mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Merge pull request #666 from ctu-developers/master
DS-2168: New REST api with CRUD operations.
This commit is contained in:
@@ -7,143 +7,849 @@
|
||||
*/
|
||||
package org.dspace.rest;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.rest.common.Bitstream;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
import org.dspace.utils.DSpace;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLConnection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.BitstreamFormat;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.rest.common.Bitstream;
|
||||
import org.dspace.rest.common.ResourcePolicy;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.storage.bitstore.BitstreamStorageManager;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: peterdietz
|
||||
* Date: 10/2/13
|
||||
* Time: 5:56 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*/
|
||||
// Every DSpace class used without namespace is from package
|
||||
// org.dspace.rest.common.*. Otherwise namespace is defined.
|
||||
@Path("/bitstreams")
|
||||
public class BitstreamResource {
|
||||
Logger log = Logger.getLogger(BitstreamResource.class);
|
||||
public class BitstreamResource extends Resource
|
||||
{
|
||||
|
||||
private static final boolean writeStatistics;
|
||||
|
||||
static{
|
||||
writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false);
|
||||
}
|
||||
|
||||
//BitstreamList - Not Implemented
|
||||
private static Logger log = Logger.getLogger(BitstreamResource.class);
|
||||
|
||||
/**
|
||||
* Return bitstream properties without file data. It can throws
|
||||
* WebApplicationException with three response codes. Response code
|
||||
* NOT_FOUND(404) or UNAUTHORIZED(401) or INTERNAL_SERVER_ERROR(500). Bad
|
||||
* request is when id of bitstream does not exist. UNAUTHORIZED is if logged
|
||||
* user into DSpace context have not permission to access bitstream. Server
|
||||
* error when something went wrong.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitstream in DSpace.
|
||||
* @param expand
|
||||
* This string defined, which additional options will be added
|
||||
* into bitstream. Single options are separated by commas without
|
||||
* space. Options are: "all", "parent".
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return If user is allowed to read bitstream, it returns instance of
|
||||
* bitstream. Otherwise, it throws WebApplicationException with
|
||||
* response code UNAUTHORIZED.
|
||||
* @throws WebApplicationException
|
||||
* It can happen on: Bad request, unauthorized, SQL exception
|
||||
* and context exception(could not create context).
|
||||
*/
|
||||
@GET
|
||||
@Path("/{bitstream_id}")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Bitstream getBitstream(@PathParam("bitstream_id") Integer bitstream_id, @QueryParam("expand") String expand) {
|
||||
public Bitstream getBitstream(@PathParam("bitstream_id") Integer bitstreamId, @QueryParam("expand") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading bitstream(id=" + bitstreamId + ") metadata.");
|
||||
org.dspace.core.Context context = null;
|
||||
try {
|
||||
context = new org.dspace.core.Context();
|
||||
Bitstream bitstream = null;
|
||||
|
||||
org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id);
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.READ);
|
||||
|
||||
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);
|
||||
} finally {
|
||||
if(context != null) {
|
||||
try {
|
||||
writeStats(dspaceBitstream, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor, headers,
|
||||
request);
|
||||
|
||||
bitstream = new Bitstream(dspaceBitstream, expand);
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage() + " occurred while trying to close");
|
||||
log.trace("Bitsream(id=" + bitstreamId + ") was successfully read.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Someting went wrong while reading bitstream(id=" + bitstreamId + ") from database! Message: " + e,
|
||||
context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Someting went wrong while reading bitstream(id=" + bitstreamId + "), ContextException. Message: "
|
||||
+ e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all bitstream resource policies from all bundles, in which
|
||||
* bitstream is.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitstream in DSpace.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return It returns array of ResourcePolicy.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{bitstream_id}/policy")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public ResourcePolicy[] getBitstreamPolicies(@PathParam("bitstream_id") Integer bitstreamId, @Context HttpHeaders headers)
|
||||
{
|
||||
|
||||
log.info("Reading bitstream(id=" + bitstreamId + ") policies.");
|
||||
org.dspace.core.Context context = null;
|
||||
List<ResourcePolicy> policies = new ArrayList<ResourcePolicy>();
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.READ);
|
||||
|
||||
Bundle[] bundles = dspaceBitstream.getBundles();
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
List<org.dspace.authorize.ResourcePolicy> bitstreamsPolicies = bundle.getBitstreamPolicies();
|
||||
for (org.dspace.authorize.ResourcePolicy policy : bitstreamsPolicies)
|
||||
{
|
||||
if (policy.getResourceID() == bitstreamId)
|
||||
{
|
||||
policies.add(new ResourcePolicy(policy));
|
||||
}
|
||||
}
|
||||
}
|
||||
context.complete();
|
||||
log.trace("Policies for bitsream(id=" + bitstreamId + ") was successfully read.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Someting went wrong while reading policies of bitstream(id=" + bitstreamId
|
||||
+ "), SQLException! Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Someting went wrong while reading policies of bitstream(id=" + bitstreamId
|
||||
+ "), ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return policies.toArray(new ResourcePolicy[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read list of bitstreams. It throws WebApplicationException with response
|
||||
* code INTERNAL_SERVER_ERROR(500), if there was problem while reading
|
||||
* bitstreams from database.
|
||||
*
|
||||
* @param limit
|
||||
* How much bitstreams in list will be. Default value is 100.
|
||||
* @param offset
|
||||
* On which index will list starts. Default values is 0.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return It returns array of bistreams. In array are not bitstreams on
|
||||
* which user has not permission to read.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading or with
|
||||
* creating context.
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Bitstream[] getBitstreams(@QueryParam("expand") String expand,
|
||||
@QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading bitstreams.(offset=" + offset + ",limit=" + limit + ")");
|
||||
org.dspace.core.Context context = null;
|
||||
List<Bitstream> bitstreams = new ArrayList<Bitstream>();
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream[] dspaceBitstreams = org.dspace.content.Bitstream.findAll(context);
|
||||
|
||||
if (!((limit != null) && (limit >= 0) && (offset != null) && (offset >= 0)))
|
||||
{
|
||||
log.warn("Pagging was badly set.");
|
||||
limit = 100;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
// TODO If bitsream doesnt not exist it throw exception.
|
||||
for (int i = offset; (i < (offset + limit)) && (i < dspaceBitstreams.length); i++)
|
||||
{
|
||||
if (AuthorizeManager.authorizeActionBoolean(context, dspaceBitstreams[i], org.dspace.core.Constants.READ))
|
||||
{
|
||||
if (dspaceBitstreams[i].getParentObject() != null)
|
||||
{ // To eliminate bitstreams which cause exception, because of
|
||||
// reading under administrator permissions
|
||||
bitstreams.add(new Bitstream(dspaceBitstreams[i], expand));
|
||||
writeStats(dspaceBitstreams[i], UsageEvent.Action.VIEW, user_ip, user_agent,
|
||||
xforwarderfor, headers, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.complete();
|
||||
log.trace("Bitstreams were successfully read.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something get wrong while reading bitstreams from database!. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Something get wrong while reading bitstreams, ContextException. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return bitstreams.toArray(new Bitstream[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bitstream data. It can throw WebApplicationException with code
|
||||
* INTERNAL_SERVER_ERROR(500). Caused by three exceptions: IOException if
|
||||
* there was problem with reading bitstream file. SQLException if there was
|
||||
* problem while reading from database. And AuthorizeException if there was
|
||||
* problem with authorization of user logged to DSpace context.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitstream, of which will be read data.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return Returns response with data with content type of file. It can
|
||||
* return response code NOT_FOUND(404) if there was bad id of
|
||||
* bitstream. Or response code UNAUTHORIZED(401) if user is not
|
||||
* allowed to read bitstream.
|
||||
* @throws WebApplicationException
|
||||
* It is throw in this cases: When was problem with reading file
|
||||
* data. Or was problem with database reading. Or was problem
|
||||
* with creating context. Or problem with authorization.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{bitstream_id}/retrieve")
|
||||
public javax.ws.rs.core.Response getFile(@PathParam("bitstream_id") final Integer bitstream_id,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) {
|
||||
public javax.ws.rs.core.Response getBitstreamData(@PathParam("bitstream_id") Integer bitstreamId,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading data of bitstream(id=" + bitstreamId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
try {
|
||||
context = new org.dspace.core.Context();
|
||||
InputStream inputStream = null;
|
||||
String type = null;
|
||||
|
||||
org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id);
|
||||
if(AuthorizeManager.authorizeActionBoolean(context, bitstream, org.dspace.core.Constants.READ)) {
|
||||
if(writeStatistics){
|
||||
writeStats(context, bitstream_id, user_ip, user_agent, xforwarderfor, headers, request);
|
||||
}
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.READ);
|
||||
|
||||
return Response.ok(bitstream.retrieve()).type(bitstream.getFormat().getMIMEType()).build();
|
||||
} else {
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
writeStats(dspaceBitstream, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor, headers,
|
||||
request);
|
||||
|
||||
log.trace("Bitsream(id=" + bitstreamId + ") data was successfully read.");
|
||||
inputStream = dspaceBitstream.retrieve();
|
||||
type = dspaceBitstream.getFormat().getMIMEType();
|
||||
|
||||
} 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);
|
||||
} finally {
|
||||
if(context != null) {
|
||||
try {
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage() + " occurred while trying to close");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not read file of bitstream(id=" + bitstreamId + ")! Message: " + e, context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something get wrong while reading bitsream(id=" + bitstreamId + ") from database! Message: " + e,
|
||||
context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not retrieve file of bitstream(id=" + bitstreamId + "), AuthorizeException! Message: " + e,
|
||||
context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException(
|
||||
"Could not retrieve file of bitstream(id=" + bitstreamId + "), ContextException! Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return Response.ok(inputStream).type(type).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bitstream policy to all bundles in which bitstream is.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitstream in DSpace.
|
||||
* @param policy
|
||||
* Policy which will be added. But this atributes does not be
|
||||
* applied: epersonId,
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return Returns ok, if was all ok. Otherwise status code 500.
|
||||
*/
|
||||
@POST
|
||||
@Path("/{bitstream_id}/policy")
|
||||
public javax.ws.rs.core.Response addBitstreamPolicy(@PathParam("bitstream_id") Integer bitstreamId, ResourcePolicy policy,
|
||||
@Context HttpHeaders headers)
|
||||
{
|
||||
|
||||
log.info("Adding bitstream(id=" + bitstreamId + ") READ policy with permission for group(id=" + policy.getGroupId()
|
||||
+ ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.READ);
|
||||
|
||||
Bundle[] bundles = dspaceBitstream.getBundles();
|
||||
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
List<org.dspace.authorize.ResourcePolicy> bitstreamsPolicies = bundle.getBitstreamPolicies();
|
||||
|
||||
org.dspace.authorize.ResourcePolicy dspacePolicy = org.dspace.authorize.ResourcePolicy.create(context);
|
||||
dspacePolicy.setAction(policy.getActionInt());
|
||||
dspacePolicy.setGroup(Group.find(context, policy.getGroupId()));
|
||||
dspacePolicy.setResourceID(dspaceBitstream.getID());
|
||||
dspacePolicy.setResource(dspaceBitstream);
|
||||
dspacePolicy.setResourceType(org.dspace.core.Constants.BITSTREAM);
|
||||
dspacePolicy.setStartDate(policy.getStartDate());
|
||||
dspacePolicy.setEndDate(policy.getEndDate());
|
||||
dspacePolicy.setRpDescription(policy.getRpDescription());
|
||||
dspacePolicy.setRpName(policy.getRpName());
|
||||
dspacePolicy.update();
|
||||
// dspacePolicy.setRpType(org.dspace.authorize.ResourcePolicy.TYPE_CUSTOM);
|
||||
bitstreamsPolicies.add(dspacePolicy);
|
||||
|
||||
bundle.replaceAllBitstreamPolicies(bitstreamsPolicies);
|
||||
bundle.update();
|
||||
}
|
||||
|
||||
context.complete();
|
||||
log.trace("Policy for bitsream(id=" + bitstreamId + ") was successfully added.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Someting went wrong while adding policy to bitstream(id=" + bitstreamId
|
||||
+ "), SQLException! Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Someting went wrong while adding policy to bitstream(id=" + bitstreamId
|
||||
+ "), ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Someting went wrong while adding policy to bitstream(id=" + bitstreamId
|
||||
+ "), AuthorizeException! Message: " + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
return Response.status(Status.OK).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update bitstream metadata. It replace everything on targeted bitstream.
|
||||
* It can throws WebApplicationException caused by two exceptions:
|
||||
* SQLException, if there was problem with database. AuthorizeException if
|
||||
* there was problem with authorization to edit bitstream metadata.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bistream, wich will be updated.
|
||||
* @param bitstream
|
||||
* Bitstream with will be placed. It muset have filled user
|
||||
* creditials.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return Return response codes: OK(200), NOT_FOUND(404) if bitstream does
|
||||
* not exist and UNAUTHORIZED(401) if user is not allowed to write
|
||||
* to bitstream.
|
||||
* @throws WebApplicationException
|
||||
* It can be thrown by: Error in reading from database. Or
|
||||
* creating context or with authorization to bitstream.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{bitstream_id}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response updateBitstream(@PathParam("bitstream_id") Integer bitstreamId, Bitstream bitstream,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Updating bitstream(id=" + bitstreamId + ") metadata.");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.WRITE);
|
||||
|
||||
writeStats(dspaceBitstream, UsageEvent.Action.UPDATE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
log.trace("Updating bitstream metadata.");
|
||||
dspaceBitstream.setDescription(bitstream.getDescription());
|
||||
if (getMimeType(bitstream.getName()) == null)
|
||||
{
|
||||
dspaceBitstream.setFormat(BitstreamFormat.findUnknown(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
dspaceBitstream.setFormat(BitstreamFormat.findByMIMEType(context, getMimeType(bitstream.getName())));
|
||||
}
|
||||
dspaceBitstream.setName(bitstream.getName());
|
||||
Integer sequenceId = bitstream.getSequenceId();
|
||||
if (sequenceId != null && sequenceId.intValue() != -1)
|
||||
{
|
||||
dspaceBitstream.setSequenceID(sequenceId);
|
||||
}
|
||||
|
||||
dspaceBitstream.update();
|
||||
|
||||
if (bitstream.getPolicies() != null)
|
||||
{
|
||||
Bundle[] bundles = dspaceBitstream.getBundles();
|
||||
ResourcePolicy[] policies = bitstream.getPolicies();
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
List<org.dspace.authorize.ResourcePolicy> bitstreamsPolicies = bundle.getBitstreamPolicies();
|
||||
// Remove old bitstream policies
|
||||
List<org.dspace.authorize.ResourcePolicy> policiesToRemove = new ArrayList<org.dspace.authorize.ResourcePolicy>();
|
||||
for (org.dspace.authorize.ResourcePolicy policy : bitstreamsPolicies)
|
||||
{
|
||||
if (policy.getResourceID() == dspaceBitstream.getID())
|
||||
{
|
||||
policiesToRemove.add(policy);
|
||||
}
|
||||
}
|
||||
for (org.dspace.authorize.ResourcePolicy policy : policiesToRemove)
|
||||
{
|
||||
bitstreamsPolicies.remove(policy);
|
||||
}
|
||||
|
||||
// Add all new bitstream policies
|
||||
for (ResourcePolicy policy : policies)
|
||||
{
|
||||
org.dspace.authorize.ResourcePolicy dspacePolicy = org.dspace.authorize.ResourcePolicy.create(context);
|
||||
dspacePolicy.setAction(policy.getActionInt());
|
||||
dspacePolicy.setGroup(Group.find(context, policy.getGroupId()));
|
||||
dspacePolicy.setResourceID(dspaceBitstream.getID());
|
||||
dspacePolicy.setResource(dspaceBitstream);
|
||||
dspacePolicy.setResourceType(org.dspace.core.Constants.BITSTREAM);
|
||||
dspacePolicy.setStartDate(policy.getStartDate());
|
||||
dspacePolicy.setEndDate(policy.getEndDate());
|
||||
dspacePolicy.setRpDescription(policy.getRpDescription());
|
||||
dspacePolicy.setRpName(policy.getRpName());
|
||||
dspacePolicy.update();
|
||||
bitstreamsPolicies.add(dspacePolicy);
|
||||
}
|
||||
bundle.replaceAllBitstreamPolicies(bitstreamsPolicies);
|
||||
bundle.update();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStats(org.dspace.core.Context context, Integer bitstream_id, String user_ip, String user_agent,
|
||||
String xforwarderfor, HttpHeaders headers,
|
||||
HttpServletRequest request) {
|
||||
context.complete();
|
||||
|
||||
try{
|
||||
DSpaceObject bitstream = DSpaceObject.find(context, Constants.BITSTREAM, bitstream_id);
|
||||
|
||||
if(user_ip==null || user_ip.length()==0){
|
||||
new DSpace().getEventService().fireEvent(
|
||||
new UsageEvent(
|
||||
UsageEvent.Action.VIEW,
|
||||
request,
|
||||
context,
|
||||
bitstream));
|
||||
} else{
|
||||
new DSpace().getEventService().fireEvent(
|
||||
new UsageEvent(
|
||||
UsageEvent.Action.VIEW,
|
||||
user_ip,
|
||||
user_agent,
|
||||
xforwarderfor,
|
||||
context,
|
||||
bitstream));
|
||||
}
|
||||
log.debug("fired event");
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not update bitstream(id=" + bitstreamId + ") metadata, SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not update bitstream(id=" + bitstreamId + ") metadata, AuthorizeException. Message: " + e,
|
||||
context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException(
|
||||
"Could not update bitstream(id=" + bitstreamId + ") metadata, ContextException. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
} catch(SQLException ex){
|
||||
log.error("SQL exception can't write usageEvent \n" + ex);
|
||||
log.info("Bitstream metadata(id=" + bitstreamId + ") were successfully updated.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update bitstream data. It change bitstream data by editing database rows.
|
||||
* It can throw WebApplicationException caused by: SQLException if there was
|
||||
* problem with database editing or reading, IOException if there was
|
||||
* problem with reading from inputstream, Exception if there was another
|
||||
* problem.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bistream, which will be updated.
|
||||
* @param is
|
||||
* Inputstream filled with new data.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return Return response if bitstream was updated. Response codes:
|
||||
* OK(200), NOT_FOUND(404) if id of bitstream was bad. And
|
||||
* UNAUTHORIZED(401) if user is not allowed to update bitstream.
|
||||
* @throws WebApplicationException
|
||||
* This exception can be thrown in this cases: Problem with
|
||||
* reading or writing to database. Or problem with reading from
|
||||
* inputstream.
|
||||
*/
|
||||
// TODO Change to better logic, without editing database.
|
||||
@PUT
|
||||
@Path("/{bitstream_id}/data")
|
||||
public Response updateBitstreamData(@PathParam("bitstream_id") Integer bitstreamId, InputStream is,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Updating bitstream(id=" + bitstreamId + ") data.");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.WRITE);
|
||||
|
||||
writeStats(dspaceBitstream, UsageEvent.Action.UPDATE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
log.trace("Creating new bitstream.");
|
||||
int newBitstreamId = BitstreamStorageManager.store(context, is);
|
||||
|
||||
log.trace("Looking for table rows of bitstreams.");
|
||||
TableRow originalBitstreamRow = DatabaseManager.find(context, "Bitstream", bitstreamId);
|
||||
TableRow bitstream = DatabaseManager.find(context, "Bitstream", newBitstreamId);
|
||||
|
||||
log.trace("Changing new internal id with old internal id.");
|
||||
String internal_id = originalBitstreamRow.getStringColumn("internal_id");
|
||||
Long size_bytes = originalBitstreamRow.getLongColumn("size_bytes");
|
||||
originalBitstreamRow.setColumn("internal_id", bitstream.getStringColumn("internal_id"));
|
||||
originalBitstreamRow.setColumn("size_bytes", bitstream.getLongColumn("size_bytes"));
|
||||
bitstream.setColumn("internal_id", internal_id);
|
||||
bitstream.setColumn("size_bytes", size_bytes);
|
||||
|
||||
DatabaseManager.update(context, originalBitstreamRow);
|
||||
BitstreamStorageManager.delete(context, newBitstreamId);
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not update bitstream(id=" + bitstreamId + ") data, SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not update bitstream(id=" + bitstreamId + ") data, IOException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException(
|
||||
"Could not update bitstream(id=" + bitstreamId + ") data, ContextException. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Bitstream(id=" + bitstreamId + ") data was successfully updated.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete bitstream from all bundles in dspace. It can throw
|
||||
* WebApplicationException, which can be caused by three exceptions.
|
||||
* SQLException if there was problem with reading from database or removing
|
||||
* from database. AuthorizeException, if user has not permission to delete
|
||||
* bitstream or file. IOException, if there was problem with file deleting.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitsream, which will be deleted.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return Return response codes: OK(200), NOT_FOUND(404) if bitstream of
|
||||
* that id does not exist and UNAUTHORIZED(401) if user is not
|
||||
* allowed to delete bitstream.
|
||||
* @throws WebApplicationException
|
||||
* It can be throw when was problem with reading or editting
|
||||
* database. Or problem with file deleting. Or problem with
|
||||
* authorization to bitstream and bundles. Or problem with
|
||||
* creating context.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{bitstream_id}")
|
||||
public Response deleteBitstream(@PathParam("bitstream_id") Integer bitstreamId, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Deleting bitstream(id=" + bitstreamId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.DELETE);
|
||||
|
||||
writeStats(dspaceBitstream, UsageEvent.Action.DELETE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
log.trace("Deleting bitstream from all bundles.");
|
||||
for (org.dspace.content.Bundle bundle : dspaceBitstream.getBundles())
|
||||
{
|
||||
org.dspace.content.Bundle.find(context, bundle.getID()).removeBitstream(dspaceBitstream);
|
||||
}
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not delete bitstream(id=" + bitstreamId + "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not delete bitstream(id=" + bitstreamId + "), AuthorizeException. Message: " + e, context);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not delete bitstream(id=" + bitstreamId + "), IOException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not delete bitstream(id=" + bitstreamId + "), ContextException. Message:" + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Bitstream(id=" + bitstreamId + ") was successfully deleted.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete policy.
|
||||
*
|
||||
* @param bitstreamId
|
||||
* Id of bitstream in dspace, which policy will be deleted.
|
||||
* @param policyId
|
||||
* Id of policy which will be deleted.
|
||||
* @param headers
|
||||
* If you want to access to item under logged user into context.
|
||||
* In headers must be set header "rest-dspace-token" with passed
|
||||
* token from login method.
|
||||
* @return It returns Ok, if was all ok. Otherwise status code 500.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{bitstream_id}/policy/{policy_id}")
|
||||
public javax.ws.rs.core.Response deleteBitstreamPolicy(@PathParam("bitstream_id") Integer bitstreamId,
|
||||
@PathParam("policy_id") Integer policyId, @Context HttpHeaders headers)
|
||||
{
|
||||
|
||||
log.info("Deleting bitstream(id=" + bitstreamId + ") READ policy(id=" + policyId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Bitstream dspaceBitstream = findBitstream(context, bitstreamId, org.dspace.core.Constants.READ);
|
||||
|
||||
Bundle[] bundles = dspaceBitstream.getBundles();
|
||||
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
List<org.dspace.authorize.ResourcePolicy> bitstreamsPolicies = bundle.getBitstreamPolicies();
|
||||
|
||||
for (org.dspace.authorize.ResourcePolicy policy : bitstreamsPolicies)
|
||||
{
|
||||
if (policy.getID() == policyId.intValue())
|
||||
{
|
||||
bitstreamsPolicies.remove(policy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bundle.replaceAllBitstreamPolicies(bitstreamsPolicies);
|
||||
bundle.update();
|
||||
}
|
||||
|
||||
context.complete();
|
||||
log.trace("Policy for bitsream(id=" + bitstreamId + ") was successfully added.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Someting went wrong while deleting READ policy(id=" + policyId + ") to bitstream(id=" + bitstreamId
|
||||
+ "), SQLException! Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Someting went wrong while deleting READ policy(id=" + policyId + ") to bitstream(id=" + bitstreamId
|
||||
+ "), ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Someting went wrong while deleting READ policy(id=" + policyId + ") to bitstream(id=" + bitstreamId
|
||||
+ "), AuthorizeException! Message: " + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return Response.status(Status.OK).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of file in MIME, by file extension.
|
||||
*
|
||||
* @param name
|
||||
* Name of file.
|
||||
* @return String filled with type of file in MIME style.
|
||||
*/
|
||||
static String getMimeType(String name)
|
||||
{
|
||||
return URLConnection.guessContentTypeFromName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find bitstream from DSpace database. It is encapsulation of method
|
||||
* org.dspace.content.Bitstream.find with checking if item exist and if user
|
||||
* logged into context has permission to do passed action.
|
||||
*
|
||||
* @param context
|
||||
* Context of actual logged user.
|
||||
* @param id
|
||||
* Id of bitstream in DSpace.
|
||||
* @param action
|
||||
* Constant from org.dspace.core.Constants.
|
||||
* @return It returns DSpace bitstream.
|
||||
* @throws WebApplicationException
|
||||
* Is thrown when item with passed id is not exists and if user
|
||||
* has no permission to do passed action.
|
||||
*/
|
||||
private org.dspace.content.Bitstream findBitstream(org.dspace.core.Context context, int id, int action)
|
||||
throws WebApplicationException
|
||||
{
|
||||
org.dspace.content.Bitstream bitstream = null;
|
||||
try
|
||||
{
|
||||
bitstream = org.dspace.content.Bitstream.find(context, id);
|
||||
|
||||
if ((bitstream == null) || (bitstream.getParentObject() == null))
|
||||
{
|
||||
context.abort();
|
||||
log.warn("Bitstream(id=" + id + ") was not found!");
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
else if (!AuthorizeManager.authorizeActionBoolean(context, bitstream, action))
|
||||
{
|
||||
context.abort();
|
||||
if (context.getCurrentUser() != null)
|
||||
{
|
||||
log.error("User(" + context.getCurrentUser().getEmail() + ") has not permission to "
|
||||
+ getActionString(action) + " bitstream!");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("User(anonymous) has not permission to " + getActionString(action) + " bitsteam!");
|
||||
}
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something get wrong while finding bitstream. SQLException, Message:" + e, context);
|
||||
}
|
||||
return bitstream;
|
||||
}
|
||||
}
|
||||
|
@@ -7,149 +7,767 @@
|
||||
*/
|
||||
package org.dspace.rest;
|
||||
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.rest.common.Collection;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
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:
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
http://localhost:8080/<webapp>/collections
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.browse.BrowseException;
|
||||
import org.dspace.rest.common.Collection;
|
||||
import org.dspace.rest.common.Item;
|
||||
import org.dspace.rest.common.MetadataEntry;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
|
||||
/**
|
||||
* This class provides all CRUD operation over collections.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*/
|
||||
@Path("/collections")
|
||||
public class CollectionsResource {
|
||||
public class CollectionsResource extends Resource
|
||||
{
|
||||
private static Logger log = Logger.getLogger(CollectionsResource.class);
|
||||
|
||||
@javax.ws.rs.core.Context ServletContext servletContext;
|
||||
|
||||
private static final boolean writeStatistics;
|
||||
|
||||
static{
|
||||
writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false);
|
||||
}
|
||||
|
||||
@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) {
|
||||
org.dspace.core.Context context = null;
|
||||
try {
|
||||
context = new org.dspace.core.Context();
|
||||
|
||||
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);
|
||||
} finally {
|
||||
if(context != null) {
|
||||
try {
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage() + " occurred while trying to close");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of collection with passed id. You can add more properties
|
||||
* through expand parameter.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection in DSpace.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of collection. Options are: "all", "parentCommunityList",
|
||||
* "parentCommunity", "items", "license" and "logo". If you want
|
||||
* to use multiple options, it must be separated by commas.
|
||||
* @param limit
|
||||
* Limit value for items in list in collection. Default value is
|
||||
* 100.
|
||||
* @param offset
|
||||
* Offset of start index in list of items of collection. Default
|
||||
* value is 0.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of collection. It can also return status code
|
||||
* NOT_FOUND(404) if id of collection is incorrect or status code
|
||||
* UNATHORIZED(401) if user has no permission to read collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException). It is thrown by NOT_FOUND and
|
||||
* UNATHORIZED status codes, too.
|
||||
*/
|
||||
@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,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) {
|
||||
org.dspace.core.Context context = null;
|
||||
try {
|
||||
context = new org.dspace.core.Context();
|
||||
public org.dspace.rest.common.Collection getCollection(@PathParam("collection_id") Integer collectionId,
|
||||
@QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit,
|
||||
@QueryParam("offset") @DefaultValue("0") Integer offset, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading collection(id=" + collectionId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
Collection collection = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId, org.dspace.core.Constants.READ);
|
||||
writeStats(dspaceCollection, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
collection = new Collection(dspaceCollection, expand, context, limit, offset);
|
||||
context.complete();
|
||||
|
||||
org.dspace.content.Collection collection = org.dspace.content.Collection.find(context, collection_id);
|
||||
if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) {
|
||||
if(writeStatistics){
|
||||
writeStats(context, collection_id, user_ip, user_agent, xforwarderfor, headers, request);
|
||||
}
|
||||
return new org.dspace.rest.common.Collection(collection, expand, context, limit, offset);
|
||||
} else {
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read collection(id=" + collectionId + "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read collection(id=" + collectionId + "), ContextException. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("Collection(id=" + collectionId + ") has been successfully read.");
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of all collections in DSpace. You can add more properties
|
||||
* through expand parameter.
|
||||
*
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of collection. Options are: "all", "parentCommunityList",
|
||||
* "parentCommunity", "items", "license" and "logo". If you want
|
||||
* to use multiple options, it must be separated by commas.
|
||||
* @param limit
|
||||
* Limit value for items in list in collection. Default value is
|
||||
* 100.
|
||||
* @param offset
|
||||
* Offset of start index in list of items of collection. Default
|
||||
* value is 0.
|
||||
* @param headers
|
||||
* If you want to access to collections under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return array of collection, on which has logged user permission
|
||||
* to view.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException).
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public org.dspace.rest.common.Collection[] getCollections(@QueryParam("expand") String expand,
|
||||
@QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading all collections.(offset=" + offset + ",limit=" + limit + ")");
|
||||
org.dspace.core.Context context = null;
|
||||
List<Collection> collections = new ArrayList<Collection>();
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
if (!((limit != null) && (limit >= 0) && (offset != null) && (offset >= 0)))
|
||||
{
|
||||
log.warn("Paging was badly set.");
|
||||
limit = 100;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
org.dspace.content.Collection[] dspaceCollections = org.dspace.content.Collection.findAll(context, limit, offset);
|
||||
for(org.dspace.content.Collection dspaceCollection : dspaceCollections)
|
||||
{
|
||||
if (AuthorizeManager.authorizeActionBoolean(context, dspaceCollection, org.dspace.core.Constants.READ))
|
||||
{
|
||||
Collection collection = new org.dspace.rest.common.Collection(dspaceCollection, null, context, limit,
|
||||
offset);
|
||||
collections.add(collection);
|
||||
writeStats(dspaceCollection, UsageEvent.Action.VIEW, user_ip, user_agent,
|
||||
xforwarderfor, headers, request);
|
||||
}
|
||||
}
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something went wrong while reading collections from database. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Something went wrong while reading collections, ContextError. Message: " + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("All collections were successfully read.");
|
||||
return collections.toArray(new org.dspace.rest.common.Collection[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of items in collection. You can add more properties to items
|
||||
* with expand parameter.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection in DSpace.
|
||||
* @param expand
|
||||
* String which define, what additional properties will be in
|
||||
* returned item. Options are separeted by commas and are: "all",
|
||||
* "metadata", "parentCollection", "parentCollectionList",
|
||||
* "parentCommunityList" and "bitstreams".
|
||||
* @param limit
|
||||
* Limit value for items in array. Default value is 100.
|
||||
* @param offset
|
||||
* Offset of start index in array of items of collection. Default
|
||||
* value is 0.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return array of items, on which has logged user permission to
|
||||
* read. It can also return status code NOT_FOUND(404) if id of
|
||||
* collection is incorrect or status code UNATHORIZED(401) if user
|
||||
* has no permission to read collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException). It is thrown by NOT_FOUND and
|
||||
* UNATHORIZED status codes, too.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{collection_id}/items")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public org.dspace.rest.common.Item[] getCollectionItems(@PathParam("collection_id") Integer collectionId,
|
||||
@QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit,
|
||||
@QueryParam("offset") @DefaultValue("0") Integer offset, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading collection(id=" + collectionId + ") items.");
|
||||
org.dspace.core.Context context = null;
|
||||
List<Item> items = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId, org.dspace.core.Constants.READ);
|
||||
writeStats(dspaceCollection, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
items = new ArrayList<Item>();
|
||||
org.dspace.content.ItemIterator dspaceItems = dspaceCollection.getItems();
|
||||
for (int i = 0; (dspaceItems.hasNext()) && (i < (limit + offset)); i++)
|
||||
{
|
||||
if (i >= offset)
|
||||
{
|
||||
org.dspace.content.Item dspaceItem = dspaceItems.next();
|
||||
if (AuthorizeManager.authorizeActionBoolean(context, dspaceItem, org.dspace.core.Constants.READ))
|
||||
{
|
||||
items.add(new Item(dspaceItem, expand, context));
|
||||
writeStats(dspaceItem, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read collection items, SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read collection items, ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("All items in collection(id=" + collectionId + ") were successfully read.");
|
||||
return items.toArray(new Item[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create item in collection. Item can be without filled metadata.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection in which will be item created.
|
||||
* @param item
|
||||
* Item filled only with metadata, other variables are ignored.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return status code with item. Return status (OK)200 if item was
|
||||
* created. NOT_FOUND(404) if id of collection does not exists.
|
||||
* UNAUTHORIZED(401) if user have not permission to write items in
|
||||
* collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading or
|
||||
* writing (SQLException) or problem with creating
|
||||
* context(ContextException) or problem with authorization to
|
||||
* collection or IOException or problem with index item into
|
||||
* browse index. It is thrown by NOT_FOUND and UNATHORIZED
|
||||
* status codes, too.
|
||||
*
|
||||
*/
|
||||
@POST
|
||||
@Path("/{collection_id}/items")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Item addCollectionItem(@PathParam("collection_id") Integer collectionId, Item item,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Create item in collection(id=" + collectionId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
Item returnItem = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId,
|
||||
org.dspace.core.Constants.WRITE);
|
||||
|
||||
writeStats(dspaceCollection, UsageEvent.Action.UPDATE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
log.trace("Creating item in collection(id=" + collectionId + ").");
|
||||
org.dspace.content.WorkspaceItem workspaceItem = org.dspace.content.WorkspaceItem.create(context, dspaceCollection,
|
||||
false);
|
||||
org.dspace.content.Item dspaceItem = workspaceItem.getItem();
|
||||
|
||||
log.trace("Adding metadata to item(id=" + dspaceItem.getID() + ").");
|
||||
if (item.getMetadata() != null)
|
||||
{
|
||||
for (MetadataEntry entry : item.getMetadata())
|
||||
{
|
||||
String data[] = mySplit(entry.getKey());
|
||||
dspaceItem.addMetadata(data[0], data[1], data[2], entry.getLanguage(), entry.getValue());
|
||||
}
|
||||
}
|
||||
workspaceItem.update();
|
||||
|
||||
// Index item to browse.
|
||||
org.dspace.browse.IndexBrowse browse = new org.dspace.browse.IndexBrowse();
|
||||
browse.indexItem(dspaceItem);
|
||||
|
||||
log.trace("Installing item to collection(id=" + collectionId + ").");
|
||||
dspaceItem = org.dspace.content.InstallItem.installItem(context, workspaceItem);
|
||||
|
||||
returnItem = new Item(dspaceItem, "", context);
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not add item into collection(id=" + collectionId + "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not add item into collection(id=" + collectionId + "), AuthorizeException. Message: " + e,
|
||||
context);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not add item into collection(id=" + collectionId + "), IOException. Message: " + e, context);
|
||||
}
|
||||
catch (BrowseException e)
|
||||
{
|
||||
processException("Could not add item into browse index, BrowseException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException(
|
||||
"Could not add item into collection(id=" + collectionId + "), ContextException. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Item successfully created in collection(id=" + collectionId + "). Item handle=" + returnItem.getHandle());
|
||||
return returnItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update collection. It replace all properties.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection in DSpace.
|
||||
* @param collection
|
||||
* Collection which will replace properties of actual collection.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response 200 if was everything all right. Otherwise 400
|
||||
* when id of community was incorrect or 401 if was problem with
|
||||
* permission to write into collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading or
|
||||
* writing. Or problem with authorization to collection. Or
|
||||
* problem with creating context.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{collection_id}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response updateCollection(@PathParam("collection_id") Integer collectionId,
|
||||
org.dspace.rest.common.Collection collection, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Updating collection(id=" + collectionId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId,
|
||||
org.dspace.core.Constants.WRITE);
|
||||
|
||||
writeStats(dspaceCollection, UsageEvent.Action.UPDATE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
dspaceCollection.setMetadata("name", collection.getName());
|
||||
dspaceCollection.setLicense(collection.getLicense());
|
||||
// dspaceCollection.setLogo(collection.getLogo()); // TODO Add this option.
|
||||
dspaceCollection.setMetadata(org.dspace.content.Collection.COPYRIGHT_TEXT, collection.getCopyrightText());
|
||||
dspaceCollection.setMetadata(org.dspace.content.Collection.INTRODUCTORY_TEXT, collection.getIntroductoryText());
|
||||
dspaceCollection.setMetadata(org.dspace.content.Collection.SHORT_DESCRIPTION, collection.getShortDescription());
|
||||
dspaceCollection.setMetadata(org.dspace.content.Collection.SIDEBAR_TEXT, collection.getSidebarText());
|
||||
dspaceCollection.update();
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not update collection(id=" + collectionId + "), ContextEception. Message: " + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not update collection(id=" + collectionId + "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not update collection(id=" + collectionId + "), AuthorizeException. Message: " + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Collection(id=" + collectionId + ") successfully updated.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete collection.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection which will be deleted.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response code OK(200) if was everything all right.
|
||||
* Otherwise return NOT_FOUND(404) if was id of community or
|
||||
* collection incorrect. Or (UNAUTHORIZED)401 if was problem with
|
||||
* permission to community or collection.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading or writing. Or problem with deleting
|
||||
* collection caused by IOException or authorization.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{collection_id}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response deleteCollection(@PathParam("collection_id") Integer collectionId, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Delete collection(id=" + collectionId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId,
|
||||
org.dspace.core.Constants.DELETE);
|
||||
|
||||
writeStats(dspaceCollection, UsageEvent.Action.REMOVE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
|
||||
org.dspace.content.Community community = (org.dspace.content.Community) dspaceCollection.getParentObject();
|
||||
community.removeCollection(dspaceCollection);
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException(
|
||||
"Could not delete collection(id=" + collectionId + "), ContextExcpetion. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not delete collection(id=" + collectionId + "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not delete collection(id=" + collectionId + "), AuthorizeException. Message: " + e, context);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not delete collection(id=" + collectionId + "), IOException. Message: " + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Collection(id=" + collectionId + ") was successfully deleted.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item in collection.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection which will be deleted.
|
||||
*
|
||||
* @param itemId
|
||||
* Id of item in colletion.
|
||||
* @return It returns status code: OK(200). NOT_FOUND(404) if item or
|
||||
* collection was not found, UNAUTHORIZED(401) if user is not
|
||||
* allowed to delete item or permission to write into collection.
|
||||
* @throws WebApplicationException
|
||||
* It can be thrown by: SQLException, when was problem with
|
||||
* database reading or writting. AuthorizeException, when was
|
||||
* problem with authorization to item or collection.
|
||||
* IOException, when was problem with removing item.
|
||||
* ContextException, when was problem with creating context of
|
||||
* DSpace.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{collection_id}/items/{item_id}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response deleteCollectionItem(@PathParam("collection_id") Integer collectionId, @PathParam("item_id") Integer itemId,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Delete item(id=" + itemId + ") in collection(id=" + collectionId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Collection dspaceCollection = findCollection(context, collectionId,
|
||||
org.dspace.core.Constants.WRITE);
|
||||
|
||||
org.dspace.content.Item item = null;
|
||||
org.dspace.content.ItemIterator dspaceItems = dspaceCollection.getItems();
|
||||
while (dspaceItems.hasNext())
|
||||
{
|
||||
org.dspace.content.Item dspaceItem = dspaceItems.next();
|
||||
if (dspaceItem.getID() == itemId)
|
||||
{
|
||||
item = dspaceItem;
|
||||
}
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
context.abort();
|
||||
log.warn("Item(id=" + itemId + ") was not found!");
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
else if (!AuthorizeManager.authorizeActionBoolean(context, item, org.dspace.core.Constants.REMOVE))
|
||||
{
|
||||
context.abort();
|
||||
if (context.getCurrentUser() != null)
|
||||
{
|
||||
log.error("User(" + context.getCurrentUser().getEmail() + ") has not permission to delete item!");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("User(anonymous) has not permission to delete item!");
|
||||
}
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage());
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
if(context != null) {
|
||||
try {
|
||||
|
||||
writeStats(dspaceCollection, UsageEvent.Action.UPDATE, user_ip, user_agent, xforwarderfor,
|
||||
headers, request);
|
||||
writeStats(item, UsageEvent.Action.REMOVE, user_ip, user_agent, xforwarderfor, headers, request);
|
||||
|
||||
dspaceCollection.removeItem(item);
|
||||
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage() + " occurred while trying to close");
|
||||
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not delete item(id=" + itemId + ") in collection(id=" + collectionId
|
||||
+ "), ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not delete item(id=" + itemId + ") in collection(id=" + collectionId
|
||||
+ "), SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not delete item(id=" + itemId + ") in collection(id=" + collectionId
|
||||
+ "), AuthorizeException. Message: " + e, context);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
processException("Could not delete item(id=" + itemId + ") in collection(id=" + collectionId
|
||||
+ "), IOException. Message: " + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Item(id=" + itemId + ") in collection(id=" + collectionId + ") was successfully deleted.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for first collection with passed name.
|
||||
*
|
||||
* @param name
|
||||
* Name of collection.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return It returns null if collection was not found. Otherwise returns
|
||||
* first founded collection.
|
||||
* @throws WebApplicationException
|
||||
*/
|
||||
@POST
|
||||
@Path("/find-collection")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Collection findCollectionByName(String name, @Context HttpHeaders headers) throws WebApplicationException
|
||||
{
|
||||
log.info("Searching for first collection with name=" + name + ".");
|
||||
org.dspace.core.Context context = null;
|
||||
Collection collection = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
org.dspace.content.Collection[] dspaceCollections;
|
||||
|
||||
dspaceCollections = org.dspace.content.Collection.findAll(context);
|
||||
|
||||
for (org.dspace.content.Collection dspaceCollection : dspaceCollections)
|
||||
{
|
||||
if (AuthorizeManager.authorizeActionBoolean(context, dspaceCollection, org.dspace.core.Constants.READ))
|
||||
{
|
||||
if (dspaceCollection.getName().equals(name))
|
||||
{
|
||||
collection = new Collection(dspaceCollection, "", context, 100, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStats(org.dspace.core.Context context, Integer collection_id, String user_ip, String user_agent,
|
||||
String xforwarderfor, HttpHeaders headers,
|
||||
HttpServletRequest request) {
|
||||
context.complete();
|
||||
|
||||
try{
|
||||
DSpaceObject collection = DSpaceObject.find(context, Constants.COLLECTION, collection_id);
|
||||
|
||||
if(user_ip==null || user_ip.length()==0){
|
||||
new DSpace().getEventService().fireEvent(
|
||||
new UsageEvent(
|
||||
UsageEvent.Action.VIEW,
|
||||
request,
|
||||
context,
|
||||
collection));
|
||||
} else{
|
||||
new DSpace().getEventService().fireEvent(
|
||||
new UsageEvent(
|
||||
UsageEvent.Action.VIEW,
|
||||
user_ip,
|
||||
user_agent,
|
||||
xforwarderfor,
|
||||
context,
|
||||
collection));
|
||||
}
|
||||
log.debug("fired event");
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something went wrong while searching for collection(name=" + name + ") from database. Message: "
|
||||
+ e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Something went wrong while searching for collection(name=" + name + "), ContextError. Message: "
|
||||
+ e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
} catch(SQLException ex){
|
||||
log.error("SQL exception can't write usageEvent \n" + ex);
|
||||
if (collection == null)
|
||||
{
|
||||
log.info("Collection was not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Collection was found with id(" + collection.getId() + ").");
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find collection from DSpace database. It is encapsulation of method
|
||||
* org.dspace.content.Collection.find with checking if item exist and if
|
||||
* user logged into context has permission to do passed action.
|
||||
*
|
||||
* @param context
|
||||
* Context of actual logged user.
|
||||
* @param id
|
||||
* Id of collection in DSpace.
|
||||
* @param action
|
||||
* Constant from org.dspace.core.Constants.
|
||||
* @return It returns DSpace collection.
|
||||
* @throws WebApplicationException
|
||||
* Is thrown when item with passed id is not exists and if user
|
||||
* has no permission to do passed action.
|
||||
*/
|
||||
private org.dspace.content.Collection findCollection(org.dspace.core.Context context, int id, int action)
|
||||
throws WebApplicationException
|
||||
{
|
||||
org.dspace.content.Collection collection = null;
|
||||
try
|
||||
{
|
||||
collection = org.dspace.content.Collection.find(context, id);
|
||||
|
||||
if (collection == null)
|
||||
{
|
||||
context.abort();
|
||||
log.warn("Collection(id=" + id + ") was not found!");
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
else if (!AuthorizeManager.authorizeActionBoolean(context, collection, action))
|
||||
{
|
||||
context.abort();
|
||||
if (context.getCurrentUser() != null)
|
||||
{
|
||||
log.error("User(" + context.getCurrentUser().getEmail() + ") has not permission to "
|
||||
+ getActionString(action) + " collection!");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("User(anonymous) has not permission to " + getActionString(action) + " collection!");
|
||||
}
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something get wrong while finding collection(id=" + id + "). SQLException, Message: " + e, context);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,14 +32,18 @@ import java.sql.SQLException;
|
||||
@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) {
|
||||
org.dspace.core.Context context = null;
|
||||
try {
|
||||
context = new org.dspace.core.Context();
|
||||
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) {
|
||||
@@ -64,14 +68,6 @@ public class HandleResource {
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage());
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
if(context != null) {
|
||||
try {
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage() + " occurred while trying to close");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
292
dspace-rest/src/main/java/org/dspace/rest/Resource.java
Normal file
292
dspace-rest/src/main/java/org/dspace/rest/Resource.java
Normal file
@@ -0,0 +1,292 @@
|
||||
/**
|
||||
* 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 java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
* Superclass of all resource class in REST api. It has methods for creating
|
||||
* context, write statistics, process exception, splitting key of metadata,
|
||||
* string representation of action and method for getting user from header.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*
|
||||
*/
|
||||
public class Resource
|
||||
{
|
||||
|
||||
private static Logger log = Logger.getLogger(Resource.class);
|
||||
|
||||
private static final boolean writeStatistics;
|
||||
static
|
||||
{
|
||||
writeStatistics = ConfigurationManager.getBooleanProperty("rest", "stats", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create context to work with DSpace database. It can create context
|
||||
* without logged user (parameter user is null) or with. It can throws
|
||||
* WebApplicationException caused by: SQLException, if there was problem
|
||||
* with reading from database. AuthorizeException, if there was problem with
|
||||
* authorization to read form database. And Exception, if there was some
|
||||
* problem with creating context.
|
||||
*
|
||||
* @param person
|
||||
* User which will be logged in context.
|
||||
* @return New created context with logged user if user was not null.
|
||||
* Otherwise, without logged user.
|
||||
* @throws ContextException
|
||||
* Throw if was problem to create context. It can be caused by
|
||||
* SQLException, error in creating context or find user to log
|
||||
* in. Or can be caused by AuthorizeException if was problem to
|
||||
* authorize to find user.
|
||||
*/
|
||||
protected static org.dspace.core.Context createContext(EPerson person) throws ContextException
|
||||
{
|
||||
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = new org.dspace.core.Context();
|
||||
context.getDBConnection().setAutoCommit(false); // Disable autocommit.
|
||||
|
||||
if (person != null)
|
||||
{
|
||||
context.setCurrentUser(person);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
}
|
||||
throw new ContextException("Could not create context, SQLException. Message: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It write statistic about using REST api.
|
||||
* @param dspaceObject
|
||||
* Object of DSpace which is performed.
|
||||
* @param action
|
||||
* What action is performed with object.
|
||||
* @param user_ip
|
||||
* @param user_agent
|
||||
* @param xforwarderfor
|
||||
* @param headers
|
||||
* @param request
|
||||
*/
|
||||
protected void writeStats(DSpaceObject dspaceObject, UsageEvent.Action action,
|
||||
String user_ip, String user_agent, String xforwarderfor, HttpHeaders headers, HttpServletRequest request)
|
||||
{
|
||||
|
||||
if (!writeStatistics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
if ((user_ip == null) || (user_ip.length() == 0))
|
||||
{
|
||||
new DSpace().getEventService().fireEvent(new UsageEvent(action, request, context, dspaceObject));
|
||||
}
|
||||
else
|
||||
{
|
||||
new DSpace().getEventService().fireEvent(
|
||||
new UsageEvent(action, user_ip, user_agent, xforwarderfor, context, dspaceObject));
|
||||
}
|
||||
|
||||
log.debug("fired event");
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
}
|
||||
log.error("Could not write usageEvent, SQLException. Message: " + e);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
log.error("Could not write usageEvent, ContextException. Message: " + e.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
log.error("Something get wrong. Aborting context in finally statement.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process exception, print message to logger error stream and abort DSpace
|
||||
* context.
|
||||
*
|
||||
* @param message
|
||||
* Message, which will be printed to error stream.
|
||||
* @param context
|
||||
* Context which must be aborted.
|
||||
* @throws WebApplicationException
|
||||
* This exception is throw for user of REST api.
|
||||
*/
|
||||
protected static void processException(String message, org.dspace.core.Context context) throws WebApplicationException
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
}
|
||||
log.error(message);
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process finally statement. It will print message to logger error stream
|
||||
* and abort DSpace context, if was not properly ended.
|
||||
*
|
||||
* @param context
|
||||
* Context which must be aborted.
|
||||
* @throws WebApplicationException
|
||||
* This exception is throw for user of REST api.
|
||||
*/
|
||||
protected void processFinally(org.dspace.core.Context context) throws WebApplicationException
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
log.error("Something get wrong. Aborting context in finally statement.");
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split string with regex ".".
|
||||
*
|
||||
* @param key
|
||||
* String which will be splitted.
|
||||
* @return String array filed with separated string.
|
||||
*/
|
||||
protected String[] mySplit(String key)
|
||||
{
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
int prev = 0;
|
||||
for (int i = 0; i < key.length(); i++)
|
||||
{
|
||||
if (key.charAt(i) == '.')
|
||||
{
|
||||
list.add(key.substring(prev, i));
|
||||
prev = i + 1;
|
||||
}
|
||||
else if (i + 1 == key.length())
|
||||
{
|
||||
list.add(key.substring(prev, i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (list.size() == 2)
|
||||
{
|
||||
list.add(null);
|
||||
}
|
||||
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation of values
|
||||
* org.dspace.core.Constants.{READ,WRITE,DELETE}.
|
||||
*
|
||||
* @param action
|
||||
* Constant from org.dspace.core.Constants.*
|
||||
* @return String representation. read or write or delete.
|
||||
*/
|
||||
protected String getActionString(int action)
|
||||
{
|
||||
String actionStr;
|
||||
switch (action)
|
||||
{
|
||||
case org.dspace.core.Constants.READ:
|
||||
actionStr = "read";
|
||||
break;
|
||||
case org.dspace.core.Constants.WRITE:
|
||||
actionStr = "write";
|
||||
break;
|
||||
case org.dspace.core.Constants.DELETE:
|
||||
actionStr = "delete";
|
||||
break;
|
||||
case org.dspace.core.Constants.REMOVE:
|
||||
actionStr = "remove";
|
||||
break;
|
||||
case org.dspace.core.Constants.ADD:
|
||||
actionStr = "add";
|
||||
break;
|
||||
default:
|
||||
actionStr = "(?action?)";
|
||||
break;
|
||||
}
|
||||
return actionStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EPerson based on stored token in headers under
|
||||
* "rest-dspace-token".
|
||||
*
|
||||
* @param headers
|
||||
* Only must have "rest-api-token" for successfull return of
|
||||
* user.
|
||||
* @return Return EPerson logged under token in headers. If token was wrong
|
||||
* or header rest-dspace-token was missing, returns null.
|
||||
*/
|
||||
protected static EPerson getUser(HttpHeaders headers)
|
||||
{
|
||||
List<String> list = headers.getRequestHeader(TokenHolder.TOKEN_HEADER);
|
||||
String token = null;
|
||||
if ((list != null) && (list.size() > 0))
|
||||
{
|
||||
token = list.get(0);
|
||||
return TokenHolder.getEPerson(token);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static String getToken(HttpHeaders headers) {
|
||||
List<String> list = headers.getRequestHeader(TokenHolder.TOKEN_HEADER);
|
||||
String token = null;
|
||||
if ((list != null) && (list.size() > 0))
|
||||
{
|
||||
token = list.get(0);
|
||||
return token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -7,39 +7,229 @@
|
||||
*/
|
||||
package org.dspace.rest;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/*
|
||||
Root of API, should have documentation on where to find the other resources.
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.rest.common.Status;
|
||||
import org.dspace.rest.common.User;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
|
||||
/**
|
||||
* Root of RESTful api. It provides login and logout. Also have method for
|
||||
* printing every method which is provides by RESTful api.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*
|
||||
*/
|
||||
@Path("/")
|
||||
public class RestIndex {
|
||||
private static Logger log = Logger.getLogger(RestIndex.class);
|
||||
|
||||
@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.
|
||||
/**
|
||||
* Return html page with information about REST api. It contains methods all
|
||||
* methods provide by REST api.
|
||||
*
|
||||
* @return HTML page which has information about all methods of REST api.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.TEXT_HTML)
|
||||
public String sayHtmlHello() {
|
||||
return "<html><title>DSpace REST</title>" +
|
||||
"<body><h1>DSpace REST API</h1>" +
|
||||
// TODO Better graphics, add arguments to all methods. (limit, offset, item and so on)
|
||||
return "<html><title>DSpace REST - index</title>" +
|
||||
"<body>"
|
||||
+ "<h1>DSpace REST API</h1>" +
|
||||
"Server path: " + servletContext.getContextPath() +
|
||||
"<h2>Index</h2>" +
|
||||
"<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>" +
|
||||
"<li>GET / - It returns this page.</li>" +
|
||||
"<li>GET /test - Return string \"REST api is running\". It is method for testing.</li>" +
|
||||
"<li>POST /login - Method for login into DSpace RESTful api. You must post User class. Example: {\"email\":\"test@dspace\",\"password\":\"pass\"}. It returns token under which will must sending requests. In header \"rest-dspace-token\"</li>" +
|
||||
"<li>POST /logout - Method for logout from DSpace RESTful api. You must post request with header \"rest-dspace-token\" token</li>" +
|
||||
"</ul>" +
|
||||
"<h2>Communities</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /communities - Returns array of all communities in DSpace.</li>" +
|
||||
"<li>GET /communities/top-communities - Returns array of all top communities in DSpace.</li>" +
|
||||
"<li>GET /communities/{communityId} - Returns community.</li>" +
|
||||
"<li>GET /communities/{communityId}/collections - Returns array of collections of community.</li>" +
|
||||
"<li>GET /communities/{communityId}/communities - Returns array of subcommunities of community.</li>" +
|
||||
"<li>POST /communities - Create new community at top level. You must post community.</li>" +
|
||||
"<li>POST /communities/{communityId}/collections - Create new collections in community. You must post collection.</li>" +
|
||||
"<li>POST /communities/{communityId}/communities - Create new subcommunity in community. You must post community.</li>" +
|
||||
"<li>PUT /communities/{communityId} - Update community.</li>" +
|
||||
"<li>DELETE /communities/{communityId} - Delete community.</li>" +
|
||||
"<li>DELETE /communities/{communityId}/collections/{collectionId} - Delete collection in community.</li>" +
|
||||
"<li>DELETE /communities/{communityId}/communities/{communityId2} - Delete subcommunity in community.</li>" +
|
||||
"</ul>" +
|
||||
"<h2>Collections</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /collections - Return all collections of DSpace in array.</li>" +
|
||||
"<li>GET /collections/{collectionId} - Return collection with id.</li>" +
|
||||
"<li>GET /collections/{collectionId}/items - Return all items of collection.</li>" +
|
||||
"<li>POST /collections/{collectionId}/items - Create posted item in collection.</li>" +
|
||||
"<li>POST /collections/find-collection - Find collection by passed name.</li>" +
|
||||
"<li>PUT /collections/{collectionId} </li> - Update collection. You muset post collection." +
|
||||
"<li>DELETE /collections/{collectionId} - Delete collection from DSpace.</li>" +
|
||||
"<li>DELETE /collections/{collectionId}/items/{itemId} - Delete item in collection. </li>" +
|
||||
"</ul>" +
|
||||
"<h2>Items</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /items - Return list of items.</li>" +
|
||||
"<li>GET /items/{item id} - Return item.</li>" +
|
||||
"<li>GET /items/{item id}/metadata - Return item metadata.</li>" +
|
||||
"<li>GET /items/{item id}/bitstreams - Return item bitstreams.</li>" +
|
||||
"<li>POST /items/find-by-metadata-field - Find items by metadata entry.</li>" +
|
||||
"<li>POST /items/{item id}/metadata - Add metadata to item.</li>" +
|
||||
"<li>POST /items/{item id}/bitstreams - Add bitstream to item.</li>" +
|
||||
"<li>PUT /items/{item id}/metadata - Update metadata in item.</li>" +
|
||||
"<li>DELETE /items/{item id} - Delete item.</li>" +
|
||||
"<li>DELETE /items/{item id}/metadata - Clear item metadata.</li>" +
|
||||
"<li>DELETE /items/{item id}/bitstreams/{bitstream id} - Delete item bitstream.</li>" +
|
||||
"</ul>" +
|
||||
"<h2>Bitstreams</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /bitstreams - Return all bitstreams in DSpace.</li>" +
|
||||
"<li>GET /bitstreams/{bitstream id} - Return bitstream.</li>" +
|
||||
"<li>GET /bitstreams/{bitstream id}/policy - Return bitstream policies.</li>" +
|
||||
"<li>POST /bitstreams/{bitstream id}/retrieve - Return data of bitstream.</li>" +
|
||||
"<li>POST /bitstreams/{bitstream id}/policy - Add policy to item.</li>" +
|
||||
"<li>PUT /bitstreams/{bitstream id}/data - Update data of bitstream.</li>" +
|
||||
"<li>PUT /bitstreams/{bitstream id} - Update metadata of bitstream.</li>" +
|
||||
"<li>DELETE /bitstreams/{bitstream id} - Delete bitstream from DSpace.</li>" +
|
||||
"<li>DELETE /bitstreams/{bitstream id}/policy/{policy_id} - Delete bitstream policy.</li>" +
|
||||
"</ul>" +
|
||||
"</body></html> ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for only test if rest api is running.
|
||||
*
|
||||
* @return String "REST api is running."
|
||||
*/
|
||||
@GET
|
||||
@Path("/test")
|
||||
public String test()
|
||||
{
|
||||
return "REST api is running.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for login user into REST api.
|
||||
*
|
||||
* @param user
|
||||
* User which will be logged into REST api.
|
||||
* @return Returns response code OK with token. Otherwise returns response
|
||||
* code FORBIDDEN(403).
|
||||
*/
|
||||
@POST
|
||||
@Path("/login")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response login(User user)
|
||||
{
|
||||
String token = TokenHolder.login(user);
|
||||
if (token == null)
|
||||
{
|
||||
log.info("REST Login Attempt failed for user: " + user.getEmail());
|
||||
return Response.status(Response.Status.FORBIDDEN).build();
|
||||
} else {
|
||||
log.info("REST Login Success for user: " + user.getEmail());
|
||||
return Response.ok(token, "text/plain").build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for logout from DSpace REST api. It removes token and user from
|
||||
* TokenHolder.
|
||||
*
|
||||
* @param headers
|
||||
* Request header which contains header with key
|
||||
* "rest-dspace-token" and value of token.
|
||||
* @return Return response OK, otherwise BAD_REQUEST, if was problem with
|
||||
* logout or token is incorrect.
|
||||
*/
|
||||
@POST
|
||||
@Path("/logout")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response logout(@Context HttpHeaders headers)
|
||||
{
|
||||
List<String> list = headers.getRequestHeader(TokenHolder.TOKEN_HEADER);
|
||||
String token = null;
|
||||
boolean logout = false;
|
||||
EPerson ePerson = null;
|
||||
if (list != null)
|
||||
{
|
||||
token = list.get(0);
|
||||
ePerson = TokenHolder.getEPerson(token);
|
||||
logout = TokenHolder.logout(token);
|
||||
}
|
||||
if ((token == null) || (!logout))
|
||||
{
|
||||
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
if(ePerson != null) {
|
||||
log.info("REST Logout: " + ePerson.getEmail());
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* ? status: OK
|
||||
* authenticated: TRUE | FALSE
|
||||
* epersonEMAIL: user@dspace.org
|
||||
* epersonNAME: Joe User
|
||||
* @param headers
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("/status")
|
||||
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
public Status status(@Context HttpHeaders headers) throws UnsupportedEncodingException {
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try {
|
||||
context = Resource.createContext(Resource.getUser(headers));
|
||||
EPerson ePerson = context.getCurrentUser();
|
||||
|
||||
if(ePerson != null) {
|
||||
//DB EPerson needed since token won't have full info, need context
|
||||
EPerson dbEPerson = EPerson.findByEmail(context, ePerson.getEmail());
|
||||
String token = Resource.getToken(headers);
|
||||
Status status = new Status(dbEPerson.getEmail(), dbEPerson.getFullName(), token);
|
||||
return status;
|
||||
}
|
||||
|
||||
} catch (ContextException e)
|
||||
{
|
||||
Resource.processException("Status context error: " + e.getMessage(), context);
|
||||
} catch (SQLException e) {
|
||||
Resource.processException("Status eperson db lookup error: " + e.getMessage(), context);
|
||||
} catch (AuthorizeException e) {
|
||||
Resource.processException("Status eperson authorize exception: " + e.getMessage(), context);
|
||||
} finally {
|
||||
context.abort();
|
||||
}
|
||||
|
||||
//fallback status, unauth
|
||||
return new Status();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
154
dspace-rest/src/main/java/org/dspace/rest/TokenHolder.java
Normal file
154
dspace-rest/src/main/java/org/dspace/rest/TokenHolder.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 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 java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.rest.common.User;
|
||||
|
||||
/**
|
||||
* This class provide token generation, token holding and logging user into rest
|
||||
* api. For login use method login with class org.dspace.rest.common.User. If
|
||||
* you want to be deleted from holder, use method for logout.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*/
|
||||
public class TokenHolder
|
||||
{
|
||||
|
||||
private static final Logger log = Logger.getLogger(TokenHolder.class);
|
||||
|
||||
public static String TOKEN_HEADER = "rest-dspace-token";
|
||||
|
||||
private static Map<String, String> tokens = new HashMap<String, String>(); // Map with pair Email,token
|
||||
|
||||
private static Map<String, EPerson> persons = new HashMap<String, EPerson>(); // Map with pair token,Eperson
|
||||
|
||||
/**
|
||||
* Login user into rest api. It check user credentials if they are okay.
|
||||
*
|
||||
* @param user
|
||||
* User which will be logged into rest api.
|
||||
* @return Returns generated token, which must be used in request header
|
||||
* under rest-api-token. If password is bad or user does not exist,
|
||||
* it returns NULL.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown by SQLException if user could not be read from
|
||||
* database. And by Authorization exception if context has not
|
||||
* permission to read eperson.
|
||||
*/
|
||||
public static String login(User user) throws WebApplicationException
|
||||
{
|
||||
org.dspace.core.Context context = null;
|
||||
String token = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = new org.dspace.core.Context();
|
||||
EPerson dspaceUser = EPerson.findByEmail(context, user.getEmail());
|
||||
|
||||
if ((dspaceUser == null) || (!dspaceUser.checkPassword(user.getPassword())))
|
||||
{
|
||||
token = null;
|
||||
}
|
||||
else if (tokens.containsKey(user.getEmail()))
|
||||
{
|
||||
token = tokens.get(user.getEmail());
|
||||
}
|
||||
else
|
||||
{
|
||||
token = generateToken();
|
||||
persons.put(token, dspaceUser);
|
||||
tokens.put(user.getEmail(), token);
|
||||
}
|
||||
|
||||
log.trace("User(" + user.getEmail() + ") has been logged.");
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
context.abort();
|
||||
log.error("Could not read user from database. Message:" + e);
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
context.abort();
|
||||
log.error("Could not find user, AuthorizeException. Message:" + e);
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ((context != null) && (context.isValid()))
|
||||
{
|
||||
context.abort();
|
||||
log.error("Something get wrong. Aborting context in finally statement.");
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EPerson for log into context.
|
||||
*
|
||||
* @param token
|
||||
* Token under which is stored eperson.
|
||||
* @return Return instance of EPerson if is token right, otherwise it
|
||||
* returns NULL.
|
||||
*/
|
||||
public static EPerson getEPerson(String token)
|
||||
{
|
||||
return persons.get(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout user from rest api. It delete token and EPerson from TokenHolder.
|
||||
*
|
||||
* @param token
|
||||
* Token under which is stored eperson.
|
||||
* @return Return true if was all okay, otherwise return false.
|
||||
*/
|
||||
public static boolean logout(String token)
|
||||
{
|
||||
if ((token == null) || (persons.get(token) == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String email = persons.get(token).getEmail();
|
||||
EPerson person = persons.remove(token);
|
||||
if (person == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tokens.remove(email);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* It generates unique token.
|
||||
*
|
||||
* @return String filled with unique token.
|
||||
*/
|
||||
private static String generateToken()
|
||||
{
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
}
|
@@ -7,15 +7,17 @@
|
||||
*/
|
||||
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;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.core.Constants;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: peterdietz
|
||||
@@ -37,6 +39,8 @@ public class Bitstream extends DSpaceObject {
|
||||
private CheckSum checkSum;
|
||||
private Integer sequenceId;
|
||||
|
||||
private ResourcePolicy[] policies = null;
|
||||
|
||||
public Bitstream() {
|
||||
|
||||
}
|
||||
@@ -72,8 +76,22 @@ public class Bitstream extends DSpaceObject {
|
||||
|
||||
if(expandFields.contains("parent") || expandFields.contains("all")) {
|
||||
parentObject = new DSpaceObject(bitstream.getParentObject());
|
||||
} else if(expandFields.contains("policies") || expandFields.contains("all")) {
|
||||
List<ResourcePolicy> tempPolicies = new ArrayList<ResourcePolicy>();
|
||||
Bundle[] bundles = bitstream.getBundles();
|
||||
for (Bundle bundle : bundles) {
|
||||
List<org.dspace.authorize.ResourcePolicy> bitstreamsPolicies = bundle.getBitstreamPolicies();
|
||||
for (org.dspace.authorize.ResourcePolicy policy : bitstreamsPolicies) {
|
||||
if (policy.getResourceID() == this.getId()) {
|
||||
tempPolicies.add(new ResourcePolicy(policy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
policies = tempPolicies.toArray(new ResourcePolicy[0]);
|
||||
} else {
|
||||
this.addExpand("parent");
|
||||
this.addExpand("policies");
|
||||
}
|
||||
|
||||
if(!expandFields.contains("all")) {
|
||||
@@ -153,4 +171,13 @@ public class Bitstream extends DSpaceObject {
|
||||
this.checkSum = checkSum;
|
||||
}
|
||||
|
||||
public ResourcePolicy[] getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
public void setPolicies(ResourcePolicy[] policies) {
|
||||
this.policies = policies;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ 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;
|
||||
|
@@ -38,8 +38,9 @@ public class Community extends DSpaceObject{
|
||||
private String copyrightText, introductoryText, shortDescription, sidebarText;
|
||||
private Integer countItems;
|
||||
|
||||
// Renamed because of xml annotation exception with this attribute and getSubCommunities.
|
||||
@XmlElement(name = "subcommunities", required = true)
|
||||
private List<Community> subCommunities = new ArrayList<Community>();
|
||||
private List<Community> subcommunities = new ArrayList<Community>();
|
||||
|
||||
private List<Collection> collections = new ArrayList<Collection>();
|
||||
|
||||
@@ -87,10 +88,10 @@ public class Community extends DSpaceObject{
|
||||
|
||||
if(expandFields.contains("subCommunities") || expandFields.contains("all")) {
|
||||
org.dspace.content.Community[] communityArray = community.getSubcommunities();
|
||||
subCommunities = new ArrayList<Community>();
|
||||
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));
|
||||
subcommunities.add(new Community(subCommunity, null, context));
|
||||
} else {
|
||||
log.info("Omitted restricted subCommunity: " + subCommunity.getID() + " _ " + subCommunity.getName());
|
||||
}
|
||||
@@ -171,4 +172,13 @@ public class Community extends DSpaceObject{
|
||||
public Bitstream getLogo() {
|
||||
return logo;
|
||||
}
|
||||
|
||||
public List<Community> getSubcommunities() {
|
||||
return subcommunities;
|
||||
}
|
||||
|
||||
public void setSubcommunities(List<Community> subcommunities) {
|
||||
this.subcommunities = subcommunities;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ 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;
|
||||
|
||||
@@ -26,9 +27,7 @@ public class DSpaceObject {
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String handle;
|
||||
|
||||
private String type;
|
||||
|
||||
@XmlElement(name = "link", required = true)
|
||||
@@ -42,17 +41,17 @@ public class DSpaceObject {
|
||||
}
|
||||
|
||||
public DSpaceObject(org.dspace.content.DSpaceObject dso) {
|
||||
setID(dso.getID());
|
||||
setId(dso.getID());
|
||||
setName(dso.getName());
|
||||
setHandle(dso.getHandle());
|
||||
setType(dso.getTypeText().toLowerCase());
|
||||
}
|
||||
|
||||
public Integer getID() {
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setID(Integer id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -74,7 +73,7 @@ public class DSpaceObject {
|
||||
|
||||
public String getLink() {
|
||||
//TODO, get actual contextPath of /rest/
|
||||
return "/rest/" + English.plural(getType()) + "/" + getID();
|
||||
return "/RESTapi/" + English.plural(getType()) + "/" + getId();
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
|
@@ -17,6 +17,7 @@ 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;
|
||||
@@ -29,6 +30,7 @@ import java.util.List;
|
||||
* Time: 4:50 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@XmlRootElement(name = "item")
|
||||
public class Item extends DSpaceObject {
|
||||
Logger log = Logger.getLogger(Item.class);
|
||||
@@ -39,11 +41,8 @@ public class Item extends DSpaceObject {
|
||||
|
||||
Collection parentCollection;
|
||||
List<Collection> parentCollectionList;
|
||||
|
||||
List<Community> parentCommunityList;
|
||||
|
||||
List<MetadataEntry> metadata;
|
||||
|
||||
List<Bitstream> bitstreams;
|
||||
|
||||
public Item(){}
|
||||
@@ -63,9 +62,8 @@ public class Item extends DSpaceObject {
|
||||
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));
|
||||
}
|
||||
if (!MetadataExposure.isHidden(context, dcv.schema, dcv.element, dcv.qualifier))
|
||||
metadata.add(new MetadataEntry(dcv.getField(), dcv.value, dcv.language));
|
||||
}
|
||||
} else {
|
||||
this.addExpand("metadata");
|
||||
|
@@ -10,37 +10,58 @@ 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.
|
||||
* @author peterdietz, Rostislav Novak (Computing and Information Centre, CTU in
|
||||
* Prague)
|
||||
*
|
||||
*/
|
||||
@XmlRootElement(name = "metadataentry")
|
||||
public class MetadataEntry {
|
||||
public class MetadataEntry
|
||||
{
|
||||
String key;
|
||||
|
||||
String value;
|
||||
|
||||
public MetadataEntry() {}
|
||||
String language;
|
||||
|
||||
public MetadataEntry(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
public MetadataEntry()
|
||||
{
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
public MetadataEntry(String key, String value, String language)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
public String getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
public void setKey(String key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getLanguage()
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language)
|
||||
{
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 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 java.util.Date;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
|
||||
public class ResourcePolicy{
|
||||
|
||||
public enum Action {
|
||||
READ, WRITE, DELETE;
|
||||
}
|
||||
|
||||
private Integer id;
|
||||
private Action action;
|
||||
private Integer epersonId;
|
||||
private Integer groupId;
|
||||
private Integer resourceId;
|
||||
private String resourceType;
|
||||
private String rpDescription;
|
||||
private String rpName;
|
||||
private String rpType;
|
||||
private Date startDate;
|
||||
private Date endDate;
|
||||
|
||||
public ResourcePolicy() {}
|
||||
|
||||
public ResourcePolicy(org.dspace.authorize.ResourcePolicy dspacePolicy) {
|
||||
this.id = dspacePolicy.getID();
|
||||
|
||||
switch(dspacePolicy.getAction()) {
|
||||
case org.dspace.core.Constants.READ:
|
||||
this.action = Action.READ;
|
||||
break;
|
||||
case org.dspace.core.Constants.WRITE:
|
||||
this.action = Action.WRITE;
|
||||
break;
|
||||
case org.dspace.core.Constants.DELETE:
|
||||
this.action = Action.DELETE;
|
||||
break;
|
||||
}
|
||||
|
||||
this.epersonId = dspacePolicy.getEPersonID();
|
||||
this.groupId = dspacePolicy.getGroupID();
|
||||
this.resourceId = dspacePolicy.getResourceID();
|
||||
this.rpDescription = dspacePolicy.getRpDescription();
|
||||
this.rpName = dspacePolicy.getRpName();
|
||||
this.rpType = dspacePolicy.getRpType();
|
||||
this.startDate = dspacePolicy.getStartDate();
|
||||
this.endDate = dspacePolicy.getEndDate();
|
||||
|
||||
switch(dspacePolicy.getResourceType()) {
|
||||
case org.dspace.core.Constants.BITSTREAM:
|
||||
this.resourceType = "bitstream";
|
||||
break;
|
||||
case org.dspace.core.Constants.ITEM:
|
||||
this.resourceType = "item";
|
||||
break;
|
||||
case org.dspace.core.Constants.COLLECTION:
|
||||
this.resourceType = "collection";
|
||||
break;
|
||||
case org.dspace.core.Constants.COMMUNITY:
|
||||
this.resourceType = "community";
|
||||
break;
|
||||
case org.dspace.core.Constants.BUNDLE:
|
||||
this.resourceType = "bundle";
|
||||
break;
|
||||
default:
|
||||
this.resourceType = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public int getActionInt(){
|
||||
switch(action) {
|
||||
case READ:
|
||||
return org.dspace.core.Constants.READ;
|
||||
case WRITE:
|
||||
return org.dspace.core.Constants.WRITE;
|
||||
case DELETE:
|
||||
return org.dspace.core.Constants.DELETE;
|
||||
}
|
||||
return org.dspace.core.Constants.READ;
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public Integer getEpersonId() {
|
||||
return epersonId;
|
||||
}
|
||||
|
||||
public void setEpersonId(Integer epersonId) {
|
||||
this.epersonId = epersonId;
|
||||
}
|
||||
|
||||
public Integer getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(Integer groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public Integer getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(Integer resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String resourceType) {
|
||||
this.resourceType = resourceType;
|
||||
}
|
||||
|
||||
public String getRpDescription() {
|
||||
return rpDescription;
|
||||
}
|
||||
|
||||
public void setRpDescription(String rpDescription) {
|
||||
this.rpDescription = rpDescription;
|
||||
}
|
||||
|
||||
public String getRpName() {
|
||||
return rpName;
|
||||
}
|
||||
|
||||
public void setRpName(String rpName) {
|
||||
this.rpName = rpName;
|
||||
}
|
||||
|
||||
public String getRpType() {
|
||||
return rpType;
|
||||
}
|
||||
|
||||
public void setRpType(String rpType) {
|
||||
this.rpType = rpType;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
105
dspace-rest/src/main/java/org/dspace/rest/common/Status.java
Normal file
105
dspace-rest/src/main/java/org/dspace/rest/common/Status.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Used to handle/determine status of REST API.
|
||||
* Mainly to know your authentication status
|
||||
*
|
||||
*/
|
||||
@XmlRootElement(name = "status")
|
||||
public class Status
|
||||
{
|
||||
private boolean okay;
|
||||
private boolean authenticated;
|
||||
private String email;
|
||||
private String fullname;
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
private String token;
|
||||
|
||||
public Status() {
|
||||
setOkay(true);
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
public Status(String email, String fullname, String token) {
|
||||
setOkay(true);
|
||||
setAuthenticated(true);
|
||||
setEmail(email);
|
||||
setFullname(fullname);
|
||||
setToken(token);
|
||||
}
|
||||
|
||||
public Status(EPerson eperson, String token) {
|
||||
setOkay(true);
|
||||
if(eperson != null) {
|
||||
setAuthenticated(true);
|
||||
setEmail(eperson.getEmail());
|
||||
setFullname(eperson.getFullName());
|
||||
setToken(token);
|
||||
} else {
|
||||
setAuthenticated(false);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonProperty("okay")
|
||||
public boolean isOkay()
|
||||
{
|
||||
return this.okay;
|
||||
}
|
||||
|
||||
@JsonProperty("okay")
|
||||
public void setOkay(boolean okay)
|
||||
{
|
||||
this.okay = okay;
|
||||
}
|
||||
|
||||
@JsonProperty("authenticated")
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
@JsonProperty("authenticated")
|
||||
public void setAuthenticated(boolean authenticated) {
|
||||
this.authenticated = authenticated;
|
||||
}
|
||||
|
||||
@JsonProperty("email")
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@JsonProperty("email")
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@JsonProperty("fullname")
|
||||
public String getFullname() {
|
||||
return fullname;
|
||||
}
|
||||
|
||||
@JsonProperty("fullname")
|
||||
public void setFullname(String fullname) {
|
||||
this.fullname = fullname;
|
||||
}
|
||||
}
|
56
dspace-rest/src/main/java/org/dspace/rest/common/User.java
Normal file
56
dspace-rest/src/main/java/org/dspace/rest/common/User.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Class for handle login information for POST request.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*
|
||||
*/
|
||||
@XmlRootElement(name = "user")
|
||||
public class User
|
||||
{
|
||||
|
||||
private String email;
|
||||
|
||||
private String password;
|
||||
|
||||
public User()
|
||||
{
|
||||
}
|
||||
|
||||
public User(String email, String password)
|
||||
{
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail()
|
||||
{
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email)
|
||||
{
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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.exceptions;
|
||||
|
||||
/**
|
||||
* Simple exception which only encapsulate classic exception. This exception is
|
||||
* only for exceptions caused by creating context.
|
||||
*
|
||||
* @author Rostislav Novak (Computing and Information Centre, CTU in Prague)
|
||||
*
|
||||
*/
|
||||
public class ContextException extends Exception
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
Exception causedBy;
|
||||
|
||||
public ContextException(String message, Exception causedBy)
|
||||
{
|
||||
super(message);
|
||||
this.causedBy = causedBy;
|
||||
}
|
||||
|
||||
public Exception getCausedBy()
|
||||
{
|
||||
return causedBy;
|
||||
}
|
||||
|
||||
}
|
@@ -36,23 +36,23 @@
|
||||
-->
|
||||
<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>
|
||||
|
||||
<!-- Security settings and mapping -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>DSpace REST API</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<user-data-constraint>
|
||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||
</user-data-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<!-- DSpace Configuration Information -->
|
||||
<context-param>
|
||||
<param-name>dspace-config</param-name>
|
||||
@@ -98,6 +98,4 @@
|
||||
</listener-class>
|
||||
</listener>
|
||||
|
||||
|
||||
|
||||
</web-app>
|
Reference in New Issue
Block a user