diff --git a/dspace-rest/LICENSE b/dspace-rest/LICENSE
new file mode 100644
index 000000000000..bc72317dc7e5
--- /dev/null
+++ b/dspace-rest/LICENSE
@@ -0,0 +1,5 @@
+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/
diff --git a/dspace-rest/README b/dspace-rest/README
new file mode 100644
index 000000000000..f95acd53ddb1
--- /dev/null
+++ b/dspace-rest/README
@@ -0,0 +1,16 @@
+A RESTful web services API for DSpace.
+
+Built on JERSEY
+
+mvn clean package
+Deploy /target/rest.war to tomcat.
+
+Endpoints:
+- http://localhost:8080/dspace-rest/collections
+-- http://localhost:8080/dspace-rest/collections/{collectionID}
+-- http://localhost:8080/dspace-rest/collections/{collectionID}?expand=parentCommunityID,parentCommunityIDList,itemIDList
+-- http://localhost:8080/dspace-rest/collections/123
+
+- http://localhost:8080/dspace-rest/communities
+
+There is an ?expand= query parameter for expensive operations. You can tack it on the end of /collections endpoints. It is optional, all, some or none.
\ No newline at end of file
diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml
new file mode 100644
index 000000000000..e4eada57b7d6
--- /dev/null
+++ b/dspace-rest/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ org.dspace.rest
+ dspace-rest
+ war
+ 1.0-SNAPSHOT
+ DSpace RESTful web services API
+ http://demo.dspace.org
+
+
+
+ com.sun.jersey
+ jersey-server
+ 1.8
+
+
+ com.sun.jersey
+ jersey-servlet
+ 1.17
+
+
+
+ com.sun.jersey
+ jersey-json
+ 1.8
+
+
+
+
+ org.dspace
+ dspace-api
+ 1.8.2
+
+
+
+
+ commons-dbcp
+ commons-dbcp
+ 1.4
+
+
+ postgresql
+ postgresql
+ 9.0-801.jdbc3
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.6
+ 1.6
+
+
+
+ ${artifactId}
+
+
diff --git a/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java b/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java
new file mode 100644
index 000000000000..bca91e68798b
--- /dev/null
+++ b/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java
@@ -0,0 +1,77 @@
+package org.dspace.rest;
+
+import org.dspace.content.Collection;
+import org.dspace.core.Context;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+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//collections
+ */
+@Path("/collections")
+public class CollectionsResource {
+ final String collectionsPath = "/dspace-rest/collections/";
+
+ private static 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 {
+ Context context = new Context();
+
+ Collection[] collections = Collection.findAll(context);
+ for(Collection collection : collections) {
+ everything.append("" + collection.getID() + " - " + collection.getName() + " \n");
+ }
+
+ } catch (SQLException e) {
+ return "ERROR: " + e.getMessage();
+ }
+
+ return "Hello! Collections" + everything.toString() + " . ";
+ }
+
+ @GET
+ @Path("/")
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public org.dspace.rest.common.Collection[] list(@QueryParam("expand") String expand) {
+ try {
+ if(context == null || !context.isValid() ) {
+ context = new Context();
+ }
+
+ Collection[] collections = Collection.findAll(context);
+ ArrayList collectionArrayList = new ArrayList();
+ for(Collection collection : collections) {
+ org.dspace.rest.common.Collection restCollection = new org.dspace.rest.common.Collection(collection, expand);
+ collectionArrayList.add(restCollection);
+ }
+
+ return collectionArrayList.toArray(new org.dspace.rest.common.Collection[0]);
+
+ } catch (SQLException e) {
+ return null;
+ }
+ }
+
+ @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) {
+ return new org.dspace.rest.common.Collection(collection_id, expand);
+ }
+}
diff --git a/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java b/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java
new file mode 100644
index 000000000000..b0cdc5af6b41
--- /dev/null
+++ b/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java
@@ -0,0 +1,46 @@
+package org.dspace.rest;
+
+import org.dspace.content.Community;
+import org.dspace.core.Context;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.sql.SQLException;
+
+/*
+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//communities
+ */
+@Path("/communities")
+public class CommunitiesResource {
+ private static 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();
+ }
+ Community[] communities = Community.findAllTop(context);
+ for(Community community : communities) {
+ everything.append(community.getName() + " \n");
+ }
+
+ } catch (SQLException e) {
+ return "ERROR: " + e.getMessage();
+ }
+
+ return "Hello! Communities: " + everything.toString() + ". ";
+ }
+}
diff --git a/dspace-rest/src/main/java/org/dspace/rest/HelloWorld.java b/dspace-rest/src/main/java/org/dspace/rest/HelloWorld.java
new file mode 100644
index 000000000000..401b633d6076
--- /dev/null
+++ b/dspace-rest/src/main/java/org/dspace/rest/HelloWorld.java
@@ -0,0 +1,27 @@
+package org.dspace.rest;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/*
+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//helloworld
+ */
+@Path("/helloworld")
+public class HelloWorld {
+
+ /*
+ 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 "Hello! Hello, world. ";
+ }
+}
diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java b/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java
new file mode 100644
index 000000000000..7545e7af6db1
--- /dev/null
+++ b/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java
@@ -0,0 +1,217 @@
+package org.dspace.rest.common;
+
+import org.dspace.content.Community;
+import org.dspace.content.Item;
+import org.dspace.content.ItemIterator;
+import org.dspace.core.Context;
+
+import javax.xml.bind.annotation.XmlRootElement;
+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
+public class Collection {
+ //Internal value
+ private Integer collectionID;
+
+ //Relationships to other objects
+ private Integer logoID;
+
+ //Exandable relationships
+ private Integer parentCommunityID;
+ private List parentCommunityIDList = new ArrayList();
+ private List itemIDList = new ArrayList();
+
+
+ private List expand = new ArrayList();
+
+ //Internal metadata
+ private String name;
+ private String handle;
+ private String license;
+
+ //Calculated
+ private Integer numberItems;
+
+ private static Context context;
+
+ public Collection(){}
+
+ public Collection(org.dspace.content.Collection collection, String expand) {
+ setup(collection, expand);
+ }
+
+ public Collection(Integer collectionID, String expand) {
+ try {
+ if(context == null || !context.isValid() ) {
+ context = new Context();
+ }
+
+ org.dspace.content.Collection collection = org.dspace.content.Collection.find(context, collectionID);
+ setup(collection, expand);
+
+ } catch (Exception e) {
+ this.setName(e.getMessage());
+
+ }
+ }
+
+ private void setup(org.dspace.content.Collection collection, String expand) {
+ List expandFields = new ArrayList();
+ if(expand != null) {
+ expandFields = Arrays.asList(expand.split(","));
+ }
+
+
+ try {
+ this.setCollectionID(collection.getID());
+ this.setName(collection.getName());
+ this.setHandle(collection.getHandle());
+
+ if(expandFields.contains("parentCommunityIDList")) {
+ Community[] parentCommunities = collection.getCommunities();
+ for(Community parentCommunity : parentCommunities) {
+ this.addParentCommunityIDList(parentCommunity.getID());
+ }
+ } else {
+ this.addExpand("parentCommunityIDList");
+ }
+
+ if(expandFields.contains("parentCommunityID")) {
+ Community parentCommunity = (Community) collection.getParentObject();
+ this.setParentCommunityID(parentCommunity.getID());
+ } else {
+ this.addExpand("parentCommunityID");
+ }
+
+ if(expandFields.contains("itemIDList")) {
+ ItemIterator childItems = collection.getItems();
+ while(childItems.hasNext()) {
+ Item item = childItems.next();
+ this.addItemIDToList(item.getID());
+ }
+ } else {
+ this.addExpand("itemIDList");
+ }
+
+ if(collection.getLogo() != null) {
+ this.setLogoID(collection.getLogo().getID());
+ }
+
+ this.setLicense(collection.getLicense());
+ this.setNumberItems(collection.countItems());
+ //collection.getMetadata()
+ } catch (Exception e) {
+
+ }
+
+ }
+
+ //metadata s
+ //String provenance_description;
+ //String short_description;
+ //String introductory_text;
+ //String copyright_text;
+ //String side_bar_text;
+
+ public Integer getCollectionID() {
+ return collectionID;
+ }
+
+ public void setCollectionID(Integer id) {
+ this.collectionID = id;
+ }
+
+ 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 Integer getLogoID() {
+ return logoID;
+ }
+
+ public void setLogoID(Integer logoID) {
+ this.logoID = logoID;
+ }
+
+ public String getLicense() {
+ return license;
+ }
+
+ public void setLicense(String license) {
+ this.license = license;
+ }
+
+ public Integer getNumberItems() {
+ return numberItems;
+ }
+
+ public void setNumberItems(Integer numberItems) {
+ this.numberItems = numberItems;
+ }
+
+ public Integer getParentCommunityID() {
+ return parentCommunityID;
+ }
+
+ public void setParentCommunityID(Integer parentCommunityID) {
+ this.parentCommunityID = parentCommunityID;
+ }
+
+ public List getParentCommunityIDList() {
+ return parentCommunityIDList;
+ }
+
+ public void setParentCommunityIDList(List parentCommunityIDList) {
+ this.parentCommunityIDList = parentCommunityIDList;
+ }
+
+ public void addParentCommunityIDList(Integer communityParentID) {
+ this.parentCommunityIDList.add(communityParentID);
+ }
+
+
+ public List getItemIDList() {
+ return itemIDList;
+ }
+
+ public void setItemIDList(List itemIDList) {
+ this.itemIDList = itemIDList;
+ }
+
+ public void addItemIDToList(Integer itemID) {
+ this.itemIDList.add(itemID);
+ }
+
+ public List getExpand() {
+ return expand;
+ }
+
+ public void setExpand(List expand) {
+ this.expand = expand;
+ }
+
+ public void addExpand(String expandableAttribute) {
+ this.expand.add(expandableAttribute);
+ }
+}
diff --git a/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml b/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 000000000000..ea28e11ce50d
--- /dev/null
+++ b/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dspace-rest/src/main/webapp/WEB-INF/web.xml b/dspace-rest/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000000..0d8be7ae7b5b
--- /dev/null
+++ b/dspace-rest/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,84 @@
+
+
+ DSpace REST API
+ com.sun.jersey.spi.container.servlet.ServletContainer
+
+
+ com.sun.jersey.config.property.packages
+ org.dspace.rest
+
+
+ com.sun.jersey.api.json.POJOMappingFeature
+ true
+
+
+ 1
+
+
+ DSpace REST API
+
+ /*
+
+
+
+ dspace-config
+ /dspace/config/dspace.cfg
+
+
+
+
+ The location of the main DSpace configuration file
+ dspace.dir
+
+ /dspace
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext.xml
+
+
+
+
+
+ org.dspace.app.util.DSpaceContextListener
+
+
+
+
+ org.dspace.servicemanager.servlet.DSpaceKernelServletContextListener
+
+
+
+
diff --git a/dspace/modules/rest/pom.xml b/dspace/modules/rest/pom.xml
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/dspace/modules/rest/src/main/webapp/.gitignore b/dspace/modules/rest/src/main/webapp/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1