Merge pull request #323 from peterdietz/rest-jersey

[DS-1696] DSpace REST API built in JERSEY
This commit is contained in:
Peter Dietz
2013-10-21 19:40:40 -07:00
24 changed files with 1766 additions and 34 deletions

View File

@@ -7,6 +7,27 @@
*/
package org.dspace.content;
import org.apache.log4j.Logger;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authorize.AuthorizeConfiguration;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.BrowseException;
import org.dspace.browse.IndexBrowse;
import org.dspace.browse.ItemCountException;
import org.dspace.browse.ItemCounter;
import org.dspace.core.*;
import org.dspace.eperson.Group;
import org.dspace.event.Event;
import org.dspace.handle.HandleManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.workflow.WorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
@@ -17,32 +38,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.MissingResourceException;
import org.apache.log4j.Logger;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authorize.AuthorizeConfiguration;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.BrowseException;
import org.dspace.browse.IndexBrowse;
import org.dspace.browse.ItemCounter;
import org.dspace.browse.ItemCountException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.I18nUtil;
import org.dspace.core.LicenseManager;
import org.dspace.core.LogManager;
import org.dspace.eperson.Group;
import org.dspace.event.Event;
import org.dspace.handle.HandleManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.workflow.WorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
/**
* Class representing a collection.
* <P>
@@ -338,6 +333,56 @@ public class Collection extends DSpaceObject
return collectionArray;
}
/**
* Get all collections in the system. Adds support for limit and offset.
* @param context
* @param limit
* @param offset
* @return
* @throws SQLException
*/
public static Collection[] findAll(Context context, Integer limit, Integer offset) throws SQLException
{
TableRowIterator tri = DatabaseManager.queryTable(context, "collection",
"SELECT * FROM collection ORDER BY name limit ? offset ?", limit, offset);
List<Collection> collections = new ArrayList<Collection>();
try
{
while (tri.hasNext())
{
TableRow row = tri.next();
// First check the cache
Collection fromCache = (Collection) context.fromCache(
Collection.class, row.getIntColumn("collection_id"));
if (fromCache != null)
{
collections.add(fromCache);
}
else
{
collections.add(new Collection(context, row));
}
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
Collection[] collectionArray = new Collection[collections.size()];
collectionArray = (Collection[]) collections.toArray(collectionArray);
return collectionArray;
}
/**
* Get the in_archive items in this collection. The order is indeterminate.
*
@@ -357,6 +402,27 @@ public class Collection extends DSpaceObject
return new ItemIterator(ourContext, rows);
}
/**
* Get the in_archive items in this collection. The order is indeterminate.
* Provides the ability to use limit and offset, for efficient paging.
* @param limit Max number of results in set
* @param offset Number of results to jump ahead by. 100 = 100th result is first, not 100th page.
* @return an iterator over the items in the collection.
* @throws SQLException
*/
public ItemIterator getItems(Integer limit, Integer offset) throws SQLException
{
String myQuery = "SELECT item.* FROM item, collection2item WHERE "
+ "item.item_id=collection2item.item_id AND "
+ "collection2item.collection_id= ? "
+ "AND item.in_archive='1' limit ? offset ?";
TableRowIterator rows = DatabaseManager.queryTable(ourContext, "item",
myQuery,getID(), limit, offset);
return new ItemIterator(ourContext, rows);
}
/**
* Get all the items in this collection. The order is indeterminate.
*

View File

@@ -7,13 +7,6 @@
*/
package org.dspace.content;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.log4j.Logger;
import org.dspace.app.util.AuthorizeUtil;
@@ -21,8 +14,8 @@ import org.dspace.authorize.AuthorizeConfiguration;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.ItemCounter;
import org.dspace.browse.ItemCountException;
import org.dspace.browse.ItemCounter;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.I18nUtil;
@@ -34,6 +27,13 @@ import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;
/**
* Class representing a community
* <P>
@@ -70,6 +70,12 @@ public class Community extends DSpaceObject
/** The default group of administrators */
private Group admins;
// Keys for accessing Community metadata
public static final String COPYRIGHT_TEXT = "copyright_text";
public static final String INTRODUCTORY_TEXT = "introductory_text";
public static final String SHORT_DESCRIPTION = "short_description";
public static final String SIDEBAR_TEXT = "side_bar_text";
/**
* Construct a community object from a database row.
*

View File

@@ -40,4 +40,12 @@ public class DCValue
/** Authority control confidence */
public int confidence = Choices.CF_UNSET;
/**
* Get the field in dot notation. i.e. schema.element.qualifier, as in dc.date.issued
* @return
*/
public String getField() {
return schema + "." + element + (qualifier==null?"":("." + qualifier));
}
}

68
dspace-rest/README.md Normal file
View File

@@ -0,0 +1,68 @@
#DSpace REST API (Jersey)
A RESTful web services API for DSpace, built using JAX-RS1 JERSEY.
##Getting Started
This REST API is integrated directly into the DSpace code-base.
* Rebuild as normal: mvn + ant
* Deploy the webapp (i.e to tomcat)
* ```<Context path="/rest" docBase="/dspace/webapps/rest" allowLinking="true"/>```
At this point, this is a READ ONLY API for DSpace, for the anonymous user. Only Anonymous READ Communities, Collections, Items, and Bitstreams are available.
##Endpoints
| Resource |CREATE|READ list|READ single|Edit|Delete|Search|
| ------------- |------|:-------:|-----------|----|------|------|
| /communities | | Y | Y | | | |
| /collections | | Y | Y | | | |
| /items | | | Y | | | |
| /bitstreams | | | Y | | | ||
###Communities
View the list of top-level communities
- http://localhost:8080/rest/communities
View a specific community
- http://localhost:8080/rest/communities/:ID
View a specific community, list its subcommunities, and subcollections
- http://localhost:8080/rest/communities/:ID?expand=all
###Collections
View the list of collections
- http://localhost:8080/rest/collections
View a specific collection
- http://localhost:8080/rest/collections/:ID
View a specific collection, and its items
- http://localhost:8080/rest/collections/:ID?expand=all
###Items
View an Item, and see its bitstreams
- http://localhost:8080/rest/items/:ID
###Bitstreams
View information about a bitstream
- http://localhost:8080/rest/bitstreams/:ID
View/Download a specific Bitstream
- http://localhost:8080/rest/bitstreams/:ID/retrieve
###Handles
Lookup a DSpaceObject by its Handle, this produces the name/ID, that you lookup in /bitstreams, /items, /collections, /communities
- http://localhost:8080/rest/handle/{prefix}/{suffix}
##Expand
There is an ?expand= query parameter for more expensive operations. You can tack it on the end of endpoints.
It is optional, all, some or none. The response will usually indicate what the available "expand" options are.
##HTTP Responses
* 200 OK - We have the requested object/objects
* 401 Unauthorized - The anonymous user does not have READ access to that object
* 404 Not Found - That object doesn't exist
* 500 Server Error - Likely a SQLException, IOException, more details in the logs.

83
dspace-rest/pom.xml Normal file
View File

@@ -0,0 +1,83 @@
<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-rest</artifactId>
<packaging>war</packaging>
<version>4.0-SNAPSHOT</version>
<name>DSpace RESTful web services API</name>
<url>http://demo.dspace.org</url>
<parent>
<groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId>
<version>4.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/..</root.basedir>
</properties>
<dependencies>
<!-- Jersey, for RESTful web services -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.17.1</version>
</dependency>
<!-- JSON serialization, should I use jackson?-->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.17.1</version>
</dependency>
<!-- Use DSpace, for now, an older version to minimize spring generated dependency on Discovery -->
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-api</artifactId>
</dependency>
<!-- Connecting to DSpace datasource sets a dependency on Postgres DB-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.0-801.jdbc3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.atteo</groupId>
<artifactId>evo-inflector</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<finalName>${artifactId}</finalName>
</build>
</project>

View File

@@ -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.rest;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import org.dspace.rest.common.Bitstream;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.sql.SQLException;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 10/2/13
* Time: 5:56 PM
* To change this template use File | Settings | File Templates.
*/
@Path("/bitstreams")
public class BitstreamResource {
Logger log = Logger.getLogger(BitstreamResource.class);
private static org.dspace.core.Context context;
//BitstreamList - Not Implemented
@GET
@Path("/{bitstream_id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Bitstream getBitstream(@PathParam("bitstream_id") Integer bitstream_id, @QueryParam("expand") String expand) {
try {
if(context == null || !context.isValid()) {
context = new Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id);
if(AuthorizeManager.authorizeActionBoolean(context, bitstream, org.dspace.core.Constants.READ)) {
return new org.dspace.rest.common.Bitstream(bitstream, expand);
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch(SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
@GET
@Path("/{bitstream_id}/retrieve")
public javax.ws.rs.core.Response getFile(@PathParam("bitstream_id") final Integer bitstream_id) {
try {
if(context == null || !context.isValid() ) {
context = new org.dspace.core.Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id);
if(AuthorizeManager.authorizeActionBoolean(context, bitstream, org.dspace.core.Constants.READ)) {
return Response.ok(bitstream.retrieve()).type(bitstream.getFormat().getMIMEType()).build();
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch (IOException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (AuthorizeException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
}
}

View File

@@ -0,0 +1,125 @@
/**
* 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.rest;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import javax.servlet.ServletContext;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.SQLException;
import java.util.ArrayList;
/*
The "Path" annotation indicates the URI this class will be available at relative to your base URL. For
example, if this web-app is launched at localhost using a context of "hello" and no URL pattern is defined
in the web.xml servlet mapping section, then the web service will be available at:
http://localhost:8080/<webapp>/collections
*/
@Path("/collections")
public class CollectionsResource {
private static Logger log = Logger.getLogger(CollectionsResource.class);
@javax.ws.rs.core.Context ServletContext servletContext;
private static org.dspace.core.Context context;
/*
The "GET" annotation indicates this method will respond to HTTP Get requests.
The "Produces" annotation indicates the MIME response the method will return.
*/
@GET
@Path("/")
@Produces(MediaType.TEXT_HTML)
public String listHTML() {
StringBuilder everything = new StringBuilder();
try {
if(context == null || !context.isValid() ) {
context = new org.dspace.core.Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Collection[] collections = org.dspace.content.Collection.findAll(context);
for(org.dspace.content.Collection collection : collections) {
//TODO check auth...
everything.append("<li><a href='" + servletContext.getContextPath() + "/collections/" + collection.getID() + "'>" + collection.getID() + " - " + collection.getName() + "</a></li>\n");
}
return "<html><title>Hello!</title><body>Collections<br/><ul>" + everything.toString() + "</ul>.</body></html> ";
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
@GET
@Path("/")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.Collection[] list(@QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset) {
try {
if(context == null || !context.isValid() ) {
context = new org.dspace.core.Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Collection[] collections;
//Only support paging if limit/offset are 0 or positive values.
if(limit != null && limit >= 0 && offset != null && offset >= 0) {
collections = org.dspace.content.Collection.findAll(context, limit, offset);
} else {
collections = org.dspace.content.Collection.findAll(context);
}
ArrayList<org.dspace.rest.common.Collection> collectionArrayList = new ArrayList<org.dspace.rest.common.Collection>();
for(org.dspace.content.Collection collection : collections) {
if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) {
org.dspace.rest.common.Collection restCollection = new org.dspace.rest.common.Collection(collection, null, context, limit, offset);
collectionArrayList.add(restCollection);
} // Not showing restricted-access collections
}
return collectionArrayList.toArray(new org.dspace.rest.common.Collection[0]);
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
@GET
@Path("/{collection_id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.Collection getCollection(@PathParam("collection_id") Integer collection_id, @QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset) {
try {
if(context == null || !context.isValid() ) {
context = new Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Collection collection = org.dspace.content.Collection.find(context, collection_id);
if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) {
return new org.dspace.rest.common.Collection(collection, expand, context, limit, offset);
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -0,0 +1,112 @@
/**
* 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.rest;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.SQLException;
import java.util.ArrayList;
/*
The "Path" annotation indicates the URI this class will be available at relative to your base URL. For
example, if this web-app is launched at localhost using a context of "hello" and no URL pattern is defined
in the web.xml servlet mapping section, then the web service will be available at:
http://localhost:8080/<webapp>/communities
*/
@Path("/communities")
public class CommunitiesResource {
private static Logger log = Logger.getLogger(CommunitiesResource.class);
private static org.dspace.core.Context context;
/*
The "GET" annotation indicates this method will respond to HTTP Get requests.
The "Produces" annotation indicates the MIME response the method will return.
*/
@GET
@Produces(MediaType.TEXT_HTML)
public String list() {
StringBuilder everything = new StringBuilder();
try {
if(context == null || !context.isValid() ) {
context = new Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Community[] communities = org.dspace.content.Community.findAllTop(context);
for(org.dspace.content.Community community : communities) {
everything.append(community.getName() + "<br/>\n");
}
return "<html><title>Hello!</title><body>Communities:<br/>" + everything.toString() + ".</body></html> ";
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
//TODO Respond to html for communities/:id
@GET
@Path("/")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.Community[] list(@QueryParam("expand") String expand) {
try {
if(context == null || !context.isValid() ) {
context = new org.dspace.core.Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Community[] topCommunities = org.dspace.content.Community.findAllTop(context);
ArrayList<org.dspace.rest.common.Community> communityArrayList = new ArrayList<org.dspace.rest.common.Community>();
for(org.dspace.content.Community community : topCommunities) {
if(AuthorizeManager.authorizeActionBoolean(context, community, org.dspace.core.Constants.READ)) {
//Only list communities that this user has access to.
org.dspace.rest.common.Community restCommunity = new org.dspace.rest.common.Community(community, expand, context);
communityArrayList.add(restCommunity);
}
}
return communityArrayList.toArray(new org.dspace.rest.common.Community[0]);
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} //finally?
}
@GET
@Path("/{community_id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.Community getCommunity(@PathParam("community_id") Integer community_id, @QueryParam("expand") String expand) {
try {
if(context == null || !context.isValid() ) {
context = new org.dspace.core.Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Community community = org.dspace.content.Community.find(context, community_id);
if(AuthorizeManager.authorizeActionBoolean(context, community, org.dspace.core.Constants.READ)) {
return new org.dspace.rest.common.Community(community, expand, context);
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} //finally?
}
}

View File

@@ -0,0 +1,73 @@
/**
* 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.rest;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.handle.HandleManager;
import org.dspace.rest.common.Collection;
import org.dspace.rest.common.Community;
import org.dspace.rest.common.DSpaceObject;
import org.dspace.rest.common.Item;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.SQLException;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 10/7/13
* Time: 1:54 PM
* To change this template use File | Settings | File Templates.
*/
@Path("/handle")
public class HandleResource {
private static Logger log = Logger.getLogger(HandleResource.class);
private static org.dspace.core.Context context;
@GET
@Path("/{prefix}/{suffix}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.DSpaceObject getObject(@PathParam("prefix") String prefix, @PathParam("suffix") String suffix, @QueryParam("expand") String expand) {
try {
if(context == null || !context.isValid() ) {
context = new Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.DSpaceObject dso = HandleManager.resolveToObject(context, prefix + "/" + suffix);
if(dso == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
log.info("DSO Lookup by handle: [" + prefix + "] / [" + suffix + "] got result of: " + dso.getTypeText() + "_" + dso.getID());
if(AuthorizeManager.authorizeActionBoolean(context, dso, org.dspace.core.Constants.READ)) {
switch(dso.getType()) {
case Constants.COMMUNITY:
return new Community((org.dspace.content.Community) dso, expand, context);
case Constants.COLLECTION:
return new Collection((org.dspace.content.Collection) dso, expand, context, null, null);
case Constants.ITEM:
return new Item((org.dspace.content.Item) dso, expand, context);
default:
return new DSpaceObject(dso);
}
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -0,0 +1,57 @@
/**
* 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.rest;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.SQLException;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 9/19/13
* Time: 4:54 PM
* To change this template use File | Settings | File Templates.
*/
@Path("/items")
public class ItemsResource {
Logger log = Logger.getLogger(ItemsResource.class);
//ItemList - Not Implemented
private static org.dspace.core.Context context;
@GET
@Path("/{item_id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public org.dspace.rest.common.Item getItem(@PathParam("item_id") Integer item_id, @QueryParam("expand") String expand) throws WebApplicationException{
try {
if(context == null || !context.isValid()) {
context = new Context();
//Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block
context.getDBConnection().setAutoCommit(true);
}
org.dspace.content.Item item = org.dspace.content.Item.find(context, item_id);
if(AuthorizeManager.authorizeActionBoolean(context, item, org.dspace.core.Constants.READ)) {
return new org.dspace.rest.common.Item(item, expand, context);
} else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
} catch (SQLException e) {
log.error(e.getMessage());
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -0,0 +1,45 @@
/**
* 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.rest;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/*
Root of API, should have documentation on where to find the other resources.
*/
@Path("/")
public class RestIndex {
@javax.ws.rs.core.Context public static ServletContext servletContext;
/*
The "GET" annotation indicates this method will respond to HTTP Get requests.
The "Produces" annotation indicates the MIME response the method will return.
*/
@GET
@Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html><title>DSpace REST</title>" +
"<body><h1>DSpace REST API</h1>" +
"<ul>" +
"<li><a href='" + servletContext.getContextPath() + "/communities'>/communities</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/communities/1'>/communities/1</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/collections'>/collections</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/collections/1'>/collections/1</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/items'>/items</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/items/1'>/items/1</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/bitstreams'>/bitstreams</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/bitstreams/1'>/bitstreams/1</a></li>" +
"<li><a href='" + servletContext.getContextPath() + "/bitstreams/1/retrieve'>/bitstreams/1/retrieve</a></li>" +
"</ul>" +
"</body></html> ";
}
}

View File

@@ -0,0 +1,104 @@
/**
* 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.rest.common;
import org.apache.log4j.Logger;
import org.dspace.core.Constants;
import javax.xml.bind.annotation.XmlRootElement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 9/21/13
* Time: 12:54 AM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "bitstream")
public class Bitstream extends DSpaceObject {
Logger log = Logger.getLogger(Bitstream.class);
private String bundleName;
private String description;
private String format;
private String mimeType;
private String sizeBytes;
private DSpaceObject parentObject;
private String retrieveLink;
public Bitstream() {
}
public Bitstream(org.dspace.content.Bitstream bitstream, String expand) throws SQLException{
super(bitstream);
setup(bitstream, expand);
}
public void setup(org.dspace.content.Bitstream bitstream, String expand) throws SQLException{
List<String> expandFields = new ArrayList<String>();
if(expand != null) {
expandFields = Arrays.asList(expand.split(","));
}
//A logo bitstream might not have a bundle...
if(bitstream.getBundles() != null & bitstream.getBundles().length >= 0) {
if(bitstream.getParentObject().getType() == Constants.ITEM) {
bundleName = bitstream.getBundles()[0].getName();
}
}
description = bitstream.getDescription();
format = bitstream.getFormatDescription();
sizeBytes = bitstream.getSize() + "";
retrieveLink = "/bitstreams/" + bitstream.getID() + "/retrieve";
mimeType = bitstream.getFormat().getMIMEType();
if(expandFields.contains("parent") || expandFields.contains("all")) {
parentObject = new DSpaceObject(bitstream.getParentObject());
} else {
this.addExpand("parent");
}
if(!expandFields.contains("all")) {
this.addExpand("all");
}
}
public String getBundleName() {
return bundleName;
}
public String getDescription() {
return description;
}
public String getFormat() {
return format;
}
public String getMimeType() {
return mimeType;
}
public String getSizeBytes() {
return sizeBytes;
}
public String getRetrieveLink() {
return retrieveLink;
}
public DSpaceObject getParentObject() {
return parentObject;
}
}

View File

@@ -0,0 +1,156 @@
/**
* 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.rest.common;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.ItemIterator;
import org.dspace.core.Context;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 5/22/13
* Time: 9:41 AM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "collection")
public class Collection extends DSpaceObject {
Logger log = Logger.getLogger(Collection.class);
//Relationships
private Bitstream logo;
private Community parentCommunity;
private List<Community> parentCommunityList = new ArrayList<Community>();
@XmlElement(name = "items")
private List<Item> items = new ArrayList<Item>();
//Collection-Metadata
private String license;
//String provenance_description;
//String short_description;
//String introductory_text;
//String copyright_text;
//String side_bar_text;
//Calculated
private Integer numberItems;
public Collection(){}
public Collection(org.dspace.content.Collection collection, String expand, Context context, Integer limit, Integer offset) throws SQLException, WebApplicationException{
super(collection);
setup(collection, expand, context, limit, offset);
}
private void setup(org.dspace.content.Collection collection, String expand, Context context, Integer limit, Integer offset) throws SQLException{
List<String> expandFields = new ArrayList<String>();
if(expand != null) {
expandFields = Arrays.asList(expand.split(","));
}
if(expandFields.contains("parentCommunityList") || expandFields.contains("all")) {
org.dspace.content.Community[] parentCommunities = collection.getCommunities();
for(org.dspace.content.Community parentCommunity : parentCommunities) {
this.addParentCommunityList(new Community(parentCommunity, null, context));
}
} else {
this.addExpand("parentCommunityList");
}
if(expandFields.contains("parentCommunity") | expandFields.contains("all")) {
org.dspace.content.Community parentCommunity = (org.dspace.content.Community) collection.getParentObject();
this.setParentCommunity(new Community(parentCommunity, null, context));
} else {
this.addExpand("parentCommunity");
}
//TODO: Item paging. limit, offset/page
if(expandFields.contains("items") || expandFields.contains("all")) {
ItemIterator childItems;
if(limit != null && limit >= 0 && offset != null && offset >= 0) {
childItems = collection.getItems(limit, offset);
} else {
childItems = collection.getItems();
}
items = new ArrayList<Item>();
while(childItems.hasNext()) {
org.dspace.content.Item item = childItems.next();
if(AuthorizeManager.authorizeActionBoolean(context, item, org.dspace.core.Constants.READ)) {
items.add(new Item(item, null, context));
}
}
} else {
this.addExpand("items");
}
if(expandFields.contains("license") || expandFields.contains("all")) {
setLicense(collection.getLicense());
} else {
this.addExpand("license");
}
if(expandFields.contains("logo") || expandFields.contains("all")) {
if(collection.getLogo() != null) {
this.logo = new Bitstream(collection.getLogo(), null);
}
}
if(!expandFields.contains("all")) {
this.addExpand("all");
}
this.setNumberItems(collection.countItems());
}
public Bitstream getLogo() {
return logo;
}
public Integer getNumberItems() {
return numberItems;
}
public void setNumberItems(Integer numberItems) {
this.numberItems = numberItems;
}
public Community getParentCommunity() {
return parentCommunity;
}
public void setParentCommunity(Community parentCommunity) {
this.parentCommunity = parentCommunity;
}
public List<Community> getParentCommunityList() {
return parentCommunityList;
}
public void addParentCommunityList(Community parentCommunity) {
this.parentCommunityList.add(parentCommunity);
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
}

View File

@@ -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.rest.common;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 5/22/13
* Time: 9:41 AM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "community")
public class Community extends DSpaceObject{
private static Logger log = Logger.getLogger(Community.class);
//Exandable relationships
private Bitstream logo;
@XmlElement(name = "parentCommunity")
private Community parentCommunity;
private String copyrightText, introductoryText, shortDescription, sidebarText;
private Integer countItems;
@XmlElement(name = "subcommunities", required = true)
private List<Community> subCommunities = new ArrayList<Community>();
@XmlElement(name = "collections")
private List<Collection> collections = new ArrayList<Collection>();
public Community(){}
public Community(org.dspace.content.Community community, String expand, Context context) throws SQLException, WebApplicationException{
super(community);
setup(community, expand, context);
}
private void setup(org.dspace.content.Community community, String expand, Context context) throws SQLException{
List<String> expandFields = new ArrayList<String>();
if(expand != null) {
expandFields = Arrays.asList(expand.split(","));
}
this.setCopyrightText(community.getMetadata(org.dspace.content.Community.COPYRIGHT_TEXT));
this.setIntroductoryText(community.getMetadata(org.dspace.content.Community.INTRODUCTORY_TEXT));
this.setSidebarText(community.getMetadata(org.dspace.content.Community.SIDEBAR_TEXT));
this.setCountItems(community.countItems());
if(expandFields.contains("parentCommunity") || expandFields.contains("all")) {
org.dspace.content.Community parentCommunity = community.getParentCommunity();
if(parentCommunity != null) {
setParentCommunity(new Community(parentCommunity, null, context));
}
} else {
this.addExpand("parentCommunity");
}
if(expandFields.contains("collections") || expandFields.contains("all")) {
org.dspace.content.Collection[] collectionArray = community.getCollections();
collections = new ArrayList<Collection>();
for(org.dspace.content.Collection collection : collectionArray) {
if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) {
collections.add(new Collection(collection, null, context, null, null));
} else {
log.info("Omitted restricted collection: " + collection.getID() + " _ " + collection.getName());
}
}
} else {
this.addExpand("collections");
}
if(expandFields.contains("subCommunities") || expandFields.contains("all")) {
org.dspace.content.Community[] communityArray = community.getSubcommunities();
subCommunities = new ArrayList<Community>();
for(org.dspace.content.Community subCommunity : communityArray) {
if(AuthorizeManager.authorizeActionBoolean(context, subCommunity, org.dspace.core.Constants.READ)) {
subCommunities.add(new Community(subCommunity, null, context));
} else {
log.info("Omitted restricted subCommunity: " + subCommunity.getID() + " _ " + subCommunity.getName());
}
}
} else {
this.addExpand("subCommunities");
}
if(expandFields.contains("logo") || expandFields.contains("all")) {
if(community.getLogo() != null) {
logo = new Bitstream(community.getLogo(), null);
}
} else {
this.addExpand("logo");
}
if(!expandFields.contains("all")) {
this.addExpand("all");
}
}
public List<Collection> getCollections() {
return collections;
}
public void setCollections(List<Collection> collections) {
this.collections = collections;
}
public Integer getCountItems() {
return countItems;
}
public void setCountItems(Integer countItems) {
this.countItems = countItems;
}
public String getSidebarText() {
return sidebarText;
}
public void setSidebarText(String sidebarText) {
this.sidebarText = sidebarText;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getIntroductoryText() {
return introductoryText;
}
public void setIntroductoryText(String introductoryText) {
this.introductoryText = introductoryText;
}
public String getCopyrightText() {
return copyrightText;
}
public void setCopyrightText(String copyrightText) {
this.copyrightText = copyrightText;
}
public Community getParentCommunity() {
return parentCommunity;
}
public void setParentCommunity(Community parentCommunity) {
this.parentCommunity = parentCommunity;
}
public Bitstream getLogo() {
return logo;
}
}

View 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/
*/
package org.dspace.rest.common;
import org.atteo.evo.inflector.English;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 10/7/13
* Time: 12:11 PM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "dspaceobject")
public class DSpaceObject {
private Integer id;
private String name;
private String handle;
private String type;
@XmlElement(name = "link", required = true)
private String link;
private ArrayList<String> expand = new ArrayList<String>();
public DSpaceObject() {
}
public DSpaceObject(org.dspace.content.DSpaceObject dso) {
setID(dso.getID());
setName(dso.getName());
setHandle(dso.getHandle());
setType(dso.getTypeText().toLowerCase());
}
public Integer getID() {
return id;
}
public void setID(Integer id) {
this.id = id;
}
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getHandle() {
return handle;
}
public void setHandle(String handle) {
this.handle = handle;
}
public String getLink() {
//TODO, get actual contextPath of /rest/
return "/rest/" + English.plural(getType()) + "/" + getID();
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getExpand() {
return expand;
}
public void setExpand(ArrayList<String> expand) {
this.expand = expand;
}
public void addExpand(String expandableAttribute) {
this.expand.add(expandableAttribute);
}
}

View File

@@ -0,0 +1,170 @@
/**
* 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.rest.common;
import org.apache.log4j.Logger;
import org.dspace.app.util.MetadataExposure;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.core.Context;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 9/19/13
* Time: 4:50 PM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "item")
public class Item extends DSpaceObject {
Logger log = Logger.getLogger(Item.class);
String isArchived;
String isWithdrawn;
String lastModified;
Collection parentCollection;
List<Collection> parentCollectionList;
List<Community> parentCommunityList;
@XmlElement(name = "metadata", required = true)
List<MetadataEntry> metadata;
@XmlElement(name = "bitstreams")
List<Bitstream> bitstreams;
public Item(){}
public Item(org.dspace.content.Item item, String expand, Context context) throws SQLException, WebApplicationException{
super(item);
setup(item, expand, context);
}
private void setup(org.dspace.content.Item item, String expand, Context context) throws SQLException{
List<String> expandFields = new ArrayList<String>();
if(expand != null) {
expandFields = Arrays.asList(expand.split(","));
}
if(expandFields.contains("metadata") || expandFields.contains("all")) {
metadata = new ArrayList<MetadataEntry>();
DCValue[] dcvs = item.getMetadata(org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY);
for (DCValue dcv : dcvs) {
if (!MetadataExposure.isHidden(context, dcv.schema, dcv.element, dcv.qualifier)) {
metadata.add(new MetadataEntry(dcv.getField(), dcv.value));
}
}
} else {
this.addExpand("metadata");
}
this.setArchived(Boolean.toString(item.isArchived()));
this.setWithdrawn(Boolean.toString(item.isWithdrawn()));
this.setLastModified(item.getLastModified().toString());
if(expandFields.contains("parentCollection") || expandFields.contains("all")) {
this.parentCollection = new Collection(item.getOwningCollection(), null, context, null, null);
} else {
this.addExpand("parentCollection");
}
if(expandFields.contains("parentCollectionList") || expandFields.contains("all")) {
this.parentCollectionList = new ArrayList<Collection>();
org.dspace.content.Collection[] collections = item.getCollections();
for(org.dspace.content.Collection collection : collections) {
this.parentCollectionList.add(new Collection(collection, null, context, null, null));
}
} else {
this.addExpand("parentCollectionList");
}
if(expandFields.contains("parentCommunityList") || expandFields.contains("all")) {
this.parentCommunityList = new ArrayList<Community>();
org.dspace.content.Community[] communities = item.getCommunities();
for(org.dspace.content.Community community : communities) {
this.parentCommunityList.add(new Community(community, null, context));
}
} else {
this.addExpand("parentCommunityList");
}
//TODO: paging - offset, limit
if(expandFields.contains("bitstreams") || expandFields.contains("all")) {
bitstreams = new ArrayList<Bitstream>();
Bundle[] bundles = item.getBundles();
for(Bundle bundle : bundles) {
org.dspace.content.Bitstream[] itemBitstreams = bundle.getBitstreams();
for(org.dspace.content.Bitstream itemBitstream : itemBitstreams) {
if(AuthorizeManager.authorizeActionBoolean(context, itemBitstream, org.dspace.core.Constants.READ)) {
bitstreams.add(new Bitstream(itemBitstream, null));
}
}
}
} else {
this.addExpand("bitstreams");
}
if(!expandFields.contains("all")) {
this.addExpand("all");
}
}
public String getArchived() {
return isArchived;
}
public void setArchived(String archived) {
isArchived = archived;
}
public String getWithdrawn() {
return isWithdrawn;
}
public void setWithdrawn(String withdrawn) {
isWithdrawn = withdrawn;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
public Collection getParentCollection() {
return parentCollection;
}
public List<Collection> getParentCollectionList() {
return parentCollectionList;
}
public List<MetadataEntry> getMetadata() {
return metadata;
}
public List<Bitstream> getBitstreams() {
return bitstreams;
}
public List<Community> getParentCommunityList() {
return parentCommunityList;
}
}

View File

@@ -0,0 +1,46 @@
/**
* 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.rest.common;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Created with IntelliJ IDEA.
* User: peterdietz
* Date: 9/20/13
* Time: 5:51 PM
* To change this template use File | Settings | File Templates.
*/
@XmlRootElement(name = "metadataentry")
public class MetadataEntry {
String key;
String value;
public MetadataEntry() {}
public MetadataEntry(String key, String value) {
this.key = key;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-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/
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<!-- Acquires the DSpace Utility Class with initialized Service Manager -->
<bean id="dspace" class="org.dspace.utils.DSpace"/>
</beans>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-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/
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<servlet>
<servlet-name>DSpace REST API</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<!--
The jersey ServletContainer will look for our Root Resource Class
(i.e. our HelloWorld class) in the foo.bar package
There are other ways to register this; see the jersey documentation for
more details
-->
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.dspace.rest</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<!--
Load the ServletContainer at startup. A value of 1 indicates the ServletContainer
is a high priority servlet to load
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DSpace REST API</servlet-name>
<!--
The url-pattern can be used to define your URL.
Example, running local host with a context of "hello" and path annotation of "world"
on the HelloWorld class:
<url-pattern>/*</url-pattern>
The web service will be available at: http://localhost:8080/hello/world
<url-pattern>/jersey/*</url-pattern>
The web service will be available at http://localhost:8080/hello/jersey/world
-->
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- DSpace Configuration Information -->
<context-param>
<param-name>dspace-config</param-name>
<param-value>${dspace.dir}/config/dspace.cfg</param-value>
</context-param>
<!-- new ConfigurationService initialization for dspace.dir -->
<context-param>
<description>
The location of the main DSpace configuration file
</description>
<param-name>dspace.dir</param-name>
<param-value>${dspace.dir}</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
<!--
Add this context if using Spring Security
/WEB-INF/applicationContext-security.xml
-->
</context-param>
<listener>
<listener-class>org.dspace.app.util.DSpaceContextListener</listener-class>
</listener>
<!-- kernel start listener (from impl)
The following listener can be used instead of the filter below, it is simpler, cleaner
and eliminates the need for a DSpaceKernelServletFilter filter to be involved with the
request cycle.
-->
<listener>
<listener-class>org.dspace.servicemanager.servlet.DSpaceKernelServletContextListener</listener-class>
</listener>
</web-app>

View File

@@ -63,6 +63,15 @@
<module>jspui</module>
</modules>
</profile>
<profile>
<id>dspace-rest</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>rest</module>
</modules>
</profile>
<profile>
<id>dspace-sword</id>
<activation>

108
dspace/modules/rest/pom.xml Normal file
View File

@@ -0,0 +1,108 @@
<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>rest</artifactId>
<packaging>war</packaging>
<name>DSpace REST (JAX RS 1 - Jersey) :: Local Customizations</name>
<description>
Overlay REST customizations
</description>
<parent>
<groupId>org.dspace</groupId>
<artifactId>modules</artifactId>
<version>4.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../../..</root.basedir>
</properties>
<build>
<filters>
<!-- Filter using the properties file defined by dspace-parent POM -->
<filter>${filters.file}</filter>
</filters>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archiveClasses>false</archiveClasses>
<webResources>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/webapp</directory>
<includes>
<include>WEB-INF/web.xml</include>
</includes>
</resource>
</webResources>
<overlays>
<!--
the priority of overlays is determined here
1.) default: anything in the current project has highest
2.) anything defined here has precedence in the order defined
3.) any war found transitively in the dependencies will be applied
next. the order is unpredictable.
-->
<overlay>
<groupId>org.dspace</groupId>
<artifactId>dspace-rest</artifactId>
</overlay>
</overlays>
</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>
<!-- DSpace REST Webapp -->
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-rest</artifactId>
<type>war</type>
<version>4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

View File

@@ -698,6 +698,10 @@ Common usage:
<fileset dir="${dspace.dir}/webapps/jspui/" />
</war>
<war destfile="${dspace.dir}/webapps/rest.war">
<fileset dir="${dspace.dir}/webapps/rest/"/>
</war>
<war destfile="${dspace.dir}/webapps/sword.war">
<fileset dir="${dspace.dir}/webapps/sword/" />
</war>

14
pom.xml
View File

@@ -396,6 +396,19 @@
</modules>
</profile>
<!-- REST Jersey -->
<profile>
<id>dspace-rest</id>
<activation>
<file>
<exists>dspace-rest/pom.xml</exists>
</file>
</activation>
<modules>
<module>dspace-rest</module>
</modules>
</profile>
<!--
Builds SWORD WAR for DSpace
@@ -492,6 +505,7 @@
<module>dspace-xmlui</module>
<module>dspace-lni</module>
<module>dspace-oai</module>
<module>dspace-rest</module>
<module>dspace-sword</module>
<module>dspace-swordv2</module>
</modules>