mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge pull request #1679 from DSpace/rest7
Merge the Rest7 branch back to the master
This commit is contained in:
@@ -9,7 +9,6 @@ jdk:
|
||||
# DS-3384 Oracle JDK 8 has DocLint enabled by default.
|
||||
# Let's use this to catch any newly introduced DocLint issues.
|
||||
- oraclejdk8
|
||||
- oraclejdk7
|
||||
|
||||
## Should we run into any problems with oraclejdk8 on Travis, we may try the following workaround.
|
||||
## https://docs.travis-ci.com/user/languages/java#Testing-Against-Multiple-JDKs
|
||||
|
@@ -434,10 +434,6 @@
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-scratchpad</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>rome</groupId>
|
||||
<artifactId>rome</artifactId>
|
||||
|
@@ -95,6 +95,12 @@ public class BitstreamServiceImpl extends DSpaceObjectServiceImpl<Bitstream> imp
|
||||
return bitstreamDAO.findAll(context, Bitstream.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Bitstream> findAll(Context context, int limit, int offset) throws SQLException
|
||||
{
|
||||
return bitstreamDAO.findAll(context, limit, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitstream create(Context context, InputStream is) throws IOException, SQLException {
|
||||
// Store the bits
|
||||
|
@@ -147,7 +147,7 @@ public abstract class DSpaceObject implements Serializable, ReloadableEntity<jav
|
||||
return handles;
|
||||
}
|
||||
|
||||
protected List<MetadataValue> getMetadata() {
|
||||
public List<MetadataValue> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
|
@@ -200,6 +200,11 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
return itemDAO.findAll(context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findAll(Context context, Integer limit, Integer offset) throws SQLException {
|
||||
return itemDAO.findAll(context, true, limit, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findAllUnfiltered(Context context) throws SQLException {
|
||||
return itemDAO.findAll(context, true, true);
|
||||
|
@@ -26,6 +26,8 @@ import java.util.List;
|
||||
*/
|
||||
public interface BitstreamDAO extends DSpaceObjectLegacySupportDAO<Bitstream> {
|
||||
|
||||
public Iterator<Bitstream> findAll(Context context, int limit, int offset) throws SQLException;
|
||||
|
||||
public List<Bitstream> findDeletedBitstreams(Context context) throws SQLException;
|
||||
|
||||
public List<Bitstream> findDuplicateInternalIdentifier(Context context, Bitstream bitstream) throws SQLException;
|
||||
|
@@ -30,6 +30,8 @@ public interface ItemDAO extends DSpaceObjectLegacySupportDAO<Item>
|
||||
{
|
||||
public Iterator<Item> findAll(Context context, boolean archived) throws SQLException;
|
||||
|
||||
public Iterator<Item> findAll(Context context, boolean archived, int limit, int offset) throws SQLException;
|
||||
|
||||
public Iterator<Item> findAll(Context context, boolean archived, boolean withdrawn) throws SQLException;
|
||||
|
||||
/**
|
||||
|
@@ -153,4 +153,12 @@ public class BitstreamDAOImpl extends AbstractHibernateDSODAO<Bitstream> impleme
|
||||
" and bit.id not in (select col.logo.id from Collection col)" +
|
||||
" and bit.id not in (select bun.primaryBitstream.id from Bundle bun)"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Bitstream> findAll(Context context, int limit, int offset) throws SQLException {
|
||||
Query query = createQuery(context, "select b FROM Bitstream b");
|
||||
query.setFirstResult(offset);
|
||||
query.setMaxResults(limit);
|
||||
return iterate(query);
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,16 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
|
||||
return iterate(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findAll(Context context, boolean archived, int limit, int offset) throws SQLException {
|
||||
Query query = createQuery(context, "FROM Item WHERE inArchive= :in_archive");
|
||||
query.setParameter("in_archive", archived);
|
||||
query.setFirstResult(offset);
|
||||
query.setMaxResults(limit);
|
||||
return iterate(query);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findAll(Context context, boolean archived, boolean withdrawn) throws SQLException {
|
||||
Query query = createQuery(context, "FROM Item WHERE inArchive= :in_archive or withdrawn = :withdrawn");
|
||||
|
@@ -27,6 +27,8 @@ public interface BitstreamService extends DSpaceObjectService<Bitstream>, DSpace
|
||||
|
||||
public List<Bitstream> findAll(Context context) throws SQLException;
|
||||
|
||||
public Iterator<Bitstream> findAll(Context context, int limit, int offset) throws SQLException;
|
||||
|
||||
/**
|
||||
* Create a new bitstream, with a new ID. The checksum and file size are
|
||||
* calculated. No authorization checks are made in this method.
|
||||
|
@@ -69,6 +69,18 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
|
||||
*/
|
||||
public Iterator<Item> findAll(Context context) throws SQLException;
|
||||
|
||||
/**
|
||||
* Get all the items in the archive. Only items with the "in archive" flag
|
||||
* set are included. The order of the list is indeterminate.
|
||||
*
|
||||
* @param context DSpace context object
|
||||
* @param limit limit
|
||||
* @param offset offset
|
||||
* @return an iterator over the items in the archive.
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
public Iterator<Item> findAll(Context context, Integer limit, Integer offset) throws SQLException;
|
||||
|
||||
/**
|
||||
* Get all "final" items in the archive, both archived ("in archive" flag) or
|
||||
* withdrawn items are included. The order of the list is indeterminate.
|
||||
|
@@ -142,7 +142,8 @@ public class Context
|
||||
if(dbConnection == null)
|
||||
{
|
||||
// Obtain a non-auto-committing connection
|
||||
dbConnection = new DSpace().getSingletonService(DBConnection.class);
|
||||
dbConnection = new DSpace().getServiceManager()
|
||||
.getServiceByName(null, DBConnection.class);
|
||||
if(dbConnection == null)
|
||||
{
|
||||
log.fatal("Cannot obtain the bean which provides a database connection. " +
|
||||
|
@@ -7,7 +7,13 @@
|
||||
*/
|
||||
package org.dspace.core;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.dspace.storage.rdbms.DatabaseConfigVO;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
@@ -15,15 +21,10 @@ import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.proxy.HibernateProxyHelper;
|
||||
import org.hibernate.resource.transaction.spi.TransactionStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.orm.hibernate4.SessionFactoryUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import org.springframework.orm.hibernate5.SessionFactoryUtils;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the DBConnection
|
||||
@@ -35,7 +36,7 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
||||
@Autowired(required = true)
|
||||
@Qualifier("sessionFactory")
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
private boolean batchModeEnabled = false;
|
||||
|
||||
@Override
|
||||
@@ -50,7 +51,7 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
||||
@Override
|
||||
public boolean isTransActionAlive() {
|
||||
Transaction transaction = getTransaction();
|
||||
return transaction != null && transaction.isActive();
|
||||
return transaction != null && transaction.getStatus().isOneOf(TransactionStatus.ACTIVE);
|
||||
}
|
||||
|
||||
protected Transaction getTransaction() {
|
||||
@@ -59,7 +60,7 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
||||
|
||||
@Override
|
||||
public boolean isSessionAlive() {
|
||||
return sessionFactory.getCurrentSession() != null && sessionFactory.getCurrentSession().getTransaction() != null && sessionFactory.getCurrentSession().getTransaction().isActive();
|
||||
return sessionFactory.getCurrentSession() != null && sessionFactory.getCurrentSession().getTransaction() != null && sessionFactory.getCurrentSession().getTransaction().getStatus().isOneOf(TransactionStatus.ACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,7 +80,7 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
||||
|
||||
@Override
|
||||
public void commit() throws SQLException {
|
||||
if(isTransActionAlive() && !getTransaction().wasRolledBack())
|
||||
if(isTransActionAlive() && !getTransaction().getStatus().isOneOf(TransactionStatus.MARKED_ROLLBACK, TransactionStatus.ROLLING_BACK))
|
||||
{
|
||||
getSession().flush();
|
||||
getTransaction().commit();
|
||||
|
@@ -10,22 +10,23 @@ package org.dspace.handle.dao.impl;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.AbstractHibernateDAO;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.handle.Handle;
|
||||
import org.dspace.handle.dao.HandleDAO;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
import org.hibernate.service.jdbc.dialect.internal.StandardDialectResolver;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the Database Access Object interface class for the Handle object.
|
||||
@@ -123,7 +124,7 @@ public class HandleDAOImpl extends AbstractHibernateDAO<Handle> implements Handl
|
||||
|
||||
// Determine what dialect we are using for this DB
|
||||
DialectResolver dialectResolver = new StandardDialectResolver();
|
||||
Dialect dialect = dialectResolver.resolveDialect(connection.getMetaData());
|
||||
Dialect dialect = dialectResolver.resolveDialect(new DatabaseMetaDataDialectResolutionInfoAdapter(connection.getMetaData()));
|
||||
|
||||
// Find the next value in our sequence (based on DB dialect)
|
||||
try (PreparedStatement preparedStatement = connection.prepareStatement(dialect.getSequenceNextValString(HANDLE_SEQUENCE)))
|
||||
|
@@ -7,15 +7,14 @@
|
||||
*/
|
||||
package org.dspace.storage.rdbms.hibernate.postgres;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQL82Dialect;
|
||||
import org.hibernate.metamodel.spi.TypeContributions;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
import org.hibernate.type.descriptor.sql.LongVarcharTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* UUID's are not supported by default in hibernate due to differences in the database in order to fix this a custom sql dialect is needed.
|
||||
* Source: https://forum.hibernate.org/viewtopic.php?f=1&t=1014157
|
||||
@@ -25,7 +24,7 @@ import java.sql.Types;
|
||||
public class DSpacePostgreSQL82Dialect extends PostgreSQL82Dialect
|
||||
{
|
||||
@Override
|
||||
public void contributeTypes(final TypeContributions typeContributions, final ServiceRegistry serviceRegistry) {
|
||||
public void contributeTypes(final org.hibernate.boot.model.TypeContributions typeContributions, final ServiceRegistry serviceRegistry) {
|
||||
super.contributeTypes(typeContributions, serviceRegistry);
|
||||
typeContributions.contributeType(new InternalPostgresUUIDType());
|
||||
}
|
||||
|
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for the Checksum Checker tool, which looks for unexpected alterations
|
||||
* in Bitstream content.
|
||||
*/
|
||||
package org.dspace.checker.dao.impl;
|
@@ -100,7 +100,7 @@
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<version>2.6.11</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- for filters -->
|
||||
@@ -165,6 +165,11 @@
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<developers>
|
||||
|
@@ -61,4 +61,8 @@ public final class DSpaceBeanPostProcessor implements BeanPostProcessor, Destruc
|
||||
DSpaceServiceManager.shutdownService(bean);
|
||||
}
|
||||
|
||||
// @Override
|
||||
public boolean requiresDestruction(Object arg0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ package org.dspace.utils.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Priority;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
@@ -31,6 +32,7 @@ import org.dspace.services.RequestService;
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
@Priority(1)
|
||||
public final class DSpaceWebappServletFilter implements Filter {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@@ -49,6 +49,7 @@
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="shared" value="true"/>
|
||||
</bean>
|
||||
<!-- CACHING end beans -->
|
||||
|
||||
@@ -70,4 +71,4 @@
|
||||
<!-- DSpaceServicesFactory (for easy access to above core services) -->
|
||||
<bean id="dSpaceServicesFactory" class="org.dspace.services.factory.DSpaceServicesFactoryImpl"/>
|
||||
|
||||
</beans>
|
||||
</beans>
|
||||
|
43
dspace-spring-rest/README.md
Normal file
43
dspace-spring-rest/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# DSpace7 REST Webapp
|
||||
> This is the new REST webapp for DSpace 7 build with Spring MVC + HATEOAS with a focus on the [JSON HAL format](http://stateless.co/hal_specification.html) ([formal specification](https://tools.ietf.org/html/draft-kelly-json-hal-08))
|
||||
|
||||
This webapp uses the following technologies:
|
||||
- [Spring Boot](https://projects.spring.io/spring-boot/)
|
||||
- [Spring MVC](https://spring.io/guides/gs/rest-service/)
|
||||
- [Spring HATEOAS](http://projects.spring.io/spring-hateoas/)
|
||||
|
||||
*Please note that we don't use Spring Data REST* but we mimic as much as possible its architecture and behaviour.
|
||||
We don't use Spring Data REST as we haven't a spring data layer and we want to provide clear separation between the persistence representation and the REST representation
|
||||
|
||||
## How to contribute
|
||||
Check the infomation available on the DSpace Official Wiki page for the [DSpace 7 Working Group](https://wiki.duraspace.org/display/DSPACE/DSpace+7+UI+Working+Group)
|
||||
|
||||
[DSpace 7 REST: Coding DSpace Objects](https://wiki.duraspace.org/display/DSPACE/DSpace+7+REST%3A+Coding+DSpace+Objects)
|
||||
|
||||
## How to run
|
||||
The only tested way right now is to run this webapp inside your IDE (Eclipse). Just create a new Tomcat 8 server and deploy the dspace-spring-rest maven module to it.
|
||||
> The *dspace.dir* is configured in the *dspace-spring-rest/src/main/resources/application.properties* file
|
||||
[currently](src/main/resources/application.properties#L25)
|
||||
|
||||
> dspace.dir = d:/install/dspace7
|
||||
|
||||
## HAL Browser
|
||||
The modified version of the HAL Browser from the Spring Data REST project is included, the index.html file is overriden locally to support the /api baseURL (see [DATAREST-971](https://jira.spring.io/browse/DATAREST-971))
|
||||
|
||||
## Packages and main classes
|
||||
*[org.dspace.app.rest.Application](src/main/java/org/dspace/app/rest/Application.java)* is the spring boot main class it initializes
|
||||
- the DSpace kernel
|
||||
- the dspaceContextListener
|
||||
- the DSpaceWebappServletFilter
|
||||
- the dspaceRequestContextFilter
|
||||
- a custom HAL RelProvider for dspace
|
||||
|
||||
*[org.dspace.app.rest.RestResourceController](src/main/java/org/dspace/app/rest/RestResourceController.java)* is the controller responsible to handle all the REST requests (so far) delegating the execution to the right repository depending on the requested resource (REST entity)
|
||||
|
||||
*[org.dspace.app.rest.model](src/main/java/org/dspace/app/rest/model)* is the package where to put all the classes representing DSpace REST resource. The classes should be named with the name of the DSpace perstent class mainly exposed + the Rest suffix (i.e. ItemRest, CollectionRest, etc.)
|
||||
|
||||
*[org.dspace.app.rest.model.hateoas](src/main/java/org/dspace/app/rest/model/hateoas)* contains the classes specific of the HAL implementation. The most important class is org.dspace.app.rest.model.hateoas.DSpaceResource<T> that wrap a DSpaceRest object adding the support for the links and embedded resources
|
||||
|
||||
*[org.dspace.app.rest.repository](src/main/java/org/dspace/app/rest/repository)* contains the implementation of the Repository Design pattern for the Rest Objects
|
||||
|
||||
*[org.dspace.app.rest.converter](src/main/java/org/dspace/app/rest/converter)* contains the converters from/to DSpace persistent entities (Item, Collection, etc.) to their equivalent REST object (ItemRest, CollectionRest, etc.)
|
143
dspace-spring-rest/pom.xml
Normal file
143
dspace-spring-rest/pom.xml
Normal file
@@ -0,0 +1,143 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-spring-rest</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>DSpace Spring Rest (Boot MVC + HATEOAS)</name>
|
||||
<description>
|
||||
DSpace new Rest API
|
||||
</description>
|
||||
|
||||
<!--
|
||||
A Parent POM that Maven inherits DSpace Default
|
||||
POM attributes from.
|
||||
-->
|
||||
<parent>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-parent</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<!-- This is the path to the root [dspace-src] directory. -->
|
||||
<root.basedir>${basedir}/..</root.basedir>
|
||||
|
||||
<!-- Default resource delimiter for Spring Boot, so it doesn't clash with Spring ${} placeholders-->
|
||||
<resource.delimiter>@</resource.delimiter>
|
||||
<!-- Define our starting class for our Spring Boot Application -->
|
||||
<start-class>org.dspace.app.rest.Application</start-class>
|
||||
<spring-boot.version>1.4.4.RELEASE</spring-boot.version>
|
||||
<json-path.version>2.2.0</json-path.version>
|
||||
<!-- <springdata.commons>1.13.0.RELEASE</springdata.commons> -->
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- These next two dependencies build a WAR that is BOTH executable
|
||||
AND deployable into an external container (Tomcat).
|
||||
See: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-maven-packaging -->
|
||||
<!-- NOTE: For rapid development (if you don't need Solr or other webapps),
|
||||
you can temporarily comment these out, and switch <packaging> to "jar".
|
||||
This lets you develop in a standalone, runnable JAR application. -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>-->
|
||||
<!-- Ensure embedded servlet container doesn't interfere when this
|
||||
WAR is deployed to an external Tomcat (i.e. provided). -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${json-path.version}</version>
|
||||
</dependency> -->
|
||||
|
||||
<!-- The HAL Browser -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-rest-hal-browser</artifactId>
|
||||
<version>2.5.6.RELEASE</version>
|
||||
<!-- if you get a java.util.zip.ZipException: invalid LOC header (bad signature)
|
||||
during the tomcat startup force the use of the previous version as the jar file
|
||||
looks corrupted in the maven repository -->
|
||||
<!-- <version>2.5.5.RELEASE</version> -->
|
||||
</dependency>
|
||||
|
||||
<!-- Add in Spring Security for AuthN and AuthZ -->
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency> -->
|
||||
|
||||
<!-- Add in log4j support by excluding default logging, and using starter-log4j -->
|
||||
<!-- See: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html#howto-configure-log4j-for-logging -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j</artifactId>
|
||||
</dependency>-->
|
||||
|
||||
<!-- DSpace dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-api</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-services</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons Collections 4.1 (used for MultiValuedMap to store metadata values for views) -->
|
||||
<!-- NOTE: Currently DSpace API / Services still used 3.2 and may need upgrading at some point -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.dspace.app.rest.filter.DSpaceRequestContextFilter;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceRelProvider;
|
||||
import org.dspace.app.rest.utils.ApplicationConfig;
|
||||
import org.dspace.app.util.DSpaceContextListener;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
import org.dspace.servicemanager.DSpaceKernelInit;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.utils.servlet.DSpaceWebappServletFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.hateoas.RelProvider;
|
||||
|
||||
/**
|
||||
* Define the Spring Boot Application settings itself. This class takes the place
|
||||
* of a web.xml file, and configures all Filters/Listeners as methods (see below).
|
||||
* <P>
|
||||
* NOTE: Requires a Servlet 3.0 container, e.g. Tomcat 7.0 or above.
|
||||
* <p>
|
||||
* NOTE: This extends SpringBootServletInitializer in order to allow us to build
|
||||
* a deployable WAR file with Spring Boot. See:
|
||||
* http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
* @author Tim Donohue
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class Application extends SpringBootServletInitializer
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(Application.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationConfig configuration;
|
||||
|
||||
/**
|
||||
* Override the default SpringBootServletInitializer.configure() method,
|
||||
* passing it this Application class.
|
||||
* <P>
|
||||
* This is necessary to allow us to build a deployable WAR, rather than
|
||||
* always relying on embedded Tomcat.
|
||||
* <P>
|
||||
* See: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file
|
||||
* @param application
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(Application.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletContextInitializer contextInitializer() {
|
||||
return new ServletContextInitializer() {
|
||||
|
||||
private transient DSpaceKernelImpl kernelImpl;
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext)
|
||||
throws ServletException {
|
||||
servletContext.setInitParameter("dspace.dir",configuration.getDspaceHome());
|
||||
|
||||
// start the kernel when the webapp starts
|
||||
try {
|
||||
this.kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||
if (! this.kernelImpl.isRunning()) {
|
||||
this.kernelImpl.start(getProvidedHome(configuration.getDspaceHome())); // init the kernel
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// failed to start so destroy it and log and throw an exception
|
||||
try {
|
||||
this.kernelImpl.destroy();
|
||||
} catch (Exception e1) {
|
||||
// nothing
|
||||
}
|
||||
String message = "Failure during filter init: " + e.getMessage();
|
||||
System.err.println(message + ":" + e);
|
||||
throw new RuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find DSpace's "home" directory.
|
||||
* Initially look for JNDI Resource called "java:/comp/env/dspace.dir".
|
||||
* If not found, look for "dspace.dir" initial context parameter.
|
||||
*/
|
||||
private String getProvidedHome(String dspaceHome){
|
||||
String providedHome = null;
|
||||
try {
|
||||
Context ctx = new InitialContext();
|
||||
providedHome = (String) ctx.lookup("java:/comp/env/" + DSpaceConfigurationService.DSPACE_HOME);
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if (providedHome == null)
|
||||
{
|
||||
if(dspaceHome != null && !dspaceHome.equals("") &&
|
||||
!dspaceHome.equals("${" + DSpaceConfigurationService.DSPACE_HOME + "}")){
|
||||
File test = new File(dspaceHome);
|
||||
if(test.exists() && new File(test,DSpaceConfigurationService.DSPACE_CONFIG_PATH).exists()) {
|
||||
providedHome = dspaceHome;
|
||||
}
|
||||
}
|
||||
}
|
||||
return providedHome;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the "DSpaceContextListener" so that it is loaded
|
||||
* for this Application.
|
||||
* @return DSpaceContextListener
|
||||
*/
|
||||
@Bean
|
||||
@Order(2)
|
||||
protected DSpaceContextListener dspaceContextListener() {
|
||||
// This listener initializes the DSpace Context object
|
||||
// (and loads all DSpace configs)
|
||||
return new DSpaceContextListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the DSpaceWebappServletFilter, which initializes the
|
||||
* DSpace RequestService / SessionService
|
||||
*
|
||||
* @return DSpaceWebappServletFilter
|
||||
*/
|
||||
@Bean
|
||||
@Order(1)
|
||||
protected Filter dspaceWebappServletFilter() {
|
||||
return new DSpaceWebappServletFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the DSpaceRequestContextFilter, a Filter which checks for open
|
||||
* Context objects *after* a request has been fully processed, and closes them
|
||||
*
|
||||
* @return DSpaceRequestContextFilter
|
||||
*/
|
||||
@Bean
|
||||
@Order(2)
|
||||
protected Filter dspaceRequestContextFilter() {
|
||||
return new DSpaceRequestContextFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected RelProvider dspaceRelProvider() {
|
||||
return new DSpaceRelProvider();
|
||||
}
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* A Service able to list all the discoverable endpoints in our REST
|
||||
* application. Endpoints need to register their managed endpoints. The service
|
||||
* is responsible to check conflict and priorities
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
* @author Tim Donohue
|
||||
*/
|
||||
@Service
|
||||
public class DiscoverableEndpointsService {
|
||||
/**
|
||||
* Contains all the registeredEndpoints as received by the single controller
|
||||
*/
|
||||
private Map<Object, List<Link>> registeredEndpoints = new HashMap<Object, List<Link>>();
|
||||
|
||||
/**
|
||||
* Is the computed list of discoverableEndpoints valid?
|
||||
*/
|
||||
private boolean initialized = false;
|
||||
|
||||
private List<Link> discoverableEndpoints = new ArrayList<Link>();
|
||||
|
||||
public void register(Object controller, List<Link> links) {
|
||||
synchronized (this) {
|
||||
initialized = false;
|
||||
registeredEndpoints.put(controller, links);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(Object controller) {
|
||||
synchronized (this) {
|
||||
initialized = false;
|
||||
registeredEndpoints.remove(controller);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Link> getDiscoverableEndpoints() {
|
||||
synchronized (this) {
|
||||
if (initialized)
|
||||
return discoverableEndpoints;
|
||||
|
||||
discoverableEndpoints.clear();
|
||||
Set<String> rels = new HashSet<String>();
|
||||
for (Entry<Object, List<Link>> controller : registeredEndpoints.entrySet()) {
|
||||
for (Link link : controller.getValue()) {
|
||||
if (isLinkValid(controller.getKey(), link.getHref())) {
|
||||
discoverableEndpoints.add(link);
|
||||
// sanity check
|
||||
// FIXME improve logging for debugging
|
||||
if (rels.contains(link.getRel())) {
|
||||
throw new IllegalStateException("The rel " + link.getRel() + " is defined multiple times!");
|
||||
}
|
||||
rels.add(link.getRel());
|
||||
}
|
||||
}
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
return discoverableEndpoints;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLinkValid(Object controller, String href) {
|
||||
// FIXME we need to implement a check to be sure that there are no other
|
||||
// controller with an highter precedence mapped on the same URL (this
|
||||
// could be used to override default implementation)
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.atteo.evo.inflector.English;
|
||||
import org.dspace.app.rest.exception.PaginationException;
|
||||
import org.dspace.app.rest.exception.RepositoryNotFoundException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.data.web.PagedResourcesAssembler;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.PagedResources;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.core.EvoInflectorRelProvider;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* This is the main entry point of the new REST API. Its responsibility is to
|
||||
* provide a consistent behaviors for all the exposed resources in terms of
|
||||
* returned HTTP codes, endpoint URLs, HTTP verbs to methods translation, etc.
|
||||
* It delegates to the repository the business logic
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/core/{model}")
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class RestResourceController implements InitializingBean {
|
||||
@Autowired
|
||||
DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@Autowired
|
||||
Utils utils;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
List<Link> links = new ArrayList<Link>();
|
||||
for (String r : utils.getRepositories()) {
|
||||
// this doesn't work as we don't have an active http request
|
||||
// see https://github.com/spring-projects/spring-hateoas/issues/408
|
||||
// Link l = linkTo(this.getClass(), r).withRel(r);
|
||||
String plural = English.plural(r);
|
||||
Link l = new Link("/api/core/" + plural, plural);
|
||||
links.add(l);
|
||||
System.out.println(l.getRel() + " " + l.getHref());
|
||||
}
|
||||
discoverableEndpointsService.register(this, links);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{id:\\d+}")
|
||||
@SuppressWarnings("unchecked")
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String model, @PathVariable Integer id, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(model, id, projection);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}")
|
||||
@SuppressWarnings("unchecked")
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String model, @PathVariable UUID uuid, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(model, uuid, projection);
|
||||
}
|
||||
|
||||
private <ID extends Serializable> DSpaceResource<RestModel> findOneInternal(String model, ID id, String projection) {
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(model);
|
||||
RestModel modelObject = null;
|
||||
try {
|
||||
modelObject = repository.findOne(id);
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
if (modelObject == null) {
|
||||
throw new ResourceNotFoundException(model + " with id: " + id + " not found");
|
||||
}
|
||||
DSpaceResource result = repository.wrapResource(modelObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{id:\\d+}/{rel}")
|
||||
ResourceSupport findRel(@PathVariable String model, @PathVariable Integer id, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(model, id, rel, projection);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}/{rel}")
|
||||
ResourceSupport findRel(@PathVariable String model, @PathVariable UUID uuid, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(model, uuid, rel, projection);
|
||||
}
|
||||
|
||||
private <ID extends Serializable> ResourceSupport findRelInternal(String model, ID uuid, String rel, String projection) {
|
||||
// FIXME this is a very bad implementation as it leads most of times to
|
||||
// more round-trip on the database and retrieval of unneeded infromation
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(model);
|
||||
RestModel modelObject = repository.findOne(uuid);
|
||||
DSpaceResource result = repository.wrapResource(modelObject, rel);
|
||||
if (result.getLink(rel) == null) {
|
||||
//TODO create a custom exception
|
||||
throw new ResourceNotFoundException(rel + "undefined for "+ model);
|
||||
}
|
||||
|
||||
ResourceSupport resu = (ResourceSupport) result.getEmbedded().get(rel);
|
||||
return resu;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@SuppressWarnings("unchecked")
|
||||
<T extends RestModel> PagedResources<DSpaceResource<T>> findAll(@PathVariable String model, Pageable page, PagedResourcesAssembler assembler, @RequestParam(required=false) String projection) {
|
||||
DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(model);
|
||||
// Link link = entityLinks.linkFor(getResourceClass(model), model, page).withSelfRel();
|
||||
Link link = linkTo(this.getClass(), model).withSelfRel();
|
||||
|
||||
Page<DSpaceResource<T>> resources;
|
||||
try {
|
||||
resources = repository.findAll(page).map(repository::wrapResource);
|
||||
// resources.forEach(r -> {
|
||||
// Link linkToSingleResource = Utils.linkToSingleResource(r, Link.REL_SELF);
|
||||
// r.add(linkToSingleResource);
|
||||
// });
|
||||
} catch (PaginationException pe) {
|
||||
resources = new PageImpl<DSpaceResource<T>>(new ArrayList<DSpaceResource<T>>(), page, pe.getTotal());
|
||||
}
|
||||
PagedResources<DSpaceResource<T>> result = assembler.toResource(resources, link);
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* This is the main entry point of the new REST API. Its responsibility is to
|
||||
* provide a consistent behaviors for all the exposed resources in terms of
|
||||
* returned HTTP codes, endpoint URLs, HTTP verbs to methods translation, etc.
|
||||
* It delegates to the repository the business logic
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class RootRestResourceController {
|
||||
@Autowired
|
||||
DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
ResourceSupport listDefinedEndpoint(HttpServletRequest request) {
|
||||
ResourceSupport root = new ResourceSupport();
|
||||
for (Link l : discoverableEndpointsService.getDiscoverableEndpoints()) {
|
||||
root.add(new Link(request.getContextPath() + l.getHref(), l.getRel()));
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.model.BitstreamFormatRest;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CheckSumRest;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* This is the converter from/to the Bitstream in the DSpace API data model and the REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class BitstreamConverter
|
||||
extends DSpaceObjectConverter<org.dspace.content.Bitstream, org.dspace.app.rest.model.BitstreamRest> {
|
||||
@Autowired(required = true)
|
||||
BitstreamFormatConverter bfConverter;
|
||||
|
||||
@Override
|
||||
public org.dspace.content.Bitstream toModel(org.dspace.app.rest.model.BitstreamRest obj) {
|
||||
return super.toModel(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitstreamRest fromModel(org.dspace.content.Bitstream obj) {
|
||||
BitstreamRest b = super.fromModel(obj);
|
||||
List<Bundle> bundles = null;
|
||||
try {
|
||||
bundles = obj.getBundles();
|
||||
} catch (SQLException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
if (bundles != null && bundles.size() > 0) {
|
||||
b.setBundleName(bundles.get(0).getName());
|
||||
}
|
||||
CheckSumRest checksum = new CheckSumRest();
|
||||
checksum.setCheckSumAlgorithm(obj.getChecksumAlgorithm());
|
||||
checksum.setValue(obj.getChecksum());
|
||||
b.setCheckSum(checksum);
|
||||
BitstreamFormatRest format = null;
|
||||
try {
|
||||
format = bfConverter.fromModel(obj.getFormat(null));
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
b.setFormat(format);
|
||||
b.setSizeBytes(obj.getSize());
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitstreamRest newInstance() {
|
||||
return new BitstreamRest();
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.dspace.app.rest.model.BitstreamFormatRest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the converter from/to the BitstreamFormat in the DSpace API data model and
|
||||
* the REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
public class BitstreamFormatConverter extends DSpaceConverter<org.dspace.content.BitstreamFormat, BitstreamFormatRest> {
|
||||
@Override
|
||||
public BitstreamFormatRest fromModel(org.dspace.content.BitstreamFormat obj) {
|
||||
BitstreamFormatRest bf = new BitstreamFormatRest();
|
||||
bf.setDescription(obj.getDescription());
|
||||
bf.setExtensions(bf.getExtensions());
|
||||
bf.setId(obj.getID());
|
||||
bf.setMimetype(obj.getMIMEType());
|
||||
bf.setShortDescription(obj.getShortDescription());
|
||||
bf.setInternal(obj.isInternal());
|
||||
return bf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.dspace.content.BitstreamFormat toModel(BitstreamFormatRest obj) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the converter from/to the Collection in the DSpace API data model and
|
||||
* the REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CollectionConverter
|
||||
extends DSpaceObjectConverter<org.dspace.content.Collection, org.dspace.app.rest.model.CollectionRest> {
|
||||
@Override
|
||||
public org.dspace.content.Collection toModel(org.dspace.app.rest.model.CollectionRest obj) {
|
||||
return (org.dspace.content.Collection) super.toModel(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRest fromModel(org.dspace.content.Collection obj) {
|
||||
return (CollectionRest) super.fromModel(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CollectionRest newInstance() {
|
||||
return new CollectionRest();
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the converter from/to the community in the DSpace API data model and
|
||||
* the REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CommunityConverter
|
||||
extends DSpaceObjectConverter<org.dspace.content.Community, org.dspace.app.rest.model.CommunityRest> {
|
||||
@Override
|
||||
public org.dspace.content.Community toModel(org.dspace.app.rest.model.CommunityRest obj) {
|
||||
return (org.dspace.content.Community) super.toModel(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityRest fromModel(org.dspace.content.Community obj) {
|
||||
return (CommunityRest) super.fromModel(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommunityRest newInstance() {
|
||||
return new CommunityRest();
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
public abstract class DSpaceConverter<M, R> implements Converter<M, R> {
|
||||
@Override
|
||||
public R convert(M source) {
|
||||
return fromModel(source);
|
||||
}
|
||||
|
||||
public abstract R fromModel(M obj);
|
||||
|
||||
public abstract M toModel(R obj);
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.model.MetadataEntryRest;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
/**
|
||||
*
|
||||
* This is the base converter from/to objects in the DSpace API data model and
|
||||
* the REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
* @param <M>
|
||||
* the Class in the DSpace API data model
|
||||
* @param <R>
|
||||
* the Class in the DSpace REST data model
|
||||
*/
|
||||
public abstract class DSpaceObjectConverter<M extends DSpaceObject, R extends org.dspace.app.rest.model.DSpaceObjectRest>
|
||||
extends DSpaceConverter<M, R> {
|
||||
@Override
|
||||
public R fromModel(M obj) {
|
||||
R resource = newInstance();
|
||||
resource.setHandle(obj.getHandle());
|
||||
if (obj.getID() != null) {
|
||||
resource.setUuid(obj.getID().toString());
|
||||
}
|
||||
resource.setName(obj.getName());
|
||||
List<MetadataEntryRest> metadata = new ArrayList<MetadataEntryRest>();
|
||||
for (MetadataValue mv : obj.getMetadata()) {
|
||||
MetadataEntryRest me = new MetadataEntryRest();
|
||||
me.setKey(mv.getMetadataField().toString('.'));
|
||||
me.setValue(mv.getValue());
|
||||
me.setLanguage(mv.getLanguage());
|
||||
metadata.add(me);
|
||||
}
|
||||
resource.setMetadata(metadata);
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public M toModel(R obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract R newInstance();
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the converter from/to the Item in the DSpace API data model and the
|
||||
* REST data model
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class ItemConverter extends DSpaceObjectConverter<org.dspace.content.Item, org.dspace.app.rest.model.ItemRest> {
|
||||
@Autowired(required = true)
|
||||
private CollectionConverter collectionConverter;
|
||||
@Autowired(required = true)
|
||||
private BitstreamConverter bitstreamConverter;
|
||||
|
||||
private static final Logger log = Logger.getLogger(ItemConverter.class);
|
||||
|
||||
@Override
|
||||
public ItemRest fromModel(org.dspace.content.Item obj) {
|
||||
ItemRest item = super.fromModel(obj);
|
||||
item.setInArchive(obj.isArchived());
|
||||
item.setDiscoverable(obj.isDiscoverable());
|
||||
item.setWithdrawn(obj.isWithdrawn());
|
||||
item.setLastModified(obj.getLastModified());
|
||||
try {
|
||||
Collection c = obj.getOwningCollection();
|
||||
if (c != null) {
|
||||
item.setOwningCollection(collectionConverter.fromModel(c));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error setting owning collection for item"+item.getHandle(), e);
|
||||
}
|
||||
try {
|
||||
Collection c = obj.getTemplateItemOf();
|
||||
if (c != null) {
|
||||
item.setTemplateItemOf(collectionConverter.fromModel(c));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error setting template item of for item "+item.getHandle(), e);
|
||||
}
|
||||
List<BitstreamRest> bitstreams = new ArrayList<BitstreamRest>();
|
||||
for (Bundle bun : obj.getBundles()) {
|
||||
for (Bitstream bit : bun.getBitstreams()) {
|
||||
BitstreamRest bitrest = bitstreamConverter.fromModel(bit);
|
||||
bitstreams.add(bitrest);
|
||||
}
|
||||
}
|
||||
item.setBitstreams(bitstreams);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.dspace.content.Item toModel(ItemRest obj) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemRest newInstance() {
|
||||
return new ItemRest();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.exception;
|
||||
|
||||
/**
|
||||
* This is an exception to manage information about pagination errors.
|
||||
* Out-of-order or other invalid requests
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class PaginationException extends RuntimeException {
|
||||
long total;
|
||||
|
||||
public PaginationException(long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* This is the exception to capture details about call to inexistent resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "This endpoint is not found in the system")
|
||||
public class RepositoryNotFoundException extends RuntimeException {
|
||||
String model;
|
||||
|
||||
public RepositoryNotFoundException(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.core.Context;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A Servlet Filter whose only role is to clean up open Context objects in
|
||||
* the request. (These Context objects may have been created by Controllers
|
||||
* in order to populate Views).
|
||||
*
|
||||
* @author Tim Donohue
|
||||
* @see ContextUtil
|
||||
*/
|
||||
public class DSpaceRequestContextFilter implements Filter
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DSpaceRequestContextFilter.class);
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
Context context = null;
|
||||
try
|
||||
{
|
||||
// First, process any other servlet filters, along with the controller & view
|
||||
chain.doFilter(request, response);
|
||||
|
||||
// *After* view was processed, check for an open Context object in the ServletRequest
|
||||
// (This Context object may have been opened by a @Controller via ContextUtil.obtainContext())
|
||||
context = (Context) request.getAttribute(ContextUtil.DSPACE_CONTEXT);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Abort the context if it's still valid, thus closing any open
|
||||
// database connections
|
||||
if ((context != null) && context.isValid())
|
||||
{
|
||||
ContextUtil.abortContext(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.hateoas.Identifiable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Base class for any REST resource that need to be addressable
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
* @param <T>
|
||||
* the class of the resource identifier
|
||||
*/
|
||||
public abstract class BaseObjectRest<T extends Serializable> implements Identifiable<T>, RestModel {
|
||||
@JsonIgnore
|
||||
protected T id;
|
||||
|
||||
@Override
|
||||
public T getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(T id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* The BitstreamFormat REST Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class BitstreamFormatRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "bitstreamformat";
|
||||
|
||||
private String shortDescription;
|
||||
|
||||
private String description;
|
||||
|
||||
private String mimetype;
|
||||
|
||||
private int supportLevel;
|
||||
|
||||
private boolean internal;
|
||||
|
||||
private List<String> extensions;
|
||||
|
||||
public String getShortDescription() {
|
||||
return shortDescription;
|
||||
}
|
||||
|
||||
public void setShortDescription(String shortDescription) {
|
||||
this.shortDescription = shortDescription;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getMimetype() {
|
||||
return mimetype;
|
||||
}
|
||||
|
||||
public void setMimetype(String mimetype) {
|
||||
this.mimetype = mimetype;
|
||||
}
|
||||
|
||||
public int getSupportLevel() {
|
||||
return supportLevel;
|
||||
}
|
||||
|
||||
public void setSupportLevel(int supportLevel) {
|
||||
this.supportLevel = supportLevel;
|
||||
}
|
||||
|
||||
public boolean isInternal() {
|
||||
return internal;
|
||||
}
|
||||
|
||||
public void setInternal(boolean internal) {
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
public List<String> getExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
|
||||
public void setExtensions(List<String> extensions) {
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
|
||||
/**
|
||||
* The Bitstream REST Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
public class BitstreamRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "bitstream";
|
||||
private String bundleName;
|
||||
|
||||
// avoid to serialize this object inline as we want a full resource embedded
|
||||
// TODO extends this annotation to provide information about lazy loading
|
||||
// and projection behavior
|
||||
@JsonProperty(access = Access.WRITE_ONLY)
|
||||
private BitstreamFormatRest format;
|
||||
private Long sizeBytes;
|
||||
private CheckSumRest checkSum;
|
||||
private Integer sequenceId;
|
||||
|
||||
public String getBundleName() {
|
||||
return bundleName;
|
||||
}
|
||||
|
||||
public void setBundleName(String bundleName) {
|
||||
this.bundleName = bundleName;
|
||||
}
|
||||
|
||||
public BitstreamFormatRest getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(BitstreamFormatRest format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public Long getSizeBytes() {
|
||||
return sizeBytes;
|
||||
}
|
||||
|
||||
public void setSizeBytes(Long sizeBytes) {
|
||||
this.sizeBytes = sizeBytes;
|
||||
}
|
||||
|
||||
public CheckSumRest getCheckSum() {
|
||||
return checkSum;
|
||||
}
|
||||
|
||||
public void setCheckSum(CheckSumRest checkSum) {
|
||||
this.checkSum = checkSum;
|
||||
}
|
||||
|
||||
public Integer getSequenceId() {
|
||||
return sequenceId;
|
||||
}
|
||||
|
||||
public void setSequenceId(Integer sequenceId) {
|
||||
this.sequenceId = sequenceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
/**
|
||||
* The CheckSum REST Resource. It is not addressable directly, only used as
|
||||
* inline object in the Bitstream resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class CheckSumRest {
|
||||
String checkSumAlgorithm;
|
||||
String value;
|
||||
|
||||
public String getCheckSumAlgorithm() {
|
||||
return checkSumAlgorithm;
|
||||
}
|
||||
|
||||
public void setCheckSumAlgorithm(String checkSumAlgorithm) {
|
||||
this.checkSumAlgorithm = checkSumAlgorithm;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
/**
|
||||
* The Collection REST Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class CollectionRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "collection";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
/**
|
||||
* The Community REST Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class CommunityRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "community";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Base REST representation for all the DSpaceObjects
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public abstract class DSpaceObjectRest extends BaseObjectRest<String> {
|
||||
@JsonIgnore
|
||||
private String uuid;
|
||||
|
||||
private String name;
|
||||
private String handle;
|
||||
private String type;
|
||||
|
||||
List<MetadataEntryRest> metadata;
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public String getId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void setHandle(String handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public List<MetadataEntryRest> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(List<MetadataEntryRest> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* The Item REST Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class ItemRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "item";
|
||||
private boolean inArchive = false;
|
||||
private boolean discoverable = false;
|
||||
private boolean withdrawn = false;
|
||||
private Date lastModified = new Date();
|
||||
@JsonIgnore
|
||||
private CollectionRest owningCollection;
|
||||
@JsonIgnore
|
||||
private CollectionRest templateItemOf;
|
||||
//private EPerson submitter;
|
||||
|
||||
List<BitstreamRest> bitstreams;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
public boolean getInArchive() {
|
||||
return inArchive;
|
||||
}
|
||||
public void setInArchive(boolean inArchive) {
|
||||
this.inArchive = inArchive;
|
||||
}
|
||||
public boolean getDiscoverable() {
|
||||
return discoverable;
|
||||
}
|
||||
public void setDiscoverable(boolean discoverable) {
|
||||
this.discoverable = discoverable;
|
||||
}
|
||||
public boolean getWithdrawn() {
|
||||
return withdrawn;
|
||||
}
|
||||
public void setWithdrawn(boolean withdrawn) {
|
||||
this.withdrawn = withdrawn;
|
||||
}
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
public void setLastModified(Date lastModified){
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
public CollectionRest getOwningCollection() {
|
||||
return owningCollection;
|
||||
}
|
||||
public void setOwningCollection(CollectionRest owningCollection){
|
||||
this.owningCollection = owningCollection;
|
||||
}
|
||||
public CollectionRest getTemplateItemOf() {
|
||||
return templateItemOf;
|
||||
}
|
||||
public void setTemplateItemOf(CollectionRest templateItemOf){
|
||||
this.templateItemOf = templateItemOf;
|
||||
}
|
||||
public List<BitstreamRest> getBitstreams() {
|
||||
return bitstreams;
|
||||
}
|
||||
|
||||
public void setBitstreams(List<BitstreamRest> bitstreams) {
|
||||
this.bitstreams = bitstreams;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
/**
|
||||
* An embeddable representation of the Metadata to use in with DSpace REST
|
||||
* Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class MetadataEntryRest {
|
||||
String key;
|
||||
|
||||
String value;
|
||||
|
||||
String language;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
/**
|
||||
* Methods to implement to make a REST resource addressable
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public interface RestModel {
|
||||
public String getType();
|
||||
|
||||
public Class getController();
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.BitstreamFormatRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* BitstreamFormat Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RelNameDSpaceResource(BitstreamFormatRest.NAME)
|
||||
public class BitstreamFormatResource extends DSpaceResource<BitstreamFormatRest> {
|
||||
public BitstreamFormatResource(BitstreamFormatRest bf, Utils utils, String... rels) {
|
||||
super(bf, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Bitstream Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RelNameDSpaceResource(BitstreamRest.NAME)
|
||||
public class BitstreamResource extends DSpaceResource<BitstreamRest> {
|
||||
public BitstreamResource(BitstreamRest bs, Utils utils, String... rels) {
|
||||
super(bs, utils, rels);
|
||||
// if (bs.getFormat() != null) {
|
||||
// BitstreamFormatResource bfr = new BitstreamFormatResource(bs.getFormat());
|
||||
// this.add(new Link(bfr.getLink(Link.REL_SELF).getHref(), "bitstreamformat"));
|
||||
// }
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Item Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RelNameDSpaceResource(CollectionRest.NAME)
|
||||
public class CollectionResource extends DSpaceResource<CollectionRest> {
|
||||
public CollectionResource(CollectionRest collection, Utils utils, String... rels) {
|
||||
super(collection, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Item Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RelNameDSpaceResource(CommunityRest.NAME)
|
||||
public class CommunityResource extends DSpaceResource<CommunityRest> {
|
||||
public CommunityResource(CommunityRest community, Utils utils, String... rels) {
|
||||
super(community, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.springframework.hateoas.core.EvoInflectorRelProvider;
|
||||
|
||||
/**
|
||||
* A DSpace Relation Provider that use the RelNameDSpaceResource to use the
|
||||
* right names for the embedded collection when a DSpaceResource is requested
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class DSpaceRelProvider extends EvoInflectorRelProvider {
|
||||
|
||||
@Override
|
||||
public String getItemResourceRelFor(Class<?> type) {
|
||||
if (DSpaceResource.class.isAssignableFrom(type)) {
|
||||
return type.getAnnotation(RelNameDSpaceResource.class).value();
|
||||
}
|
||||
return super.getItemResourceRelFor(type);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
|
||||
/**
|
||||
* A base class for DSpace Rest HAL Resource. The HAL Resource wraps the REST
|
||||
* Resource adding support for the links and embedded resources. Each property
|
||||
* of the wrapped REST resource is automatically translated in a link and the
|
||||
* available information included as embedded resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public abstract class DSpaceResource<T extends RestModel> extends ResourceSupport {
|
||||
@JsonUnwrapped
|
||||
private final T data;
|
||||
|
||||
@JsonProperty(value = "_embedded")
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
private Map<String, Object> embedded = new HashMap<String, Object>();
|
||||
|
||||
public DSpaceResource(T data, Utils utils, String... rels) {
|
||||
this.data = data;
|
||||
|
||||
if (data != null) {
|
||||
try {
|
||||
for (PropertyDescriptor pd : Introspector.getBeanInfo(data.getClass()).getPropertyDescriptors()) {
|
||||
Method readMethod = pd.getReadMethod();
|
||||
if (readMethod != null && !"class".equals(pd.getName())) {
|
||||
if (RestModel.class.isAssignableFrom(readMethod.getReturnType())) {
|
||||
this.add(utils.linkToSubResource(data, pd.getName()));
|
||||
RestModel linkedObject = (RestModel) readMethod.invoke(data);
|
||||
if (linkedObject != null) {
|
||||
embedded.put(pd.getName(),
|
||||
utils.getResourceRepository(linkedObject.getType()).wrapResource(linkedObject));
|
||||
} else {
|
||||
embedded.put(pd.getName(), null);
|
||||
}
|
||||
|
||||
Method writeMethod = pd.getWriteMethod();
|
||||
writeMethod.invoke(data, new Object[] { null });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IntrospectionException | IllegalArgumentException | IllegalAccessException
|
||||
| InvocationTargetException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
this.add(utils.linkToSingleResource(data, Link.REL_SELF));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> getEmbedded() {
|
||||
return embedded;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Item Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RelNameDSpaceResource(ItemRest.NAME)
|
||||
public class ItemResource extends DSpaceResource<ItemRest> {
|
||||
public ItemResource(ItemRest item, Utils utils, String... rels) {
|
||||
super(item, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation allows to set the name to use for REST collections
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RelNameDSpaceResource {
|
||||
String value();
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.converter.BitstreamFormatConverter;
|
||||
import org.dspace.app.rest.model.BitstreamFormatRest;
|
||||
import org.dspace.app.rest.model.hateoas.BitstreamFormatResource;
|
||||
import org.dspace.content.BitstreamFormat;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage BitstreamFormat Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component(BitstreamFormatRest.NAME)
|
||||
public class BitstreamFormatRestRepository extends DSpaceRestRepository<BitstreamFormatRest, Integer> {
|
||||
BitstreamFormatService bfs = ContentServiceFactory.getInstance().getBitstreamFormatService();
|
||||
@Autowired
|
||||
BitstreamFormatConverter converter;
|
||||
|
||||
public BitstreamFormatRestRepository() {
|
||||
System.out.println("Repository initialized by Spring");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitstreamFormatRest findOne(Context context, Integer id) {
|
||||
BitstreamFormat bit = null;
|
||||
try {
|
||||
bit = bfs.find(context, id);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (bit == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.fromModel(bit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<BitstreamFormatRest> findAll(Context context, Pageable pageable) {
|
||||
List<BitstreamFormat> bit = null;
|
||||
try {
|
||||
bit = bfs.findAll(context);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
Page<BitstreamFormatRest> page = utils.getPage(bit, pageable).map(converter);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<BitstreamFormatRest> getDomainClass() {
|
||||
return BitstreamFormatRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitstreamFormatResource wrapResource(BitstreamFormatRest bs, String... rels) {
|
||||
return new BitstreamFormatResource(bs, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.hateoas.BitstreamResource;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Bitstream Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(BitstreamRest.NAME)
|
||||
public class BitstreamRestRepository extends DSpaceRestRepository<BitstreamRest, UUID> {
|
||||
BitstreamService bs = ContentServiceFactory.getInstance().getBitstreamService();
|
||||
@Autowired
|
||||
BitstreamConverter converter;
|
||||
|
||||
public BitstreamRestRepository() {
|
||||
System.out.println("Repository initialized by Spring");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitstreamRest findOne(Context context, UUID id) {
|
||||
Bitstream bit = null;
|
||||
try {
|
||||
bit = bs.find(context, id);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (bit == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.fromModel(bit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<BitstreamRest> findAll(Context context, Pageable pageable) {
|
||||
List<Bitstream> bit = new ArrayList<Bitstream>();
|
||||
Iterator<Bitstream> it = null;
|
||||
int total = 0;
|
||||
try {
|
||||
total = bs.countTotal(context);
|
||||
it = bs.findAll(context, pageable.getPageSize(), pageable.getOffset());
|
||||
while(it.hasNext()) {
|
||||
bit.add(it.next());
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
Page<BitstreamRest> page = new PageImpl<Bitstream>(bit, pageable, total).map(converter);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<BitstreamRest> getDomainClass() {
|
||||
return BitstreamRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitstreamResource wrapResource(BitstreamRest bs, String... rels) {
|
||||
return new BitstreamResource(bs, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.converter.CollectionConverter;
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.hateoas.CollectionResource;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Item Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(CollectionRest.NAME)
|
||||
public class CollectionRestRepository extends DSpaceRestRepository<CollectionRest, UUID> {
|
||||
CollectionService cs = ContentServiceFactory.getInstance().getCollectionService();
|
||||
@Autowired
|
||||
CollectionConverter converter;
|
||||
|
||||
|
||||
public CollectionRestRepository() {
|
||||
System.out.println("Repository initialized by Spring");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRest findOne(Context context, UUID id) {
|
||||
Collection collection = null;
|
||||
try {
|
||||
collection = cs.find(context, id);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (collection == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.fromModel(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CollectionRest> findAll(Context context, Pageable pageable) {
|
||||
List<Collection> it = null;
|
||||
List<Collection> collections = new ArrayList<Collection>();
|
||||
int total = 0;
|
||||
try {
|
||||
total = cs.countTotal(context);
|
||||
it = cs.findAll(context, pageable.getPageSize(), pageable.getOffset());
|
||||
for (Collection c: it) {
|
||||
collections.add(c);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
Page<CollectionRest> page = new PageImpl<Collection>(collections, pageable, total).map(converter);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<CollectionRest> getDomainClass() {
|
||||
return CollectionRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionResource wrapResource(CollectionRest collection, String... rels) {
|
||||
return new CollectionResource(collection, utils, rels);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.converter.CommunityConverter;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.hateoas.CommunityResource;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Item Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(CommunityRest.NAME)
|
||||
public class CommunityRestRepository extends DSpaceRestRepository<CommunityRest, UUID> {
|
||||
CommunityService cs = ContentServiceFactory.getInstance().getCommunityService();
|
||||
@Autowired
|
||||
CommunityConverter converter;
|
||||
|
||||
|
||||
public CommunityRestRepository() {
|
||||
System.out.println("Repository initialized by Spring");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityRest findOne(Context context, UUID id) {
|
||||
Community community = null;
|
||||
try {
|
||||
community = cs.find(context, id);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (community == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.fromModel(community);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CommunityRest> findAll(Context context, Pageable pageable) {
|
||||
List<Community> it = null;
|
||||
List<Community> communities = new ArrayList<Community>();
|
||||
int total = 0;
|
||||
try {
|
||||
total = cs.countTotal(context);
|
||||
it = cs.findAll(context, pageable.getPageSize(), pageable.getOffset());
|
||||
for (Community c: it) {
|
||||
communities.add(c);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
Page<CommunityRest> page = new PageImpl<Community>(communities, pageable, total).map(converter);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<CommunityRest> getDomainClass() {
|
||||
return CommunityRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityResource wrapResource(CommunityRest community, String... rels) {
|
||||
return new CommunityResource(community, utils, rels);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
/**
|
||||
* This is the base class for any Rest Repository. It add a DSpaceContext to the
|
||||
* normal Spring Data Repository methods signature and assure that the
|
||||
* repository is able to wrap a DSpace Rest Object in a HAL Resource
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public abstract class DSpaceRestRepository<T extends RestModel, ID extends Serializable>
|
||||
implements PagingAndSortingRepository<T, ID> {
|
||||
@Autowired
|
||||
protected Utils utils;
|
||||
|
||||
protected RequestService requestService = new DSpace().getRequestService();
|
||||
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Iterable<S> save(Iterable<S> entities) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findOne(ID id) {
|
||||
Context context = obtainContext();
|
||||
return findOne(context, id);
|
||||
}
|
||||
|
||||
public abstract T findOne(Context context, ID id);
|
||||
|
||||
@Override
|
||||
public boolean exists(ID id) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
throw new RuntimeException("findAll MUST be paginated");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(Iterable<ID> ids) {
|
||||
throw new RuntimeException("findAll MUST be paginated");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(ID id) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Iterable<? extends T> entities) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(Sort sort) {
|
||||
throw new RuntimeException("findAll MUST be paginated");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
Context context = obtainContext();
|
||||
return findAll(context, pageable);
|
||||
}
|
||||
|
||||
public abstract Page<T> findAll(Context context, Pageable pageable);
|
||||
|
||||
private Context obtainContext() {
|
||||
Request currentRequest = requestService.getCurrentRequest();
|
||||
Context context = (Context) currentRequest.getAttribute(ContextUtil.DSPACE_CONTEXT);
|
||||
if (context != null && context.isValid()) {
|
||||
return context;
|
||||
}
|
||||
context = new Context();
|
||||
currentRequest.setAttribute(ContextUtil.DSPACE_CONTEXT, context);
|
||||
return context;
|
||||
}
|
||||
|
||||
public abstract Class<T> getDomainClass();
|
||||
|
||||
public abstract DSpaceResource<T> wrapResource(T model, String... rels);
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.converter.ItemConverter;
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.hateoas.ItemResource;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Item Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(ItemRest.NAME)
|
||||
public class ItemRestRepository extends DSpaceRestRepository<ItemRest, UUID> {
|
||||
ItemService is = ContentServiceFactory.getInstance().getItemService();
|
||||
@Autowired
|
||||
ItemConverter converter;
|
||||
|
||||
|
||||
public ItemRestRepository() {
|
||||
System.out.println("Repository initialized by Spring");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRest findOne(Context context, UUID id) {
|
||||
Item item = null;
|
||||
try {
|
||||
item = is.find(context, id);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.fromModel(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ItemRest> findAll(Context context, Pageable pageable) {
|
||||
Iterator<Item> it = null;
|
||||
List<Item> items = new ArrayList<Item>();
|
||||
int total = 0;
|
||||
try {
|
||||
total = is.countTotal(context);
|
||||
it = is.findAll(context, pageable.getPageSize(), pageable.getOffset());
|
||||
while (it.hasNext()) {
|
||||
Item i = it.next();
|
||||
items.add(i);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
Page<ItemRest> page = new PageImpl<Item>(items, pageable, total).map(converter);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ItemRest> getDomainClass() {
|
||||
return ItemRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemResource wrapResource(ItemRest item, String... rels) {
|
||||
return new ItemResource(item, utils, rels);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
||||
|
||||
/**
|
||||
* This class provide extra configuration for our Spring Boot Application
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSpringDataWebSupport
|
||||
@ComponentScan({ "org.dspace.app.rest.converter", "org.dspace.app.rest.repository", "org.dspace.app.rest.utils" })
|
||||
public class ApplicationConfig {
|
||||
@Value("${dspace.dir}")
|
||||
private String dspaceHome;
|
||||
|
||||
public String getDspaceHome() {
|
||||
return dspaceHome;
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.utils;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Miscellaneous UI utility methods methods for managing DSpace context.
|
||||
*
|
||||
* This class was "adapted" from the class of the same name in old XMLUI.
|
||||
*
|
||||
* @author Tim Donohue
|
||||
*/
|
||||
public class ContextUtil
|
||||
{
|
||||
/** The log4j logger */
|
||||
private static final Logger log = Logger.getLogger(ContextUtil.class);
|
||||
|
||||
/** Where the context is stored on an HTTP Request object */
|
||||
public static final String DSPACE_CONTEXT = "dspace.context";
|
||||
|
||||
/**
|
||||
* Inspection method to check if a DSpace context has been created for this request.
|
||||
*
|
||||
* @param request
|
||||
* the servlet request object
|
||||
* @return True if a context has previously been created, false otherwise.
|
||||
*/
|
||||
public static boolean isContextAvailable(ServletRequest request) {
|
||||
Object object = request.getAttribute(DSPACE_CONTEXT);
|
||||
|
||||
if (object instanceof Context)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a new context object. If a context object has already been created
|
||||
* for this HTTP request, it is re-used, otherwise it is created.
|
||||
*
|
||||
* @param request
|
||||
* the servlet request object
|
||||
*
|
||||
* @return a context object
|
||||
*/
|
||||
public static Context obtainContext(ServletRequest request) throws SQLException
|
||||
{
|
||||
Context context = (Context) request.getAttribute(DSPACE_CONTEXT);
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
context = ContextUtil.intializeContext();
|
||||
|
||||
// Store the context in the request
|
||||
request.setAttribute(DSPACE_CONTEXT, context);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new Context object
|
||||
* @return a DSpace Context Object
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static Context intializeContext() throws SQLException
|
||||
{
|
||||
// Create a new Context
|
||||
Context context = new Context();
|
||||
|
||||
// Set the session ID
|
||||
/**context.setExtraLogInfo("session_id="
|
||||
+ request.getSession().getId());
|
||||
|
||||
AuthenticationUtil.resumeLogin(context, request);
|
||||
|
||||
// Set any special groups - invoke the authentication mgr.
|
||||
int[] groupIDs = AuthenticationManager.getSpecialGroups(context, request);
|
||||
|
||||
for (int i = 0; i < groupIDs.length; i++)
|
||||
{
|
||||
context.setSpecialGroup(groupIDs[i]);
|
||||
log.debug("Adding Special Group id="+String.valueOf(groupIDs[i]));
|
||||
}
|
||||
|
||||
// Set the session ID and IP address
|
||||
String ip = request.getRemoteAddr();
|
||||
if (useProxies == null) {
|
||||
useProxies = ConfigurationManager.getBooleanProperty("useProxies", false);
|
||||
}
|
||||
if(useProxies && request.getHeader("X-Forwarded-For") != null)
|
||||
{
|
||||
// This header is a comma delimited list
|
||||
for(String xfip : request.getHeader("X-Forwarded-For").split(","))
|
||||
{
|
||||
if(!request.getHeader("X-Forwarded-For").contains(ip))
|
||||
{
|
||||
ip = xfip.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
context.setExtraLogInfo("session_id=" + request.getSession().getId() + ":ip_addr=" + ip);
|
||||
*/
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a context exists for this request, if so complete the context.
|
||||
*
|
||||
* @param request
|
||||
* The request object
|
||||
*/
|
||||
public static void completeContext(ServletRequest request) throws ServletException
|
||||
{
|
||||
Context context = (Context) request.getAttribute(DSPACE_CONTEXT);
|
||||
|
||||
if (context != null && context.isValid())
|
||||
{
|
||||
try
|
||||
{
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void abortContext(ServletRequest request)
|
||||
{
|
||||
Context context = (Context) request.getAttribute(DSPACE_CONTEXT);
|
||||
|
||||
if (context != null && context.isValid())
|
||||
{
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.utils;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.atteo.evo.inflector.English;
|
||||
import org.dspace.app.rest.exception.PaginationException;
|
||||
import org.dspace.app.rest.exception.RepositoryNotFoundException;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Collection of utility methods
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class Utils {
|
||||
@Autowired
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
public <T> Page<T> getPage(List<T> fullContents, Pageable pageable) {
|
||||
int total = fullContents.size();
|
||||
List<T> pageContent = null;
|
||||
if (pageable.getOffset() > total) {
|
||||
throw new PaginationException(total);
|
||||
} else {
|
||||
if (pageable.getOffset() + pageable.getPageSize() > total) {
|
||||
pageContent = fullContents.subList(pageable.getOffset(), total);
|
||||
} else {
|
||||
pageContent = fullContents.subList(pageable.getOffset(), pageable.getOffset() + pageable.getPageSize());
|
||||
}
|
||||
return new PageImpl<T>(pageContent, pageable, total);
|
||||
}
|
||||
}
|
||||
|
||||
public Link linkToSingleResource(DSpaceResource r, String rel) {
|
||||
RestModel data = r.getData();
|
||||
return linkToSingleResource(data, rel);
|
||||
}
|
||||
|
||||
public Link linkToSingleResource(RestModel data, String rel) {
|
||||
return linkTo(data.getController(), data.getType()).slash(data).withRel(rel);
|
||||
}
|
||||
|
||||
public Link linkToSubResource(RestModel data, String rel) {
|
||||
return linkTo(data.getController(), data.getType()).slash(data).slash(rel).withRel(rel);
|
||||
}
|
||||
|
||||
public DSpaceRestRepository getResourceRepository(String modelPlural) {
|
||||
String model = makeSingular(modelPlural);
|
||||
try {
|
||||
return applicationContext.getBean(model, DSpaceRestRepository.class);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
throw new RepositoryNotFoundException(model);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getRepositories() {
|
||||
return applicationContext.getBeanNamesForType(DSpaceRestRepository.class);
|
||||
}
|
||||
|
||||
public static String makeSingular(String modelPlural) {
|
||||
//The old dspace res package includes the evo inflection library which has a plural() function but no singular function
|
||||
if (modelPlural.equals("communities")) {
|
||||
return CommunityRest.NAME;
|
||||
}
|
||||
return modelPlural.replaceAll("s$", "");
|
||||
}
|
||||
}
|
99
dspace-spring-rest/src/main/resources/application.properties
Normal file
99
dspace-spring-rest/src/main/resources/application.properties
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# The contents of this file are subject to the license and copyright
|
||||
# detailed in the LICENSE and NOTICE files at the root of the source
|
||||
# tree and available online at
|
||||
#
|
||||
# http://www.dspace.org/license/
|
||||
#
|
||||
|
||||
#
|
||||
# Spring Boot application.properties
|
||||
# Docs (including info on how to override these default settings)
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
|
||||
# For common settings see:
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
#
|
||||
#
|
||||
# TODO: Eventually would could think of "wiring" this up to use Commons Configuration as well
|
||||
# See, for example: http://stackoverflow.com/questions/25271537/remote-propertysource
|
||||
# and https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
|
||||
|
||||
########################
|
||||
# DSpace Settings
|
||||
#
|
||||
# DSpace installation directory
|
||||
dspace.dir=${dspace.dir}
|
||||
#dspace.dir=d:/install/dspace7
|
||||
|
||||
########################
|
||||
# Spring Boot Settings
|
||||
#
|
||||
# Testing an "application Name"
|
||||
spring.application.name = DSpace Spring Rest
|
||||
|
||||
########################
|
||||
# Spring DATA Rest settings
|
||||
#
|
||||
spring.data.rest.basePath=/api
|
||||
|
||||
########################
|
||||
# Jackson serialization settings
|
||||
#
|
||||
spring.jackson.serialization.fail-on-empty-beans=false
|
||||
|
||||
########################
|
||||
# Internationalization
|
||||
#
|
||||
# Base Path for our messages file (i18n)
|
||||
spring.messages.basename=i18n/messages
|
||||
spring.messages.encoding=UTF-8
|
||||
|
||||
###########################
|
||||
# Embedded Tomcat Settings
|
||||
#
|
||||
# Change application port (for embedded Tomcat)
|
||||
# Spring Boot app will be available at http://localhost:[server.port]/
|
||||
server.port=8080
|
||||
|
||||
# Context path where application should be made available
|
||||
# (Optional, defaults to root context)
|
||||
#server.context-path=/spring-data-rest
|
||||
|
||||
# This creates a Tomcat context-param named "dspace.dir"
|
||||
# and sets it to the value of the "dspace.dir" property (listed above)
|
||||
server.context-parameters.dspace.dir=${dspace.dir}
|
||||
|
||||
# This creates a Tomcat context-param named "dspace-config"
|
||||
# (Used by DSpaceContextListener to load the configurations)
|
||||
# This is only needed in DSpace 5 or below to initialize ConfigurationManager
|
||||
#server.context-parameters.dspace-config=${dspace.dir}/config/dspace.cfg
|
||||
|
||||
# Error handling settings
|
||||
# Always include the fullstacktrace in error pages
|
||||
# (Our Error page hides this stacktrace so it only is visible in HTML source)
|
||||
# Can be set to "never" if you don't want it.
|
||||
server.error.include-stacktrace = always
|
||||
|
||||
######################
|
||||
# Spring Boot Autoconfigure
|
||||
#
|
||||
# DISABLE a few autoconfiguration scripts, as DSpace configures these already
|
||||
# * DataSourceAutoConfiguration (DB connection / datasource)
|
||||
# * FlywayAutoConfiguration (Flyway migrations)
|
||||
#
|
||||
# TODO: If we go with Spring boot, we should investigate whether it's worth
|
||||
# re-enabling these and removing the custom DSpace initialization code
|
||||
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, \
|
||||
# org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, \
|
||||
# org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
|
||||
|
||||
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, \
|
||||
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, \
|
||||
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
|
||||
|
||||
#########################
|
||||
# Spring Boot Logging levels
|
||||
#
|
||||
#logging.level.org.springframework.boot=DEBUG
|
||||
#logging.level.org.springframework.web=DEBUG
|
||||
#logging.level.org.hibernate=ERROR
|
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# The contents of this file are subject to the license and copyright
|
||||
# detailed in the LICENSE and NOTICE files at the root of the source
|
||||
# tree and available online at
|
||||
#
|
||||
# http://www.dspace.org/license/
|
||||
#
|
||||
|
298
dspace-spring-rest/src/main/webapp/index.html
Normal file
298
dspace-spring-rest/src/main/webapp/index.html
Normal file
@@ -0,0 +1,298 @@
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>The HAL Browser (customized for Spring Data REST)</title>
|
||||
<link rel="stylesheet" media="screen" href="api/browser/vendor/css/bootstrap.css" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.sidebar-nav {
|
||||
padding: 9px 0;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" media="screen" href="api/browser/vendor/css/bootstrap-responsive.css" />
|
||||
<link rel="stylesheet" media="screen" href="api/browser/styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container-fluid">
|
||||
<a class="brand">The HAL Browser</a>
|
||||
<div class="nav-collapse">
|
||||
<ul class="nav">
|
||||
<li><a href="#/" id="entryPointLink">Go To Entry Point</a></li>
|
||||
<li><a href="https://github.com/mikekelly/hal-browser">About The HAL Browser</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="browser" class="container-fluid"></div>
|
||||
|
||||
<script id="location-bar-template" type="text/template">
|
||||
<form>
|
||||
<div class="input-append span12 location-bar-container">
|
||||
<input class="span11" id="appendedInputButton" type="text" value="<%= _.escape(url) %>">
|
||||
<button class="btn" type="submit">Go!</button>
|
||||
<span class="ajax-loader"></span>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script id="links-template" type="text/template">
|
||||
<h2>Links</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>rel</th>
|
||||
<th>title</th>
|
||||
<th>name / index</th>
|
||||
<th>docs</th>
|
||||
<th>GET</th>
|
||||
<th>NON-GET</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(links, function(obj, rel) { %>
|
||||
<% if ($.isArray(obj)) { %>
|
||||
<% _.each(obj, function(link, i) { %>
|
||||
<tr>
|
||||
<td><strong><%= HAL.truncateIfUrl(rel) %></strong></td>
|
||||
<td><%= link.title || '' %></td>
|
||||
<td><%= link.name ? 'name: ' + link.name : 'index: ' + i %></a></td>
|
||||
<td>
|
||||
<% if (HAL.isUrl(rel)) { %>
|
||||
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (link.templated === true) { %>
|
||||
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
|
||||
<% } else { %>
|
||||
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(link.href) %>" title="Perform non-GET request">!</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
<% } else { %>
|
||||
<tr>
|
||||
<td><strong><%= HAL.truncateIfUrl(rel) %></strong></td>
|
||||
<td><%= obj.title || '' %></td>
|
||||
<td><%= obj.name || '' %></td>
|
||||
<td>
|
||||
<% if (HAL.isUrl(rel)) { %>
|
||||
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (obj.templated === true) { %>
|
||||
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
|
||||
<% } else { %>
|
||||
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(obj.href) %>" title="Perform non-GET request">!</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script id="properties-template" type="text/template">
|
||||
<h2>Properties</h2>
|
||||
<pre><%= _.escape(JSON.stringify(properties, null, HAL.jsonIndent)) %></pre>
|
||||
</script>
|
||||
|
||||
<script id="request-headers-template" type="text/template">
|
||||
<h2>Custom Request Headers</h2>
|
||||
<textarea class="span12"></textarea>
|
||||
</script>
|
||||
|
||||
<script id="response-headers-template" type="text/template">
|
||||
<h2>Response Headers</h2>
|
||||
<pre><%= status.code %> <%= status.text %>
|
||||
|
||||
<% _.each(headers, function(value, name) {
|
||||
%><%= _.escape(name) %>: <%
|
||||
if(HAL.isFollowableHeader(name)) {
|
||||
%><a href="<%= HAL.normalizeUrl(value) %>" class="follow"><%
|
||||
}
|
||||
%><%= _.escape(value)
|
||||
%><% if(HAL.isFollowableHeader(name)) {
|
||||
%></a><%
|
||||
} %>
|
||||
<% }) %></pre>
|
||||
</script>
|
||||
|
||||
<script id="response-body-template" type="text/template">
|
||||
<h2>Response Body</h2>
|
||||
<pre><%= _.escape(body) %></pre>
|
||||
</script>
|
||||
|
||||
<script id="query-uri-template" type="text/template">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Expand URI Template</h3>
|
||||
</div>
|
||||
|
||||
<form id="query" action="<%= href %>">
|
||||
<div class="modal-body">
|
||||
<p>URI Template:</p>
|
||||
<pre><%- href %></pre>
|
||||
<p>Input (JSON):</p>
|
||||
<textarea><%= input %></textarea>
|
||||
<p>Expanded URI:</p>
|
||||
<pre class="preview"> </pre>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Follow URI</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
|
||||
<script id="non-safe-request-template" type="text/template">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Make a non-GET request</h3>
|
||||
</div>
|
||||
|
||||
<form class="non-safe" action="<%= href %>">
|
||||
<div class="modal-body">
|
||||
<p>Target URI</p>
|
||||
<input name="url" type="text" class="url" value="<%= href %>" />
|
||||
<p>Method:</p>
|
||||
<input name="method" type="text" class="method" value="POST" />
|
||||
<p>Headers:</p>
|
||||
<textarea name="headers" class="headers" style="height: 100px">
|
||||
Content-Type: application/json
|
||||
<%= user_defined_headers %>
|
||||
</textarea>
|
||||
<p>Body:</p>
|
||||
<textarea name="body" class="body" style="height: 200px">
|
||||
{
|
||||
|
||||
}
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Make Request</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script id="dynamic-request-template" type="text/template">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Create/Update</h3>
|
||||
</div>
|
||||
|
||||
<form class="non-safe" action="<%= href %>">
|
||||
<div class="modal-body" style="padding-top: 0px">
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<div class="well well-small" style="padding-bottom: 0px;">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="control-group">
|
||||
<label class="control-label" style="display: inline-block; font-weight: bold;">Action:</label>
|
||||
<input name="method" type="text" class="method controls" style="width: 98%" value="POST" />
|
||||
<input name="url" type="text" class="url controls" style="width: 98%" value="<%= href %>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Make Request</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
|
||||
<script id="embedded-resources-template" type="text/template">
|
||||
<h2>Embedded Resources</h2>
|
||||
</script>
|
||||
|
||||
<script id="embedded-resource-template" type="text/template">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="#"><%= resource.identifier %><% if (resource.title) { %>: <span class="embedded-resource-title"><%- resource.title %></span><% } %>
|
||||
<% if (HAL.isUrl(resource.embed_rel)) { %>
|
||||
<span class="dox pull-right" data-href="<%= HAL.normalizeUrl(HAL.buildUrl(resource.embed_rel)) %>">
|
||||
<i class="icon-book"></i>
|
||||
</span>
|
||||
<% } %>
|
||||
</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="api/browser/vendor/js/jquery-1.10.2.min.js"></script>
|
||||
<script src="api/browser/vendor/js/underscore.js"></script>
|
||||
<script src="api/browser/vendor/js/backbone.js"></script>
|
||||
<script src="api/browser/vendor/js/uritemplates.js"></script>
|
||||
<script src="api/browser/vendor/js/URI.min.js"></script>
|
||||
<script src="api/browser/vendor/js/bootstrap.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal.js"></script>
|
||||
<script src="api/browser/js/hal/browser.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/http/client.js"></script>
|
||||
<script src="api/browser/js/hal/resource.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/browser.js"></script>
|
||||
<script src="api/browser/js/hal/views/explorer.js"></script>
|
||||
<script src="api/browser/js/hal/views/inspector.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/navigation.js"></script>
|
||||
<script src="api/browser/js/hal/views/location_bar.js"></script>
|
||||
<script src="api/browser/js/hal/views/request_headers.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/resource.js"></script>
|
||||
<script src="api/browser/js/hal/views/properties.js"></script>
|
||||
<script src="api/browser/js/hal/views/links.js"></script>
|
||||
<script src="api/browser/js/hal/views/embedded_resources.js"></script>
|
||||
<script src="api/browser/js/hal/views/embedded_resource.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/non_safe_request_dialog.js"></script>
|
||||
<script src="api/browser/js/hal/views/query_uri_dialog.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/response.js"></script>
|
||||
<script src="api/browser/js/hal/views/response_headers.js"></script>
|
||||
<script src="api/browser/js/hal/views/response_body.js"></script>
|
||||
|
||||
<script src="api/browser/js/hal/views/documentation.js"></script>
|
||||
|
||||
<script src="api/browser/vendor/js/jsoneditor.js"></script>
|
||||
<script src="api/browser/js/CustomPostForm.js"></script>
|
||||
|
||||
<script>
|
||||
var browser = new HAL.Browser({
|
||||
container: $('#browser'),
|
||||
entryPoint: '/dspace-spring-rest/api'
|
||||
});
|
||||
Backbone.history.start();
|
||||
</script>
|
||||
</body>
|
@@ -22,7 +22,9 @@
|
||||
<!--Second level cache configuration-->
|
||||
<property name="hibernate.cache.use_second_level_cache">true</property>
|
||||
<property name="hibernate.cache.use_query_cache">true</property>
|
||||
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
|
||||
<property name="hibernate.cache.region.factory_class">
|
||||
org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
|
||||
</property>
|
||||
<property name="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</property>
|
||||
|
||||
|
||||
|
@@ -105,5 +105,16 @@
|
||||
<module>oai</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>dspace-spring-rest</id>
|
||||
<activation>
|
||||
<file>
|
||||
<exists>spring-rest/pom.xml</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>spring-rest</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
109
dspace/modules/spring-rest/pom.xml
Normal file
109
dspace/modules/spring-rest/pom.xml
Normal file
@@ -0,0 +1,109 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.dspace.modules</groupId>
|
||||
<artifactId>spring-rest</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>DSpace Spring Rest:: Local Customizations</name>
|
||||
<description>Overlay REST customizations.
|
||||
This is probably a temporary solution to the build problems. We like to investigate about
|
||||
the possibility to remove the overlays enable a more flexible extension mechanism.
|
||||
The use of web-fragment and spring mvc technology allow us to add request handlers
|
||||
just adding new jar in the classloader</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>modules</artifactId>
|
||||
<groupId>org.dspace</groupId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<!-- This is the path to the root [dspace-src] directory. -->
|
||||
<root.basedir>${basedir}/../../..</root.basedir>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Unpack the "additions" module into our target directory,
|
||||
so that any custom classes in that module can be included
|
||||
into this WAR's WEB-INF/classes (see maven-war-plugin below). -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.dspace.modules</includeGroupIds>
|
||||
<includeArtifactIds>additions</includeArtifactIds>
|
||||
<!--NOTE: by default this will also unpack transitive dependencies. To disable, uncomment this next line:
|
||||
<excludeTransitive>true</excludeTransitive>
|
||||
-->
|
||||
<outputDirectory>${project.build.directory}/additions</outputDirectory>
|
||||
<excludes>META-INF/**</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<archiveClasses>false</archiveClasses>
|
||||
<!-- Filter the web.xml (needed for IDE compatibility/debugging) -->
|
||||
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
|
||||
<!-- Copy any 'additions' (see m-dependency-p above) into WEB-INF/classes.
|
||||
This ensures they are loaded prior to dependencies in WEB-INF/lib
|
||||
(per Servlet 3.0 spec, section 10.5), and allows them to override
|
||||
default classes in this WAR -->
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>${project.build.directory}/additions</directory>
|
||||
<targetPath>WEB-INF/classes</targetPath>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>prepare-package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>oracle-support</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>db.name</name>
|
||||
<value>oracle</value>
|
||||
</property>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.oracle</groupId>
|
||||
<artifactId>ojdbc6</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.dspace.modules</groupId>
|
||||
<artifactId>additions</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-spring-rest</artifactId>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -668,6 +668,7 @@ Common usage:
|
||||
<fileset dir="webapps">
|
||||
<exclude name="**/web.xml" />
|
||||
<exclude name="**/robots.txt" />
|
||||
<exclude name="**/application.properties" />
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
@@ -676,6 +677,7 @@ Common usage:
|
||||
<fileset dir="webapps">
|
||||
<include name="**/web.xml" />
|
||||
<include name="**/robots.txt" />
|
||||
<include name="**/application.properties" />
|
||||
</fileset>
|
||||
<filterchain>
|
||||
<expandproperties />
|
||||
|
48
pom.xml
48
pom.xml
@@ -23,17 +23,13 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>${project.build.sourceEncoding}</project.reporting.outputEncoding>
|
||||
<java.version>1.7</java.version>
|
||||
<java.version>1.8</java.version>
|
||||
<postgresql.driver.version>9.4.1211</postgresql.driver.version>
|
||||
<solr.version>4.10.4</solr.version>
|
||||
<jena.version>2.13.0</jena.version>
|
||||
<slf4j.version>1.7.14</slf4j.version>
|
||||
<!--
|
||||
Hibernate version pinned to 4.2, 4.3 does not work with the spring version we are currently using
|
||||
Upgrading the spring version will make the XMLUI crash
|
||||
-->
|
||||
<hibernate.version>4.2.21.Final</hibernate.version>
|
||||
<spring.version>3.2.16.RELEASE</spring.version>
|
||||
<slf4j.version>1.7.22</slf4j.version>
|
||||
<hibernate.version>5.2.8.Final</hibernate.version>
|
||||
<spring.version>4.3.6.RELEASE</spring.version>
|
||||
<!-- 'root.basedir' is the path to the root [dspace-src] dir. It must be redefined by each child POM,
|
||||
as it is used to reference the LICENSE_HEADER and *.properties file(s) in that directory. -->
|
||||
<root.basedir>${basedir}</root.basedir>
|
||||
@@ -64,7 +60,7 @@
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- Make sure that we do not have conflicting dependencies-->
|
||||
<execution>
|
||||
<!-- <execution>
|
||||
<id>enforce-versions</id>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
@@ -74,7 +70,7 @@
|
||||
<DependencyConvergence />
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</execution> -->
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Used to compile all Java classes -->
|
||||
@@ -672,6 +668,18 @@
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>dspace-spring-rest</id>
|
||||
<activation>
|
||||
<file>
|
||||
<exists>dspace-spring-rest/pom.xml</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>dspace-spring-rest</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<!--
|
||||
The 'release' profile is used by the 'maven-release-plugin' (see above)
|
||||
to actually perform a DSpace software release to Maven central.
|
||||
@@ -694,6 +702,7 @@
|
||||
<module>dspace-solr</module>
|
||||
<module>dspace-sword</module>
|
||||
<module>dspace-swordv2</module>
|
||||
<module>dspace-spring-rest</module>
|
||||
</modules>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -843,6 +852,12 @@
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-spring-rest</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-solr</artifactId>
|
||||
@@ -857,7 +872,6 @@
|
||||
<type>war</type>
|
||||
<classifier>skinny</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- DSpace Localization Packages -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
@@ -1439,4 +1453,16 @@
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>stax</groupId>
|
||||
<artifactId>stax-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
Reference in New Issue
Block a user