/**
* 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.sword2;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.swordapp.server.*;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
public class MediaResourceManagerDSpace extends DSpaceSwordAPI
implements MediaResourceManager
{
private static Logger log = Logger
.getLogger(MediaResourceManagerDSpace.class);
protected AuthorizeService authorizeService = AuthorizeServiceFactory
.getInstance().getAuthorizeService();
private VerboseDescription verboseDescription = new VerboseDescription();
private boolean isAccessible(Context context, Bitstream bitstream)
throws DSpaceSwordException
{
try
{
return authorizeService
.authorizeActionBoolean(context, bitstream, Constants.READ);
}
catch (SQLException e)
{
throw new DSpaceSwordException(e);
}
}
private boolean isAccessible(Context context, Item item)
throws DSpaceSwordException
{
try
{
return authorizeService
.authorizeActionBoolean(context, item, Constants.READ);
}
catch (SQLException e)
{
throw new DSpaceSwordException(e);
}
}
private MediaResource getBitstreamResource(Context context,
Bitstream bitstream)
throws SwordServerException, SwordAuthException
{
try
{
InputStream stream = bitstreamService.retrieve(context, bitstream);
MediaResource mr = new MediaResource(stream,
bitstream.getFormat(context).getMIMEType(), null, true);
mr.setContentMD5(bitstream.getChecksum());
mr.setLastModified(this.getLastModified(context, bitstream));
return mr;
}
catch (IOException | SQLException e)
{
throw new SwordServerException(e);
}
catch (AuthorizeException e)
{
throw new SwordAuthException(e);
}
}
private MediaResource getItemResource(Context context, Item item,
SwordUrlManager urlManager, String uri, Map<String, String> accept)
throws SwordError, DSpaceSwordException, SwordServerException
{
boolean feedRequest = urlManager.isFeedRequest(context, uri);
SwordContentDisseminator disseminator = null;
// first off, consider the accept headers. The accept argument is a map
// from accept header to value.
// we only care about Accept and Accept-Packaging
if (!feedRequest)
{
String acceptContentType = this.getHeader(accept, "Accept", null);
String acceptPackaging = this.getHeader(accept, "Accept-Packaging",
UriRegistry.PACKAGE_SIMPLE_ZIP);
// we know that only one Accept-Packaging value is allowed, so we don't need
// to do any further work on it.
// we extract from the Accept header the ordered list of content types
TreeMap<Float, List<String>> analysed = this
.analyseAccept(acceptContentType);
// the meat of this is done by the package disseminator
disseminator = SwordDisseminatorFactory
.getContentInstance(analysed, acceptPackaging);
}
else
{
// we just want to ask for the atom version, so we bypass the main content
// negotiation place
Map<Float, List<String>> analysed = new HashMap<Float, List<String>>();
List<String> list = new ArrayList<String>();
list.add("application/atom+xml");
analysed.put((float) 1.0, list);
disseminator = SwordDisseminatorFactory
.getContentInstance(analysed, null);
}
// Note that at this stage, if we don't have a desiredContentType, it will
// be null, and the disseminator is free to choose the format
InputStream stream = disseminator.disseminate(context, item);
return new MediaResource(stream, disseminator.getContentType(),
disseminator.getPackaging());
}
public MediaResource getMediaResourceRepresentation(String uri,
Map<String, String> accept, AuthCredentials authCredentials,
SwordConfiguration swordConfig)
throws SwordError, SwordServerException, SwordAuthException
{
// all the bits we need to make this method function
SwordContext sc = null;
SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig;
Context ctx = null;
try
{
// create an unauthenticated context for our initial explorations
ctx = new Context();
SwordUrlManager urlManager = config.getUrlManager(ctx, config);
// is this a request for a bitstream or an item (which is the full media resource)?
if (urlManager.isActionableBitstreamUrl(ctx, uri))
{
// request for a bitstream
Bitstream bitstream = urlManager.getBitstream(ctx, uri);
if (bitstream == null)
{
// bitstream not found in the database, so 404 the client.
// Arguably, we should try to authenticate first, but it's not so important
throw new SwordError(404);
}
// find out, now we know what we're being asked for, whether this is allowed
WorkflowManagerFactory.getInstance()
.retrieveBitstream(ctx, bitstream);
// we can do this in principle, but now find out whether the bitstream is accessible without credentials
boolean accessible = this.isAccessible(ctx, bitstream);
if (!accessible)
{
// try to authenticate, and if successful switch the contexts around
sc = this.doAuth(authCredentials);
ctx.abort();
ctx = sc.getContext();
// re-retrieve the bitstream using the new context
bitstream = bitstreamService.find(ctx, bitstream.getID());
// and re-verify its accessibility
accessible = this.isAccessible(ctx, bitstream);
if (!accessible)
{
throw new SwordAuthException();
}
}
// if we get to here we are either allowed to access the bitstream without credentials,
// or we have been authenticated with acceptable credentials
MediaResource mr = this.getBitstreamResource(ctx, bitstream);
if (sc != null)
{
sc.abort();
}
if (ctx.isValid())
{
ctx.abort();
}
return mr;
}
else
{
// request for an item
Item item = urlManager.getItem(ctx, uri);
if (item == null)
{
// item now found in the database, so 404 the client
// Arguably, we should try to authenticate first, but it's not so important
throw new SwordError(404);
}
// find out, now we know what we're being asked for, whether this is allowed
WorkflowManagerFactory.getInstance().retrieveContent(ctx, item);
// we can do this in principle but now find out whether the item is accessible without credentials
boolean accessible = this.isAccessible(ctx, item);
if (!accessible)
{
// try to authenticate, and if successful switch the contexts around
sc = this.doAuth(authCredentials);
ctx.abort();
ctx = sc.getContext();
}
// if we get to here we are either allowed to access the bitstream without credentials,
// or we have been authenticated
MediaResource mr = this
.getItemResource(ctx, item, urlManager, uri, accept);
// sc.abort();
ctx.abort();
return mr;
}
}
catch (SQLException | DSpaceSwordException e)
{
throw new SwordServerException(e);
}
finally
{
// if there is a sword context, abort it (this will abort the inner dspace context as well)
if (sc != null)
{
sc.abort();
}
if (ctx != null && ctx.isValid())
{
ctx.abort();
}
}
}
private Date getLastModified(Context context, Bitstream bitstream)
throws SQLException
{
Date lm = null;
List<Bundle> bundles = bitstream.getBundles();
for (Bundle bundle : bundles)
{
List<Item> items = bundle.getItems();
for (Item item : items)
{
Date possible = item.getLastModified();
if (lm == null)
{
lm = possible;
}
else if (possible.getTime() > lm.getTime())
{
lm = possible;
}
}
}
if (lm == null)
{
return new Date();
}
return lm;
}
public DepositReceipt replaceMediaResource(String emUri, Deposit deposit,
AuthCredentials authCredentials, SwordConfiguration swordConfig)
throws SwordError, SwordServerException, SwordAuthException
{
// start the timer
Date start = new Date();
// store up the verbose description, which we can then give back at the end if necessary
this.verboseDescription
.append("Initialising verbose replace of media resource");
SwordContext sc = null;
SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig;
try
{
sc = this.doAuth(authCredentials);
Context context = sc.getContext();
if (log.isDebugEnabled())
{
log.debug(LogManager.getHeader(context, "sword_replace", ""));
}
DepositReceipt receipt;
SwordUrlManager urlManager = config.getUrlManager(context, config);
if (urlManager.isActionableBitstreamUrl(context, emUri))
{
Bitstream bitstream = urlManager.getBitstream(context, emUri);
if (bitstream == null)
{
throw new SwordError(404);
}
// now we have the deposit target, we can determine whether this operation is allowed
// at all
WorkflowManager wfm = WorkflowManagerFactory.getInstance();
wfm.replaceBitstream(context, bitstream);
// check that we can submit to ALL the items this bitstream is in
List<Item> items = new ArrayList<>();
List<Bundle> bundles = bitstream.getBundles();
for (Bundle bundle : bundles)
{
List<Item> bundleItems = bundle
.getItems();
for (Item item : bundleItems)
{
this.checkAuth(sc, item);
items.add(item);
}
}
// make a note of the authentication in the verbose string
this.verboseDescription.append("Authenticated user: " +
sc.getAuthenticated().getEmail());
if (sc.getOnBehalfOf() != null)
{
this.verboseDescription.append("Depositing on behalf of: " +
sc.getOnBehalfOf().getEmail());
}
DepositResult result = null;
try
{
result = this
.replaceBitstream(sc, items, bitstream, deposit,
authCredentials, config);
}
catch (DSpaceSwordException | SwordError e)
{
if (config.isKeepPackageOnFailedIngest())
{
try
{
this.storePackageAsFile(deposit, authCredentials,
config);
}
catch (IOException e2)
{
log.warn("Unable to store SWORD package as file: " +
e);
}
}
throw e;
}
// now we've produced a deposit, we need to decide on its workflow state
wfm.resolveState(context, deposit, null,
this.verboseDescription, false);
ReceiptGenerator genny = new ReceiptGenerator();
receipt = genny.createFileReceipt(context, result, config);
}
else
{
// get the deposit target
Item item = this.getDSpaceTarget(context, emUri, config);
if (item == null)
{
throw new SwordError(404);
}
// now we have the deposit target, we can determine whether this operation is allowed
// at all
WorkflowManager wfm = WorkflowManagerFactory.getInstance();
wfm.replaceResourceContent(context, item);
// find out if the supplied SWORDContext can submit to the given
// dspace object
SwordAuthenticator auth = new SwordAuthenticator();
if (!auth.canSubmit(sc, item, this.verboseDescription))
{
// throw an exception if the deposit can't be made
String oboEmail = "none";
if (sc.getOnBehalfOf() != null)
{
oboEmail = sc.getOnBehalfOf().getEmail();
}
log.info(LogManager
.getHeader(context, "replace_failed_authorisation",
"user=" +
sc.getAuthenticated().getEmail() +
",on_behalf_of=" + oboEmail));
throw new SwordAuthException(
"Cannot replace the given item with this context");
}
// make a note of the authentication in the verbose string
this.verboseDescription.append("Authenticated user: " +
sc.getAuthenticated().getEmail());
if (sc.getOnBehalfOf() != null)
{
this.verboseDescription.append("Depositing on behalf of: " +
sc.getOnBehalfOf().getEmail());
}
try
{
this.replaceContent(sc, item, deposit, authCredentials,
config);
}
catch (DSpaceSwordException | SwordError e)
{
if (config.isKeepPackageOnFailedIngest())
{
try
{
this.storePackageAsFile(deposit, authCredentials,
config);
}
catch (IOException e2)
{
log.warn("Unable to store SWORD package as file: " +
e);
}
}
throw e;
}
// now we've produced a deposit, we need to decide on its workflow state
wfm.resolveState(context, deposit, null,
this.verboseDescription, false);
ReceiptGenerator genny = new ReceiptGenerator();
receipt = genny
.createMediaResourceReceipt(context, item, config);
}
Date finish = new Date();
long delta = finish.getTime() - start.getTime();
this.verboseDescription
.append("Total time for deposit processing: " + delta +
" ms");
// receipt.setVerboseDescription(this.verboseDescription.toString());
// if something hasn't killed it already (allowed), then complete the transaction
sc.commit();
// return the receipt for the purposes of the location
return receipt;
}
catch (DSpaceSwordException e)
{
log.error("caught exception:", e);
throw new SwordServerException(
"There was a problem depositing the item", e);
}
catch (SQLException e)
{
throw new SwordServerException(e);
}
finally
{
// this is a read operation only, so there's never any need to commit the context
if (sc != null)
{
sc.abort();
}
}
}
public void deleteMediaResource(String emUri,
AuthCredentials authCredentials, SwordConfiguration swordConfig)
throws SwordError, SwordServerException, SwordAuthException
{
// start the timer
Date start = new Date();
// store up the verbose description, which we can then give back at the end if necessary
this.verboseDescription
.append("Initialising verbose delete of media resource");
SwordContext sc = null;
SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig;
try
{
sc = this.doAuth(authCredentials);
Context context = sc.getContext();
if (log.isDebugEnabled())
{
log.debug(LogManager.getHeader(context, "sword_delete", ""));
}
SwordUrlManager urlManager = config.getUrlManager(context, config);
WorkflowManager wfm = WorkflowManagerFactory.getInstance();
// get the deposit target
if (urlManager.isActionableBitstreamUrl(context, emUri))
{
Bitstream bitstream = urlManager.getBitstream(context, emUri);
if (bitstream == null)
{
throw new SwordError(404);
}
// now we have the deposit target, we can determine whether this operation is allowed
// at all
wfm.deleteBitstream(context, bitstream);
// check that we can submit to ALL the items this bitstream is in
List<Item> items = new ArrayList<>();
for (Bundle bundle : bitstream.getBundles())
{
List<Item> bundleItems = bundle
.getItems();
for (Item item : bundleItems)
{
this.checkAuth(sc, item);
items.add(item);
}
}
// make a note of the authentication in the verbose string
this.verboseDescription.append("Authenticated user: " +
sc.getAuthenticated().getEmail());
if (sc.getOnBehalfOf() != null)
{
this.verboseDescription.append("Depositing on behalf of: " +
sc.getOnBehalfOf().getEmail());
}
this.removeBitstream(sc, bitstream, items, authCredentials,
config);
}
else
{
Item item = this.getDSpaceTarget(context, emUri, config);
if (item == null)
{
throw new SwordError(404);
}
// now we have the deposit target, we can determine whether this operation is allowed
// at all
wfm.deleteMediaResource(context, item);
// find out if the supplied SWORDContext can submit to the given
// dspace object
SwordAuthenticator auth = new SwordAuthenticator();
if (!auth.canSubmit(sc, item, this.verboseDescription))
{
// throw an exception if the deposit can't be made
String oboEmail = "none";
if (sc.getOnBehalfOf() != null)
{
oboEmail = sc.getOnBehalfOf().getEmail();
}
log.info(LogManager
.getHeader(context, "replace_failed_authorisation",
"user=" +
sc.getAuthenticated().getEmail() +
",on_behalf_of=" + oboEmail));
throw new SwordAuthException(
"Cannot replace the given item with this context");
}
// make a note of the authentication in the verbose string
this.verboseDescription.append("Authenticated user: " +
sc.getAuthenticated().getEmail());
if (sc.getOnBehalfOf() != null)
{
this.verboseDescription.append("Depositing on behalf of: " +
sc.getOnBehalfOf().getEmail());
}
// do the business of removal
this.removeContent(sc, item, authCredentials, config);
}
// now we've produced a deposit, we need to decide on its workflow state
wfm.resolveState(context, null, null, this.verboseDescription,
false);
//ReceiptGenerator genny = new ReceiptGenerator();
//DepositReceipt receipt = genny.createReceipt(context, result, config);
Date finish = new Date();
long delta = finish.getTime() - start.getTime();
this.verboseDescription
.append("Total time for deposit processing: " + delta +
" ms");
// receipt.setVerboseDescription(this.verboseDescription.toString());
// if something hasn't killed it already (allowed), then complete the transaction
sc.commit();
// So, we don't actually return a receipt, but it was useful constructing it. Perhaps this will
// change in the spec?
}
catch (DSpaceSwordException e)
{
log.error("caught exception:", e);
throw new SwordServerException(
"There was a problem depositing the item", e);
}
catch (SQLException e)
{
throw new SwordServerException(e);
}
finally
{
// this is a read operation only, so there's never any need to commit the context
if (sc != null)
{
sc.abort();
}
}
}
public DepositReceipt addResource(String emUri, Deposit deposit,
AuthCredentials authCredentials, SwordConfiguration swordConfig)
throws SwordError, SwordServerException, SwordAuthException
{
// start the timer
Date start = new Date();
// store up the verbose description, which we can then give back at the end if necessary
this.verboseDescription
.append("Initialising verbose add to media resource");
SwordContext sc = null;
SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig;
try
{
sc = this.doAuth(authCredentials);
Context context = sc.getContext();
if (log.isDebugEnabled())
{
log.debug(LogManager.getHeader(context, "sword_add", ""));
}
// get the deposit target
Item item = this.getDSpaceTarget(context, emUri, config);
if (item == null)
{
throw new SwordError(404);
}
// now we have the deposit target, we can determine whether this operation is allowed
// at all
WorkflowManager wfm = WorkflowManagerFactory.getInstance();
wfm.addResourceContent(context, item);
// find out if the supplied SWORDContext can submit to the given
// dspace object
SwordAuthenticator auth = new SwordAuthenticator();
if (!auth.canSubmit(sc, item, this.verboseDescription))
{
// throw an exception if the deposit can't be made
String oboEmail = "none";
if (sc.getOnBehalfOf() != null)
{
oboEmail = sc.getOnBehalfOf().getEmail();
}
log.info(LogManager
.getHeader(context, "replace_failed_authorisation",
"user=" +
sc.getAuthenticated().getEmail() +
",on_behalf_of=" + oboEmail));
throw new SwordAuthException(
"Cannot replace the given item with this context");
}
// make a note of the authentication in the verbose string
this.verboseDescription.append("Authenticated user: " +
sc.getAuthenticated().getEmail());
if (sc.getOnBehalfOf() != null)
{
this.verboseDescription.append("Depositing on behalf of: " +
sc.getOnBehalfOf().getEmail());
}
DepositResult result;
try
{
result = this
.addContent(sc, item, deposit, authCredentials, config);
if (deposit.isMultipart())
{
ContainerManagerDSpace cm = new ContainerManagerDSpace();
result = cm
.doAddMetadata(sc, item, deposit, authCredentials,
config, result);
}
}
catch (DSpaceSwordException | SwordError e)
{
if (config.isKeepPackageOnFailedIngest())
{
try
{
this.storePackageAsFile(deposit, authCredentials,
config);
if (deposit.isMultipart())
{
this.storeEntryAsFile(deposit, authCredentials,
config);
}
}
catch (IOException e2)
{
log.warn("Unable to store SWORD package as file: " + e);
}
}
throw e;
}
// now we've produced a deposit, we need to decide on its workflow state
wfm.resolveState(context, deposit, null, this.verboseDescription,
false);
ReceiptGenerator genny = new ReceiptGenerator();
// Now, this bit is tricky:
DepositReceipt receipt;
// If this was a single file deposit, then we don't return a receipt, we just
// want to specify the location header
if (deposit.getPackaging().equals(UriRegistry.PACKAGE_BINARY))
{
receipt = genny.createFileReceipt(context, result, config);
}
// if, on the other-hand, this was a package, then we want to generate a
// deposit receipt proper, but with the location being for the media resource
else
{
receipt = genny.createReceipt(context, result, config, true);
}
Date finish = new Date();
long delta = finish.getTime() - start.getTime();
this.verboseDescription
.append("Total time for add processing: " + delta + " ms");
this.addVerboseDescription(receipt, this.verboseDescription);
// if something hasn't killed it already (allowed), then complete the transaction
sc.commit();
return receipt;
}
catch (DSpaceSwordException e)
{
log.error("caught exception:", e);
throw new SwordServerException(
"There was a problem depositing the item", e);
}
finally
{
// this is a read operation only, so there's never any need to commit the context
if (sc != null)
{
sc.abort();
}
}
}
private void removeContent(SwordContext swordContext, Item item,
AuthCredentials authCredentials,
SwordConfigurationDSpace swordConfig)
throws DSpaceSwordException, SwordAuthException
{
try
{
// remove content only really means everything from the ORIGINAL bundle
VersionManager vm = new VersionManager();
Iterator<Bundle> bundles = item.getBundles().iterator();
while (bundles.hasNext())
{
Bundle bundle = bundles.next();
if (Constants.CONTENT_BUNDLE_NAME.equals(bundle.getName()))
{
bundles.remove();
vm.removeBundle(swordContext.getContext(), item, bundle);
}
}
}
catch (SQLException | IOException e)
{
throw new DSpaceSwordException(e);
}
catch (AuthorizeException e)
{
throw new SwordAuthException(e);
}
}
private void removeBitstream(SwordContext swordContext, Bitstream bitstream,
List<Item> items, AuthCredentials authCredentials,
SwordConfigurationDSpace swordConfig)
throws DSpaceSwordException, SwordAuthException
{
try
{
// remove content only really means everything from the ORIGINAL bundle
VersionManager vm = new VersionManager();
for (Item item : items)
{
vm.removeBitstream(swordContext.getContext(), item, bitstream);
}
}
catch (SQLException | IOException e)
{
throw new DSpaceSwordException(e);
}
catch (AuthorizeException e)
{
throw new SwordAuthException(e);
}
}
private void replaceContent(SwordContext swordContext, Item item,
Deposit deposit, AuthCredentials authCredentials,
SwordConfigurationDSpace swordConfig)
throws DSpaceSwordException, SwordError, SwordAuthException,
SwordServerException
{
// get the things out of the service that we need
Context context = swordContext.getContext();
// is the content acceptable? If not, this will throw an error
this.isAcceptable(swordConfig, context, deposit, item);
// Obtain the relevant ingester from the factory
SwordContentIngester si = SwordIngesterFactory
.getContentInstance(context, deposit, null);
this.verboseDescription
.append("Loaded ingester: " + si.getClass().getName());
try
{
// delegate the to the version manager to get rid of any existing content and to version
// if if necessary
VersionManager vm = new VersionManager();
vm.removeBundle(swordContext.getContext(), item, "ORIGINAL");
}
catch (SQLException | IOException e)
{
throw new DSpaceSwordException(e);
}
catch (AuthorizeException e)
{
throw new SwordAuthException(e);
}
// do the deposit
DepositResult result = si
.ingest(context, deposit, item, this.verboseDescription);
this.verboseDescription.append("Replace completed successfully");
// store the originals (this code deals with the possibility that that's not required)
this.storeOriginals(swordConfig, context, this.verboseDescription,
deposit, result);
}
private DepositResult replaceBitstream(SwordContext swordContext,
List<Item> items, Bitstream bitstream, Deposit deposit,
AuthCredentials authCredentials,
SwordConfigurationDSpace swordConfig)
throws DSpaceSwordException, SwordError, SwordAuthException,
SwordServerException
{
// FIXME: this is basically not possible with the existing DSpace API.
// We hack around it by deleting the old bitstream and
// adding the new one and returning it,
// but this isn't in line with the REST approach of SWORD, so the caller should really
// 405 the client
// get the things out of the service that we need
Context context = swordContext.getContext();
// is the content acceptable to the items? If not, this will throw an error
for (Item item : items)
{
this.isAcceptable(swordConfig, context, deposit, item);
}
// Obtain the relevant ingester from the factory
SwordContentIngester si = SwordIngesterFactory
.getContentInstance(context, deposit, null);
this.verboseDescription
.append("Loaded ingester: " + si.getClass().getName());
try
{
// first we delete the original bitstream
this.removeBitstream(swordContext, bitstream, items,
authCredentials, swordConfig);
DepositResult result = null;
boolean first = true;
for (Item item : items)
{
if (first)
{
// just do this to the first item
result = this.addContent(swordContext, item, deposit,
authCredentials, swordConfig);
}
else
{
// now duplicate the bitstream to all the others
List<Bundle> bundles = item.getBundles();
if (!bundles.isEmpty())
{
bundleService.addBitstream(context, bundles.get(0),
result.getOriginalDeposit());
}
else
{
Bundle bundle = bundleService.create(context, item,
Constants.CONTENT_BUNDLE_NAME);
bundleService.addBitstream(context, bundle,
result.getOriginalDeposit());
}
}
}
// DepositResult result = si.ingest(context, deposit, items, this.verboseDescription);
this.verboseDescription.append("Replace completed successfully");
return result;
}
catch (SQLException e)
{
throw new DSpaceSwordException(e);
}
catch (AuthorizeException e)
{
throw new SwordAuthException(e);
}
}
private DepositResult addContent(SwordContext swordContext, Item item,
Deposit deposit, AuthCredentials authCredentials,
SwordConfigurationDSpace swordConfig)
throws DSpaceSwordException, SwordError, SwordAuthException,
SwordServerException
{
// get the things out of the service that we need
Context context = swordContext.getContext();
// is the content acceptable? If not, this will throw an error
this.isAcceptable(swordConfig, context, deposit, item);
// Obtain the relevant ingester from the factory
SwordContentIngester si = SwordIngesterFactory
.getContentInstance(context, deposit, null);
this.verboseDescription
.append("Loaded ingester: " + si.getClass().getName());
// do the deposit
DepositResult result = si
.ingest(context, deposit, item, this.verboseDescription);
this.verboseDescription.append("Add completed successfully");
// store the originals (this code deals with the possibility that that's not required)
this.storeOriginals(swordConfig, context, this.verboseDescription,
deposit, result);
return result;
}
private Item getDSpaceTarget(Context context, String editMediaUrl,
SwordConfigurationDSpace config)
throws DSpaceSwordException, SwordError
{
SwordUrlManager urlManager = config.getUrlManager(context, config);
// get the target collection
Item item = urlManager.getItem(context, editMediaUrl);
this.verboseDescription
.append("Performing replace using edit-media URL: " +
editMediaUrl);
this.verboseDescription
.append("Location resolves to item with handle: " +
item.getHandle());
return item;
}
private void checkAuth(SwordContext sc, Item item)
throws DSpaceSwordException, SwordError, SwordAuthException
{
Context context = sc.getContext();
SwordAuthenticator auth = new SwordAuthenticator();
if (!auth.canSubmit(sc, item, this.verboseDescription))
{
// throw an exception if the deposit can't be made
String oboEmail = "none";
if (sc.getOnBehalfOf() != null)
{
oboEmail = sc.getOnBehalfOf().getEmail();
}
log.info(LogManager
.getHeader(context, "replace_failed_authorisation",
"user=" +
sc.getAuthenticated().getEmail() +
",on_behalf_of=" + oboEmail));
throw new SwordAuthException(
"Cannot replace the given item with this context");
}
}
}