/** * 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.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.*; import org.dspace.core.Constants; import org.dspace.core.Context; import org.swordapp.server.Deposit; import org.swordapp.server.SwordAuthException; import org.swordapp.server.SwordError; import org.swordapp.server.UriRegistry; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; public class SimpleZipContentIngester extends AbstractSwordContentIngester { protected BundleService bundleService = ContentServiceFactory.getInstance() .getBundleService(); protected BitstreamService bitstreamService = ContentServiceFactory .getInstance().getBitstreamService(); protected WorkspaceItemService workspaceItemService = ContentServiceFactory .getInstance().getWorkspaceItemService(); public DepositResult ingestToCollection(Context context, Deposit deposit, Collection collection, VerboseDescription verboseDescription, DepositResult result) throws DSpaceSwordException, SwordError, SwordAuthException { try { // get deposited file as file object File depositFile = deposit.getFile(); // decide whether we have a new item or an existing one Item item = null; WorkspaceItem wsi = null; if (result != null) { item = result.getItem(); } else { result = new DepositResult(); } if (item == null) { // simple zip ingester uses the item template, since there is no native metadata wsi = workspaceItemService.create(context, collection, true); item = wsi.getItem(); } // get the original bundle List<Bundle> bundles = item.getBundles(); Bundle original = null; for (Bundle bundle : bundles) { if (Constants.CONTENT_BUNDLE_NAME.equals(bundle.getName())) { original = bundle; break; } } if (original == null) { original = bundleService .create(context, item, Constants.CONTENT_BUNDLE_NAME); } // unzip the file into the bundle List<Bitstream> derivedResources = this .unzipToBundle(context, depositFile, original); // now we have an item in the workspace, and we need to consider adding some metadata to it, // but since the zip file didn't contain anything, what do we do? itemService.addMetadata(context, item, "dc", "title", null, null, "Untitled: " + deposit.getFilename()); itemService .addMetadata(context, item, "dc", "description", null, null, "Zip file deposted by SWORD without accompanying metadata"); // update the item metadata to inclue the current time as // the updated date this.setUpdatedDate(context, item, verboseDescription); // DSpace ignores the slug value as suggested identifier, but // it does store it in the metadata this.setSlug(context, item, deposit.getSlug(), verboseDescription); // in order to write these changes, we need to bypass the // authorisation briefly, because although the user may be // able to add stuff to the repository, they may not have // WRITE permissions on the archive. context.turnOffAuthorisationSystem(); itemService.update(context, item); context.restoreAuthSystemState(); verboseDescription.append("Ingest successful"); verboseDescription .append("Item created with internal identifier: " + item.getID()); result.setItem(item); result.setTreatment(this.getTreatment()); result.setDerivedResources(derivedResources); return result; } catch (AuthorizeException e) { throw new SwordAuthException(e); } catch (SQLException e) { throw new DSpaceSwordException(e); } } private List<Bitstream> unzipToBundle(Context context, File depositFile, Bundle target) throws DSpaceSwordException, SwordError, SwordAuthException { try { // get the zip file into a usable form ZipFile zip = new ZipFile(depositFile); List<Bitstream> derivedResources = new ArrayList<Bitstream>(); Enumeration zenum = zip.entries(); while (zenum.hasMoreElements()) { ZipEntry entry = (ZipEntry) zenum.nextElement(); InputStream stream = zip.getInputStream(entry); Bitstream bs = bitstreamService.create(context, target, stream); BitstreamFormat format = this .getFormat(context, entry.getName()); bs.setFormat(context, format); bs.setName(context, entry.getName()); bitstreamService.update(context, bs); derivedResources.add(bs); } return derivedResources; } catch (ZipException e) { throw new SwordError(UriRegistry.ERROR_BAD_REQUEST, "unable to unzip provided package", e); } catch (IOException | SQLException e) { throw new DSpaceSwordException(e); } catch (AuthorizeException e) { throw new SwordAuthException(e); } } public DepositResult ingestToItem(Context context, Deposit deposit, Item item, VerboseDescription verboseDescription, DepositResult result) throws DSpaceSwordException, SwordError, SwordAuthException { try { if (result == null) { result = new DepositResult(); } result.setItem(item); // get deposited file as file object File depositFile = deposit.getFile(); // get the original bundle List<Bundle> bundles = item.getBundles(); Bundle original = null; for (Bundle bundle : bundles) { if (Constants.CONTENT_BUNDLE_NAME.equals(bundle.getName())) { original = bundle; break; } } if (original == null) { original = bundleService .create(context, item, Constants.CONTENT_BUNDLE_NAME); } // we are now free to go and unpack the new zip into the original bundle List<Bitstream> derivedResources = this .unzipToBundle(context, depositFile, original); // update the item metadata to inclue the current time as // the updated date this.setUpdatedDate(context, item, verboseDescription); // in order to write these changes, we need to bypass the // authorisation briefly, because although the user may be // able to add stuff to the repository, they may not have // WRITE permissions on the archive. context.turnOffAuthorisationSystem(); itemService.update(context, item); context.restoreAuthSystemState(); verboseDescription.append("Replace successful"); result.setItem(item); result.setTreatment(this.getTreatment()); result.setDerivedResources(derivedResources); return result; } catch (AuthorizeException e) { throw new SwordAuthException(e); } catch (SQLException e) { throw new DSpaceSwordException(e); } } /** * The human readable description of the treatment this ingester has * put the deposit through * * @return human readable description * @throws DSpaceSwordException * can be thrown by the internals of the DSpace SWORD implementation */ private String getTreatment() throws DSpaceSwordException { return "The package has been ingested and unpacked into the item. Template metadata for " + "the collection has been used, and a default title with the name of the file has " + "been set"; } }