mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@6073 9c30dcfa-912a-0410-8fc2-9e0234be79fd
454 lines
17 KiB
Java
454 lines
17 KiB
Java
/**
|
|
* 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.embargo;
|
|
|
|
import java.io.IOException;
|
|
import java.sql.SQLException;
|
|
import java.util.Date;
|
|
|
|
import org.apache.commons.cli.CommandLine;
|
|
import org.apache.commons.cli.HelpFormatter;
|
|
import org.apache.commons.cli.Options;
|
|
import org.apache.commons.cli.ParseException;
|
|
import org.apache.commons.cli.PosixParser;
|
|
import org.apache.log4j.Logger;
|
|
import org.dspace.authorize.AuthorizeException;
|
|
import org.dspace.content.DCDate;
|
|
import org.dspace.content.DCValue;
|
|
import org.dspace.content.DSpaceObject;
|
|
import org.dspace.content.Item;
|
|
import org.dspace.content.ItemIterator;
|
|
import org.dspace.content.MetadataSchema;
|
|
import org.dspace.core.ConfigurationManager;
|
|
import org.dspace.core.Constants;
|
|
import org.dspace.core.Context;
|
|
import org.dspace.core.PluginManager;
|
|
import org.dspace.handle.HandleManager;
|
|
|
|
/**
|
|
* Public interface to the embargo subsystem.
|
|
* <p>
|
|
* Configuration properties: (with examples)
|
|
* <br/># DC metadata field to hold the user-supplied embargo terms
|
|
* <br/>embargo.field.terms = dc.embargo.terms
|
|
* <br/># DC metadata field to hold computed "lift date" of embargo
|
|
* <br/>embargo.field.lift = dc.date.available
|
|
* <br/># String to indicate indefinite (forever) embargo in terms
|
|
* <br/>embargo.terms.open = Indefinite
|
|
* <br/># implementation of embargo setter plugin
|
|
* <br/>plugin.single.org.dspace.embargo.EmbargoSetter = edu.my.Setter
|
|
* <br/># implementation of embargo lifter plugin
|
|
* <br/>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();
|
|
// if lift is null, we might be restoring an item from an AIP
|
|
DCDate myLift = lift;
|
|
if (myLift == null)
|
|
{
|
|
if ((myLift = recoverEmbargoDate(item)) == null)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
String slift = myLift.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.
|
|
* <p>
|
|
* 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 = null;
|
|
|
|
// Its poor form to blindly use an object that could be null...
|
|
if (terms == null)
|
|
return null;
|
|
|
|
result = setter.parseTerms(context, item,
|
|
terms.length > 0 ? terms[0].value : null);
|
|
|
|
if (result == null)
|
|
return null;
|
|
|
|
// new DCDate(non-date String) means toDate() will return null
|
|
Date liftDate = result.toDate();
|
|
if (liftDate == null)
|
|
{
|
|
throw new IllegalArgumentException(
|
|
"Embargo lift date is uninterpretable: "
|
|
+ result.toString());
|
|
}
|
|
|
|
// sanity check: do not allow an embargo lift date in the past.
|
|
if (liftDate.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 Item with an expired embargo,
|
|
* and then lift that embargo.
|
|
* <p>
|
|
* Options:
|
|
* <dl>
|
|
* <dt>-c,--check</dt>
|
|
* <dd> Function: ONLY check the state of embargoed Items, do
|
|
* NOT lift any embargoes.</dd>
|
|
* <dt>-h,--help</dt>
|
|
* <dd> Help.</dd>
|
|
* <dt>-i,--identifier</dt>
|
|
* <dd> Process ONLY this Handle identifier(s), which must be
|
|
* an Item. Can be repeated.</dd>
|
|
* <dt>-l,--lift</dt>
|
|
* <dd> Function: ONLY lift embargoes, do NOT check the state
|
|
* of any embargoed Items.</dd>
|
|
* <dt>-n,--dryrun</dt>
|
|
* <dd> Do not change anything in the data model; print
|
|
* message instead.</dd>
|
|
* <dt>-v,--verbose</dt>
|
|
* <dd> Print a line describing action taken for each
|
|
* embargoed Item found.</dd>
|
|
* <dt>-q,--quiet</dt>
|
|
* <dd> No output except upon error.</dd>
|
|
* </dl>
|
|
*/
|
|
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 false 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 spec
|
|
private static String getSchemaOf(String field)
|
|
{
|
|
String sa[] = field.split("\\.", 3);
|
|
return sa[0];
|
|
}
|
|
|
|
// return the element part of "schema.element.qualifier" metadata field spec, if any
|
|
private static String getElementOf(String field)
|
|
{
|
|
String sa[] = field.split("\\.", 3);
|
|
return sa.length > 1 ? sa[1] : null;
|
|
}
|
|
|
|
// return the qualifier part of "schema.element.qualifier" metadata field spec, if any
|
|
private static String getQualifierOf(String field)
|
|
{
|
|
String sa[] = field.split("\\.", 3);
|
|
return sa.length > 2 ? sa[2] : null;
|
|
}
|
|
|
|
// return the lift date assigned when embargo was set, or null, if either:
|
|
// it was never under embargo, or the lift date has passed.
|
|
private static DCDate recoverEmbargoDate(Item item) {
|
|
DCDate liftDate = null;
|
|
DCValue lift[] = item.getMetadata(lift_schema, lift_element, lift_qualifier, Item.ANY);
|
|
if (lift.length > 0)
|
|
{
|
|
liftDate = new DCDate(lift[0].value);
|
|
// sanity check: do not allow an embargo lift date in the past.
|
|
if (liftDate.toDate().before(new Date()))
|
|
{
|
|
liftDate = null;
|
|
}
|
|
}
|
|
return liftDate;
|
|
}
|
|
}
|