
org.dspace.sword.DepositManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dspace-sword Show documentation
Show all versions of dspace-sword Show documentation
DSpace SWORD Deposit Service Provider Extension
The newest version!
/**
* 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.sword;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Context;
import org.dspace.core.LogHelper;
import org.dspace.core.Utils;
import org.purl.sword.base.Deposit;
import org.purl.sword.base.DepositResponse;
import org.purl.sword.base.SWORDAuthenticationException;
import org.purl.sword.base.SWORDEntry;
import org.purl.sword.base.SWORDErrorException;
/**
* This class is responsible for initiating the process of
* deposit of SWORD Deposit objects into the DSpace repository
*
* @author Richard Jones
*/
public class DepositManager {
/**
* Log4j logger
*/
public static final Logger log = org.apache.logging.log4j.LogManager.getLogger(DepositManager.class);
/**
* The SWORD service implementation
*/
private SWORDService swordService;
/**
* Construct a new DepositManager using the given instantiation of
* the SWORD service implementation
*
* @param service SWORD service
*/
public DepositManager(SWORDService service) {
this.swordService = service;
log.debug("Created instance of DepositManager");
}
public DSpaceObject getDepositTarget(Deposit deposit)
throws DSpaceSWORDException, SWORDErrorException {
SWORDUrlManager urlManager = swordService.getUrlManager();
Context context = swordService.getContext();
// get the target collection
String loc = deposit.getLocation();
DSpaceObject dso = urlManager.getDSpaceObject(context, loc);
swordService.message("Performing deposit using location: " + loc);
if (dso instanceof Collection) {
CollectionService collectionService = ContentServiceFactory
.getInstance().getCollectionService();
swordService.message(
"Location resolves to collection with handle: " +
dso.getHandle() +
" and name: " +
collectionService.getName((Collection) dso));
} else if (dso instanceof Item) {
swordService.message("Location resolves to item with handle: " +
dso.getHandle());
}
return dso;
}
/**
* Once this object is fully prepared, this method will execute
* the deposit process. The returned DepositRequest can be
* used then to assemble the SWORD response.
*
* @param deposit deposit request
* @return the response to the deposit request
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
* @throws SWORDErrorException on generic SWORD exception
* @throws SWORDAuthenticationException Thrown if the authentication fails
*/
public DepositResponse deposit(Deposit deposit)
throws DSpaceSWORDException, SWORDErrorException,
SWORDAuthenticationException {
// start the timer, and initialise the verboseness of the request
Date start = new Date();
swordService.message("Initialising verbose deposit");
// get the things out of the service that we need
SWORDContext swordContext = swordService.getSwordContext();
Context context = swordService.getContext();
// get the deposit target
DSpaceObject dso = this.getDepositTarget(deposit);
// find out if the supplied SWORDContext can submit to the given
// dspace object
SWORDAuthenticator auth = new SWORDAuthenticator();
if (!auth.canSubmit(swordService, deposit, dso)) {
// throw an exception if the deposit can't be made
String oboEmail = "none";
if (swordContext.getOnBehalfOf() != null) {
oboEmail = swordContext.getOnBehalfOf().getEmail();
}
log.info(LogHelper.getHeader(context,
"deposit_failed_authorisation",
"user=" + swordContext.getAuthenticated().getEmail() +
",on_behalf_of=" + oboEmail));
throw new SWORDAuthenticationException(
"Cannot submit to the given collection with this context");
}
// make a note of the authentication in the verbose string
swordService.message("Authenticated user: " +
swordContext.getAuthenticated().getEmail());
if (swordContext.getOnBehalfOf() != null) {
swordService.message("Depositing on behalf of: " +
swordContext.getOnBehalfOf().getEmail());
}
// determine which deposit engine we initialise
Depositor dep = null;
if (dso instanceof Collection) {
swordService.message(
"Initialising depositor for an Item in a Collection");
dep = new CollectionDepositor(swordService, dso);
} else if (dso instanceof Item) {
swordService.message(
"Initialising depositor for a Bitstream in an Item");
dep = new ItemDepositor(swordService, dso);
}
if (dep == null) {
log.error(
"The specified deposit target does not exist, or is not a collection or an item");
throw new DSpaceSWORDException(
"Deposit target is not a collection or an item");
}
DepositResult result = null;
try {
result = dep.doDeposit(deposit);
} catch (DSpaceSWORDException | SWORDErrorException | RuntimeException e) {
if (swordService.getSwordConfig().isKeepPackageOnFailedIngest()) {
try {
storePackageAsFile(deposit);
} catch (IOException e2) {
log.warn("Unable to store SWORD package as file: " + e);
}
}
throw e;
}
// now construct the deposit response. The response will be
// CREATED if the deposit is in the archive, or ACCEPTED if
// the deposit is in the workflow. We use a separate record
// for the handle because DSpace will not supply the Item with
// a record of the handle straight away.
String handle = result.getHandle();
int state = Deposit.CREATED;
if (StringUtils.isBlank(handle)) {
state = Deposit.ACCEPTED;
}
DepositResponse response = new DepositResponse(state);
response.setLocation(result.getMediaLink());
DSpaceATOMEntry dsatom = null;
if (result.getItem() != null) {
swordService.message("Initialising ATOM entry generator for an Item");
dsatom = new ItemEntryGenerator(swordService);
} else if (result.getBitstream() != null) {
swordService.message(
"Initialising ATOM entry generator for a Bitstream");
dsatom = new BitstreamEntryGenerator(swordService);
}
if (dsatom == null) {
log.error("The deposit failed, see exceptions for explanation");
throw new DSpaceSWORDException(
"Result of deposit did not yield an Item or a Bitstream");
}
SWORDEntry entry = dsatom.getSWORDEntry(result, deposit);
// if this was a no-op, we need to remove the files we just
// deposited, and abort the transaction
if (deposit.isNoOp()) {
dep.undoDeposit(result);
swordService.message(
"NoOp Requested: Removed all traces of submission");
}
entry.setNoOp(deposit.isNoOp());
Date finish = new Date();
long delta = finish.getTime() - start.getTime();
swordService.message(
"Total time for deposit processing: " + delta + " ms");
entry.setVerboseDescription(
swordService.getVerboseDescription().toString());
response.setEntry(entry);
return response;
}
/**
* Store original package on disk and companion file containing SWORD
* headers as found in the deposit object
* Also write companion file with header info from the deposit object.
*
* @param deposit the original deposit request
*/
private void storePackageAsFile(Deposit deposit) throws IOException {
String path = swordService.getSwordConfig().getFailedPackageDir();
File dir = new File(path);
if (!dir.exists() || !dir.isDirectory()) {
throw new IOException(
"Directory does not exist for writing packages on ingest error.");
}
String filenameBase =
"sword-" + deposit.getUsername() + "-" + (new Date()).getTime();
// No dots or slashes allowed in filename
filenameBase = filenameBase.replaceAll("\\.", "").replaceAll("/", ""). replaceAll("\\\\", "");
File packageFile = new File(path, filenameBase);
File headersFile = new File(path, filenameBase + "-headers");
InputStream is = new BufferedInputStream(
new FileInputStream(deposit.getFile()));
OutputStream fos = new BufferedOutputStream(
new FileOutputStream(packageFile));
Utils.copy(is, fos);
fos.close();
is.close();
//write companion file with headers
PrintWriter pw = new PrintWriter(
new BufferedWriter(new FileWriter(headersFile)));
pw.println("Content-Disposition=" + deposit.getContentDisposition());
pw.println("Content-Type=" + deposit.getContentType());
pw.println("Packaging=" + deposit.getPackaging());
pw.println("Location=" + deposit.getLocation());
pw.println("On Behalf of=" + deposit.getOnBehalfOf());
pw.println("Slug=" + deposit.getSlug());
pw.println("User name=" + deposit.getUsername());
pw.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy