diff --git a/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoLifter.java b/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoLifter.java new file mode 100644 index 0000000000..a641a57b5b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoLifter.java @@ -0,0 +1,75 @@ +/* + * DefaultEmbargoLifter.java + * + * Version: $Revision: 1.1 $ + * + * Date: $Date: 2009/07/16 01:52:59 $ + * + * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Hewlett-Packard Company nor the name of the + * Massachusetts Institute of Technology nor the names of their + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package org.dspace.embargo; + +import java.sql.SQLException; +import java.io.IOException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Item; +import org.dspace.core.Context; + +/** + * Plugin interface for the embargo lifting function. + * + * @author Larry Stone + * @author Richard Rodgers + */ +public class DefaultEmbargoLifter implements EmbargoLifter +{ + public DefaultEmbargoLifter() + { + super(); + } + + /** + * Enforce lifting of embargo by turning read access to bitstreams in + * this Item back on. + * + * @param context the DSpace context + * @param item the item to embargo + */ + public void liftEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException + { + // remove the item's policies and replace them with + // the defaults from the collection + item.inheritCollectionDefaultPolicies(item.getOwningCollection()); + } +} diff --git a/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoSetter.java b/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoSetter.java new file mode 100644 index 0000000000..1245073798 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/embargo/DefaultEmbargoSetter.java @@ -0,0 +1,164 @@ +/* + * DefaultEmbargoSetter.java + * + * Version: $Revision: 1.1 $ + * + * Date: $Date: 2009/07/16 01:52:59 $ + * + * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Hewlett-Packard Company nor the name of the + * Massachusetts Institute of Technology nor the names of their + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package org.dspace.embargo; + +import java.sql.SQLException; +import java.io.IOException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.core.Constants; + +/** + * Default plugin implementation of the embargo setting function. + * The parseTerms() provides only very rudimentary terms logic - entry + * of a configurable string (in terms field) for 'unlimited' embargo, otherwise + * a standard ISO 8601 (yyyy-mm-dd) date is assumed. Users are encouraged + * to override this method for enhanced functionality. + * + * @author Larry Stone + * @author Richard Rodgers + */ +public class DefaultEmbargoSetter implements EmbargoSetter +{ + private String termsOpen = null; + + public DefaultEmbargoSetter() + { + super(); + termsOpen = ConfigurationManager.getProperty("embargo.terms.open"); + } + + /** + * Parse the terms into a definite date. Terms are expected to consist of + * either: a token (value configured in 'embargo.terms.open' property) to indicate + * indefinite embargo, or a literal lift date formatted in ISO 8601 format (yyyy-mm-dd) + * + * @param context the DSpace context + * @param item the item to embargo + * @param terms the embargo terms + * @return parsed date in DCDate format + */ + public DCDate parseTerms(Context context, Item item, String terms) + throws SQLException, AuthorizeException, IOException + { + if (terms != null && terms.length() > 0) + { + if (termsOpen.equals(terms)) + return EmbargoManager.FOREVER; + else + return new DCDate(terms); + } + return null; + } + + /** + * Enforce embargo by turning off all read access to bitstreams in + * this Item. + * + * @param context the DSpace context + * @param item the item to embargo + */ + public void setEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException + { + for (Bundle bn : item.getBundles()) + { + // Skip the LICENSE and METADATA bundles, they stay world-readable + String bnn = bn.getName(); + if (!(bnn.equals(Constants.LICENSE_BUNDLE_NAME) || bnn.equals(Constants.METADATA_BUNDLE_NAME))) + { + AuthorizeManager.removePoliciesActionFilter(context, bn, Constants.READ); + for (Bitstream bs : bn.getBitstreams()) + { + AuthorizeManager.removePoliciesActionFilter(context, bs, Constants.READ); + } + } + } + } + + /** + * Check that embargo is properly set on Item, e.g. no read access + * to bitstreams. + * + * @param context the DSpace context + * @param item the item to embargo + */ + public void checkEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException + { + for (Bundle bn : item.getBundles()) + { + // Skip the LICENSE and METADATA bundles, they stay world-readable + String bnn = bn.getName(); + if (!(bnn.equals(Constants.LICENSE_BUNDLE_NAME) || bnn.equals(Constants.METADATA_BUNDLE_NAME))) + { + // don't report on "TEXT" or "THUMBNAIL" bundles; those + // can have READ long as the bitstreams in them do not. + if (!(bnn.equals("TEXT") || bnn.equals("THUMBNAIL"))) + { + // check for ANY read policies and report them: + for (ResourcePolicy rp : AuthorizeManager.getPoliciesActionFilter(context, bn, Constants.READ)) + { + System.out.println("CHECK WARNING: Item "+item.getHandle()+", Bundle "+bn.getName()+" allows READ by "+ + ((rp.getEPersonID() < 0) ? "Group "+rp.getGroup().getName() : + "EPerson "+rp.getEPerson().getFullName())); + } + } + + for (Bitstream bs : bn.getBitstreams()) + { + for (ResourcePolicy rp : AuthorizeManager.getPoliciesActionFilter(context, bs, Constants.READ)) + { + System.out.println("CHECK WARNING: Item "+item.getHandle()+", Bitstream "+bs.getName()+" (in Bundle "+bn.getName()+") allows READ by "+ + ((rp.getEPersonID() < 0) ? "Group "+rp.getGroup().getName() : + "EPerson "+rp.getEPerson().getFullName())); + } + } + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/embargo/EmbargoLifter.java b/dspace-api/src/main/java/org/dspace/embargo/EmbargoLifter.java new file mode 100644 index 0000000000..d0ad2ead0f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/embargo/EmbargoLifter.java @@ -0,0 +1,66 @@ +/* + * EmbargoLifter.java + * + * Version: $Revision: 1.1 $ + * + * Date: $Date: 2009/07/16 01:52:59 $ + * + * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Hewlett-Packard Company nor the name of the + * Massachusetts Institute of Technology nor the names of their + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package org.dspace.embargo; + +import java.sql.SQLException; +import java.io.IOException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Item; +import org.dspace.core.Context; + + +/** + * Plugin interface for the embargo lifting function. + * + * @author Larry Stone + * @author Richard Rodgers + */ +public interface EmbargoLifter +{ + /** + * Implement the lifting of embargo in the "resource policies" + * (access control) by e.g. turning on default read access to all Bitstreams. + * + * @param context the DSpace context + * @param item the Item on which to lift the embargo + */ + public void liftEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException; +} diff --git a/dspace-api/src/main/java/org/dspace/embargo/EmbargoManager.java b/dspace-api/src/main/java/org/dspace/embargo/EmbargoManager.java new file mode 100644 index 0000000000..5efe006af5 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/embargo/EmbargoManager.java @@ -0,0 +1,414 @@ +/* + * EmbargoManager.java + * + * Version: $Revision: 1.10 $ + * + * Date: $Date: 2009/09/08 20:03:45 $ + * + * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Hewlett-Packard Company nor the name of the + * Massachusetts Institute of Technology nor the names of their + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package org.dspace.embargo; + +import java.sql.SQLException; +import java.util.Date; +import java.io.IOException; + +import org.apache.log4j.Logger; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; +import org.apache.commons.cli.ParseException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Item; +import org.dspace.content.ItemIterator; +import org.dspace.content.DCDate; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.MetadataSchema; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.core.Utils; +import org.dspace.core.PluginManager; +import org.dspace.handle.HandleManager; + +/** + * Public interface to the embargo subsystem. + * + * Configuration properties: (with examples) + * # DC metadata field to hold the user-supplied embargo terms + * embargo.field.terms = dc.embargo.terms + * # DC metadata field to hold computed "lift date" of embargo + * embargo.field.lift = dc.date.available + * # String to indicate indefinite (forever) embargo in terms + * embargo.terms.open = Indefinite + * # implementation of embargo setter plugin + * plugin.single.org.dspace.embargo.EmbargoSetter = edu.my.Setter + * # implementation of embargo lifter plugin + * plugin.single.org.dspace.embargo.EmbargoLifter = edu.my.Lifter + * + * @author Larry Stone + * @author Richard Rodgers + */ +public class EmbargoManager +{ + /** Special date signalling an Item is to be embargoed forever. + ** The actual date is the first day of the year 10,000 UTC. + **/ + public static final DCDate FOREVER = new DCDate("10000-01-01"); + + /** log4j category */ + private static Logger log = Logger.getLogger(EmbargoManager.class); + + // Metadata field components for user-supplied embargo terms + // set from the DSpace configuration by init() + private static String terms_schema = null; + private static String terms_element = null; + private static String terms_qualifier = null; + + // Metadata field components for lift date, encoded as a DCDate + // set from the DSpace configuration by init() + private static String lift_schema = null; + private static String lift_element = null; + private static String lift_qualifier = null; + + // plugin implementations + // set from the DSpace configuration by init() + private static EmbargoSetter setter = null; + private static EmbargoLifter lifter = null; + + /** + * Put an Item under embargo until the specified lift date. + * Calls EmbargoSetter plugin to adjust Item access control policies. + * + * @param context the DSpace context + * @param item the item to embargo + * @param lift date on which the embargo is to be lifted. + */ + public static void setEmbargo(Context context, Item item, DCDate lift) + throws SQLException, AuthorizeException, IOException + { + init(); + String slift = lift.toString(); + boolean ignoreAuth = context.ignoreAuthorization(); + try + { + context.setIgnoreAuthorization(true); + item.clearMetadata(lift_schema, lift_element, lift_qualifier, Item.ANY); + item.addMetadata(lift_schema, lift_element, lift_qualifier, null, slift); + log.info("Set embargo on Item "+item.getHandle()+", expires on: "+slift); + setter.setEmbargo(context, item); + item.update(); + } + finally + { + context.setIgnoreAuthorization(ignoreAuth); + } + } + + /** + * Get the embargo lift date for an Item, if any. This looks for the + * metadata field configured to hold embargo terms, and gives it + * to the EmbargoSetter plugin's method to interpret it into + * an absolute timestamp. This is intended to be called at the time + * the Item is installed into the archive. + *

+ * Note that the plugin is *always* called, in case it gets its cue for + * the embargo date from sources other than, or in addition to, the + * specified field. + * + * @param context the DSpace context + * @param item the item to embargo + * @return lift date on which the embargo is to be lifted, or null if none + */ + public static DCDate getEmbargoDate(Context context, Item item) + throws SQLException, AuthorizeException, IOException + { + init(); + DCValue terms[] = item.getMetadata(terms_schema, terms_element, terms_qualifier, Item.ANY); + DCDate result = setter.parseTerms(context, item, terms.length > 0 ? terms[0].value : null); + + // sanity check: do not allow an embargo lift date in the past. + if (result != null && result.toDate().before(new Date())) + { + throw new IllegalArgumentException("Embargo lift date must be in the future, but this is in the past: "+result.toString()); + } + return result; + } + + /** + * Lift the embargo on an item which is assumed to be under embargo. + * Call the plugin to manage permissions in its own way, then delete + * the administrative metadata fields that dictated embargo date. + * + * @param context the DSpace context + * @param item the item on which to lift the embargo + */ + public static void liftEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException + { + init(); + lifter.liftEmbargo(context, item); + item.clearMetadata(lift_schema, lift_element, lift_qualifier, Item.ANY); + + // set the dc.date.available value to right now + item.clearMetadata(MetadataSchema.DC_SCHEMA, "date", "available", Item.ANY); + item.addMetadata(MetadataSchema.DC_SCHEMA, "date", "available", null, DCDate.getCurrent().toString()); + + log.info("Lifting embargo on Item "+item.getHandle()); + item.update(); + } + + /** + * Command-line service to scan for every Items with an expired embargo, + * and then lift that embargo. + * + * Options: + * -c,--check Function: ONLY check the state of embargoed Items, do + * NOT lift any embargoes. + * -h,--help help + * -i,--identifier Process ONLY this Handle identifier(s), which must be + * an Item. Can be repeated. + * -l,--lift Function: ONLY lift embargoes, do NOT check the state + * of any embargoed Items. + * -n,--dryrun Do not change anything in the data model, print + * message instead. + * -v,--verbose Print a line describing action taken for each + * embargoed Item found. + * -q,--quiet No output except upon error + */ + public static void main(String argv[]) + { + init(); + int status = 0; + + Options options = new Options(); + options.addOption("v", "verbose", false, + "Print a line describing action taken for each embargoed Item found."); + options.addOption("q", "quiet", false, + "Do not print anything except for errors."); + options.addOption("n", "dryrun", false, + "Do not change anything in the data model, print message instead."); + options.addOption("i", "identifier", true, + "Process ONLY this Handle identifier(s), which must be an Item. Can be repeated."); + options.addOption("c", "check", false, + "Function: ONLY check the state of embargoed Items, do NOT lift any embargoes."); + options.addOption("l", "lift", false, + "Function: ONLY lift embargoes, do NOT check the state of any embargoed Items."); + options.addOption("h", "help", false, "help"); + CommandLine line = null; + try + { + line = new PosixParser().parse(options, argv); + } + catch(ParseException e) + { + System.err.println("Command error: " + e.getMessage()); + new HelpFormatter().printHelp(EmbargoManager.class.getName(), options); + System.exit(1); + } + + if (line.hasOption('h')) + { + new HelpFormatter().printHelp(EmbargoManager.class.getName(), options); + System.exit(0); + } + + // sanity check, --lift and --check are mutually exclusive: + if (line.hasOption('l') && line.hasOption('c')) + { + System.err.println("Command error: --lift and --check are mutually exclusive, try --help for assistance."); + System.exit(1); + } + + Context context = null; + try + { + context = new Context(); + context.setIgnoreAuthorization(true); + Date now = new Date(); + + // scan items under embargo + if (line.hasOption('i')) + { + for (String handle : line.getOptionValues('i')) + { + DSpaceObject dso = HandleManager.resolveToObject(context, handle); + if (dso == null) + { + System.err.println("Error, cannot resolve handle="+handle+" to a DSpace Item."); + status = 1; + } + else if (dso.getType() != Constants.ITEM) + { + System.err.println("Error, the handle="+handle+" is not a DSpace Item."); + status = 1; + } + else + { + if (processOneItem(context, (Item)dso, line, now)) + status = 1; + } + } + } + else + { + ItemIterator ii = Item.findByMetadataField(context, lift_schema, lift_element, lift_qualifier, Item.ANY); + while (ii.hasNext()) + { + if (processOneItem(context, ii.next(), line, now)) + status = 1; + } + } + log.debug("Cache size at end = "+context.getCacheSize()); + context.complete(); + context = null; + } + catch (Exception e) + { + System.err.println("ERROR, got exception: "+e); + e.printStackTrace(); + status = 1; + } + finally + { + if (context != null) + { + try + { + context.abort(); + } + catch (Exception e) + { + } + } + } + System.exit(status); + } + + // lift or check embargo on one Item, handle exceptions + // return flase on success, true if there was fatal exception. + private static boolean processOneItem(Context context, Item item, CommandLine line, Date now) + throws Exception + { + boolean status = false; + DCValue lift[] = item.getMetadata(lift_schema, lift_element, lift_qualifier, Item.ANY); + + if (lift.length > 0) + { + // need to survive any failure on a single item, go on to process the rest. + try + { + DCDate liftDate = new DCDate(lift[0].value); + log.debug("Testing embargo on item="+item.getHandle()+", date="+liftDate.toString()); + if (liftDate.toDate().before(now)) + { + if (line.hasOption('v')) + System.err.println("Lifting embargo from Item handle="+item.getHandle()+", lift date="+lift[0].value); + if (line.hasOption('n')) + { + if (!line.hasOption('q')) + System.err.println("DRY RUN: would have lifted embargo from Item handle="+item.getHandle()+", lift date="+lift[0].value); + } + else if (!line.hasOption('c')) + liftEmbargo(context, item); + } + else if (!line.hasOption('l')) + { + if (line.hasOption('v')) + System.err.println("Checking current embargo on Item handle="+item.getHandle()+", lift date="+lift[0].value); + setter.checkEmbargo(context, item); + } + } + catch (Exception e) + { + log.error("Failed attempting to lift embargo, item="+item.getHandle()+": ", e); + System.err.println("Failed attempting to lift embargo, item="+item.getHandle()+": "+ e); + status = true; + } + } + context.removeCached(item, item.getID()); + return status; + } + + // initialize - get plugins and MD field settings from config + private static void init() + { + if (terms_schema == null) + { + String terms = ConfigurationManager.getProperty("embargo.field.terms"); + String lift = ConfigurationManager.getProperty("embargo.field.lift"); + if (terms == null || lift == null) + throw new IllegalStateException("Missing one or more of the required DSpace configuration properties for EmbargoManager, check your configuration file."); + terms_schema = getSchemaOf(terms); + terms_element = getElementOf(terms); + terms_qualifier = getQualifierOf(terms); + lift_schema = getSchemaOf(lift); + lift_element = getElementOf(lift); + lift_qualifier = getQualifierOf(lift); + + setter = (EmbargoSetter)PluginManager.getSinglePlugin(EmbargoSetter.class); + if (setter == null) + throw new IllegalStateException("The EmbargoSetter plugin was not defined in DSpace configuration."); + lifter = (EmbargoLifter)PluginManager.getSinglePlugin(EmbargoLifter.class); + if (lifter == null) + throw new IllegalStateException("The EmbargoLifter plugin was not defined in DSpace configuration."); + + } + } + + // return the schema part of "schema.element.qualifier" metadata field + private static String getSchemaOf(String field) + { + String sa[] = field.split("\\.", 3); + return sa[0]; + } + + // return the schema part of "schema.element.qualifier" metadata field + private static String getElementOf(String field) + { + String sa[] = field.split("\\.", 3); + return sa.length > 0 ? sa[1] : null; + } + + // return the schema part of "schema.element.qualifier" metadata field + private static String getQualifierOf(String field) + { + String sa[] = field.split("\\.", 3); + return sa.length > 1 ? sa[2] : null; + } +} diff --git a/dspace-api/src/main/java/org/dspace/embargo/EmbargoSetter.java b/dspace-api/src/main/java/org/dspace/embargo/EmbargoSetter.java new file mode 100644 index 0000000000..e9b71e7fd1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/embargo/EmbargoSetter.java @@ -0,0 +1,106 @@ +/* + * EmbargoSetter.java + * + * Version: $Revision: 1.2 $ + * + * Date: $Date: 2009/08/05 21:59:34 $ + * + * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Hewlett-Packard Company nor the name of the + * Massachusetts Institute of Technology nor the names of their + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package org.dspace.embargo; + +import java.util.Date; +import java.sql.SQLException; +import java.io.IOException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.core.Context; + +/** + * Plugin interface for the embargo setting function. + * + * @author Larry Stone + * @author Richard Rodgers + */ +public interface EmbargoSetter +{ + /** + * Get lift date of embargo from the "terms" supplied in the + * metadata (or other available state) of this Item. Return null + * if it is clear this should not be under embargo -- that is to be + * expected since this method is invoked on all newly-archived Items. + *

+ * Note that the value (if any) of the metadata field configured to + * contain embargo terms is passed explicitly, but this method is + * free to explore other metadata fields, and even Bitstream contents, + * to determine the embargo status and lift date. + *

+ * Expect this method to be called at the moment before the Item is + * installed into the archive (i.e. after workflow). This may be + * significant if the embargo lift date is computed relative to the present. + * + * @param context the DSpace context + * @param item the item to embargo + * @param terms value of the metadata field configured as embargo terms, if any. + * @return absolute date on which the embargo is to be lifted, or null if none + */ + public DCDate parseTerms(Context context, Item item, String terms) + throws SQLException, AuthorizeException, IOException; + + /** + * Enforce embargo by e.g. turning off all read access to bitstreams in + * this Item. + * + * @param context the DSpace context + * @param item the item to embargo + */ + public void setEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException; + + /** + * Check that embargo is properly set on Item, e.g. no read access + * to bitstreams. It is expected to report any noteworthy + * discrepencies by writing on the stream System.err, although + * logging is also encouraged. Only report conditions that + * constitute a risk of exposing Bitstreams that should be under + * embargo -- e.g. readable Bitstreams or ORIGINAL bundles. A + * readable bundle named "TEXT" does not constitute a direct risk so + * long as its member Bitstreams are not readable. + * + * @param context the DSpace context + * @param item the item to embargo + */ + public void checkEmbargo(Context context, Item item) + throws SQLException, AuthorizeException, IOException; +}