(Alexey Maslov) OAI-PMH + OAI-ORE Harvesting Patch

http://jira.dspace.org/jira/browse/DS-289

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@4228 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Scott Phillips
2009-08-24 21:18:09 +00:00
parent 57ea973114
commit 3dacc68256
35 changed files with 5686 additions and 60 deletions

View File

@@ -176,6 +176,10 @@
<groupId>com.ibm.icu</groupId> <groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId> <artifactId>icu4j</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>oclc-harvester2</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,561 @@
/*
* Harvest.java
*
* Version: $Revision: 1 $
*
* Date: $Date: 2007-11-28 15:07:34 -0600 (Wed, 28 Nov 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.app.harvest;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.xpath.XPathAPI;
import org.dspace.app.itemimport.ItemImport;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.IndexBrowse;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.FormatIdentifier;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.content.InstallItem;
import org.dspace.content.Item;
import org.dspace.content.ItemIterator;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.harvest.OAIHarvester;
import org.dspace.content.WorkspaceItem;
import org.dspace.harvest.OAIHarvester.HarvestingException;
import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.handle.HandleManager;
import org.dspace.workflow.WorkflowManager;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Test class for harvested collections.
*
* @author Alexey Maslov
*/
public class Harvest
{
private static Context context;
public static void main(String[] argv) throws Exception
{
// create an options object and populate it
CommandLineParser parser = new PosixParser();
Options options = new Options();
options.addOption("p", "purge", false, "delete all items in the collection");
options.addOption("r", "run", false, "run the standrad harvest procedure");
options.addOption("g", "ping", false, "test the OAI server and set");
options.addOption("o", "once", false, "run the harvest procedure with specified parameters");
options.addOption("s", "setup", false, "Set the collection up for harvesting");
options.addOption("S", "start", false, "start the harvest loop");
options.addOption("R", "reset", false, "reset harvest status on all collections");
options.addOption("P", "purge", false, "purge all harvestable collections");
options.addOption("e", "eperson", true, "eperson");
options.addOption("c", "collection", true, "harvesting collection (handle or id)");
options.addOption("t", "type", true, "type of harvesting (0 for none)");
options.addOption("a", "address", true, "address of the OAI-PMH server");
options.addOption("i", "oai_set_id", true, "id of the PMH set representing the harvested collection");
options.addOption("m", "metadata_format", true, "the name of the desired metadata format for harvesting, resolved to namespace and crosswalk in dspace.cfg");
options.addOption("h", "help", false, "help");
CommandLine line = parser.parse(options, argv);
String command = null;
String eperson = null;
String collection = null;
String oaiSource = null;
String oaiSetID = null;
String metadataKey = null;
int harvestType = 0;
if (line.hasOption('h'))
{
HelpFormatter myhelp = new HelpFormatter();
myhelp.printHelp("Harvest\n", options);
System.out
.println("\nPING OAI server: Harvest -g -s oai_source -i oai_set_id");
System.out
.println("RUNONCE harvest with arbitrary options: Harvest -o -e eperson -c collection -t harvest_type -a oai_source -i oai_set_id -m metadata_format");
System.out
.println("SETUP a collection for harvesting: Harvest -s -c collection -t harvest_type -a oai_source -i oai_set_id -m metadata_format");
System.out
.println("RUN harvest once: Harvest -r -e eperson -c collection");
System.out
.println("START harvest scheduler: Harvest -S");
System.out
.println("RESET all harvest status: Harvest -R");
System.out
.println("PURGE a collection of items and settings: Harvest -p -e eperson -c collection");
System.out
.println("PURGE all harvestable collections: Harvest -P -e eperson");
System.exit(0);
}
if (line.hasOption('s')) {
command = "config";
}
if (line.hasOption('p')) {
command = "purge";
}
if (line.hasOption('r')) {
command = "run";
}
if (line.hasOption('g')) {
command = "ping";
}
if (line.hasOption('o')) {
command = "runOnce";
}
if (line.hasOption('S')) {
command = "start";
}
if (line.hasOption('R')) {
command = "reset";
}
if (line.hasOption('P')) {
command = "purgeAll";
}
if (line.hasOption('e')) {
eperson = line.getOptionValue('e');
}
if (line.hasOption('c')) {
collection = line.getOptionValue('c');
}
if (line.hasOption('t')) {
harvestType = Integer.parseInt(line.getOptionValue('t'));
} else {
harvestType = 0;
}
if (line.hasOption('a')) {
oaiSource = line.getOptionValue('a');
}
if (line.hasOption('i')) {
oaiSetID = line.getOptionValue('i');
}
if (line.hasOption('m')) {
metadataKey = line.getOptionValue('m');
}
// Instantiate our class
Harvest harvester = new Harvest();
harvester.context = new Context();
// Check our options
if (command == null)
{
System.out
.println("Error - no parameters specified (run with -h flag for details)");
System.exit(1);
}
// Run a single harvest cycle on a collection using saved settings.
else if (command.equals("run"))
{
if (collection == null || eperson == null)
{
System.out
.println("Error - a target collection and eperson must be provided");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
harvester.runHarvest(collection, eperson);
}
// start the harvest loop
else if (command.equals("start"))
{
startHarvester();
}
// reset harvesting status
else if (command.equals("reset"))
{
resetHarvesting();
}
// purge all collections that are set up for harvesting (obviously for testing purposes only)
else if (command.equals("purgeAll"))
{
if (eperson == null)
{
System.out
.println("Error - an eperson must be provided");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
List<Integer> cids = HarvestedCollection.findAll(context);
System.out.println("Purging the following collections (deleting items and resetting harvest status): " + cids.toString());
for (Integer cid : cids)
{
harvester.purgeCollection(cid.toString(), eperson);
}
context.complete();
}
// Delete all items in a collection. Useful for testing fresh harvests.
else if (command.equals("purge"))
{
if (collection == null || eperson == null)
{
System.out
.println("Error - a target collection and eperson must be provided");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
harvester.purgeCollection(collection, eperson);
context.complete();
//TODO: implement this... remove all items and remember to unset "last-harvested" settings
}
// Configure a collection with the three main settings
else if (command.equals("config"))
{
if (collection == null)
{
System.out.println("Error - a target collection must be provided");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
if (oaiSource == null || oaiSetID == null)
{
System.out.println("Error - both the OAI server address and OAI set id must be specified");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
if (metadataKey == null)
{
System.out.println("Error - a metadata key (commonly the prefix) must be specified for this collection");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
harvester.configureCollection(collection, harvestType, oaiSource, oaiSetID, metadataKey);
}
else if (command.equals("ping"))
{
if (oaiSource == null || oaiSetID == null)
{
System.out.println("Error - both the OAI server address and OAI set id must be specified");
System.out.println(" (run with -h flag for details)");
System.exit(1);
}
}
}
/**
* check
* @param collectionID
* @return
*/
private Collection checkCollection(String collectionID)
{
Collection collection = resolveCollection(collectionID);
try {
HarvestedCollection hc = HarvestedCollection.find(context, collection.getID());
if (!hc.isHarvestable()) {
System.out.println("Collection '"+ collection.getName() +"' is not set up for harvesting");
System.exit(1);
}
} catch (SQLException se) {
se.printStackTrace();
}
return collection;
}
/*
* Resolve the ID into a collection and check to see if its harvesting options are set. If so, return
* the collection, if not, bail out.
*/
private Collection resolveCollection(String collectionID) {
DSpaceObject dso;
Collection targetCollection = null;
try {
// is the ID a handle?
if (collectionID.indexOf('/') != -1)
{
// string has a / so it must be a handle - try and resolve it
dso = HandleManager.resolveToObject(context, collectionID);
// resolved, now make sure it's a collection
if (dso == null || dso.getType() != Constants.COLLECTION)
targetCollection = null;
else
targetCollection = (Collection)dso;
}
// not a handle, try and treat it as an integer collection
// database ID
else if (collectionID != null)
{
System.out.println("Looking up by id: " + collectionID + ", parsed as '" + Integer.parseInt(collectionID) + "', " + "in context: " + context);
targetCollection = Collection.find(context, Integer.parseInt(collectionID));
}
// was the collection valid?
if (targetCollection == null)
{
System.out.println("Cannot resolve " + collectionID + " to collection");
System.exit(1);
}
}
catch (SQLException se) {
se.printStackTrace();
}
return targetCollection;
}
private void configureCollection(String collectionID, int type, String oaiSource, String oaiSetId, String mdConfigId) {
System.out.println("Running: configure collection");
Collection collection = resolveCollection(collectionID);
System.out.println(collection.getID());
try {
HarvestedCollection hc = HarvestedCollection.find(context, collection.getID());
if (hc == null) {
hc = HarvestedCollection.create(context, collection.getID());
}
context.turnOffAuthorisationSystem();
hc.setHarvestParams(type, oaiSource, oaiSetId, mdConfigId);
hc.setHarvestStatus(HarvestedCollection.STATUS_READY);
hc.update();
context.restoreAuthSystemState();
context.complete();
}
catch (Exception e) {
System.out.println("Changes could not be committed");
e.printStackTrace();
System.exit(1);
}
finally {
context.restoreAuthSystemState();
}
}
/**
* Purges a collection of all harvest-related data and settings. All items in the collection will be deleted.
*
* @param collectionID
* @param email
*/
private void purgeCollection(String collectionID, String email) {
System.out.println("Purging collection of all items and reseting last_harvested and harvest_message: " + collectionID);
Collection collection = resolveCollection(collectionID);
try
{
EPerson eperson = EPerson.findByEmail(context, email);
context.setCurrentUser(eperson);
context.turnOffAuthorisationSystem();
ItemIterator it = collection.getAllItems();
IndexBrowse ib = new IndexBrowse(context);
int i=0;
while (it.hasNext()) {
i++;
Item item = it.next();
System.out.println("Deleting: " + item.getHandle());
ib.itemRemoved(item);
collection.removeItem(item);
// commit every 50 items
if (i%50 == 0) {
context.commit();
i=0;
}
}
HarvestedCollection hc = HarvestedCollection.find(context, collection.getID());
if (hc != null) {
hc.setHarvestResult(null,"");
hc.setHarvestStatus(HarvestedCollection.STATUS_READY);
hc.setHarvestStartTime(null);
hc.update();
}
context.restoreAuthSystemState();
context.commit();
}
catch (Exception e) {
System.out.println("Changes could not be committed");
e.printStackTrace();
System.exit(1);
}
finally {
context.restoreAuthSystemState();
}
}
/**
* Run a single harvest cycle on the specified collection under the authorization of the supplied EPerson
*/
private void runHarvest(String collectionID, String email) {
System.out.println("Running: a harvest cycle on " + collectionID);
System.out.print("Initializing the harvester... ");
OAIHarvester harvester = null;
try {
Collection collection = resolveCollection(collectionID);
HarvestedCollection hc = HarvestedCollection.find(context, collection.getID());
harvester = new OAIHarvester(context, collection, hc);
System.out.println("success. ");
}
catch (HarvestingException hex) {
System.out.print("failed. ");
System.out.println(hex.getMessage());
System.exit(1);
} catch (SQLException se) {
// TODO Auto-generated catch block
se.printStackTrace();
}
try {
// Harvest will not work for an anonymous user
EPerson eperson = EPerson.findByEmail(context, email);
System.out.println("Harvest started... ");
context.setCurrentUser(eperson);
harvester.runHarvest();
context.complete();
}
catch (Exception e) {
// Not much else we can do at this point
e.printStackTrace();
System.exit(1);
}
System.out.println("Harvest complete. ");
}
/**
* Resets harvest_status and harvest_start_time flags for all collections that have a row in the harvested_collections table
*/
private static void resetHarvesting() {
System.out.print("Resetting harvest status flag on all collections... ");
try
{
List<Integer> cids = HarvestedCollection.findAll(context);
for (Integer cid : cids)
{
HarvestedCollection hc = HarvestedCollection.find(context, cid);
//hc.setHarvestResult(null,"");
hc.setHarvestStartTime(null);
hc.setHarvestStatus(HarvestedCollection.STATUS_READY);
hc.update();
}
context.commit();
System.out.println("success. ");
}
catch (Exception ex) {
System.out.println("failed. ");
ex.printStackTrace();
}
}
/**
* Starts up the harvest scheduler. Terminating this process will stop the scheduler.
*/
private static void startHarvester()
{
try
{
System.out.print("Starting harvest loop... ");
OAIHarvester.startNewScheduler();
System.out.println("running. ");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

View File

@@ -258,9 +258,9 @@ public class Item extends DSpaceObject
// Call update to give the item a last modified date. OK this isn't // Call update to give the item a last modified date. OK this isn't
// amazingly efficient but creates don't happen that often. // amazingly efficient but creates don't happen that often.
context.setIgnoreAuthorization(true); context.turnOffAuthorisationSystem();
i.update(); i.update();
context.setIgnoreAuthorization(false); context.restoreAuthSystemState();
context.addEvent(new Event(Event.CREATE, Constants.ITEM, i.getID(), null)); context.addEvent(new Event(Event.CREATE, Constants.ITEM, i.getID(), null));

View File

@@ -0,0 +1,161 @@
/*
* DIMDisseminationCrosswalk.java
*
* Version: $Revision: 1 $
*
* Date: $Date: 2007-07-30 12:26:50 -0500 (Mon, 30 Jul 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.content.crosswalk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Utils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* DIM dissemination crosswalk
* <p>
* Produces the metadata encoded in DSpace Intermediate Format, without the overhead of XSLT processing.
*
* @author Alexey Maslov
* @version $Revision: 1 $
*/
public class DIMDisseminationCrosswalk
implements DisseminationCrosswalk
{
/** log4j category */
private static Logger log = Logger.getLogger(OREDisseminationCrosswalk.class);
// Non-existant XSD schema
public static final String DIM_XSD = "null";
// Namespaces
public static final Namespace DIM_NS =
Namespace.getNamespace("dim", "http://www.dspace.org/xmlns/dspace/dim");
private static final Namespace namespaces[] = { DIM_NS };
private static XMLOutputter outputUgly = new XMLOutputter();
private static XMLOutputter outputPretty = new XMLOutputter(Format.getPrettyFormat());
private static SAXBuilder builder = new SAXBuilder();
public Namespace[] getNamespaces()
{
return namespaces;
}
/* No schema for DIM */
public String getSchemaLocation()
{
return DIM_NS.getURI() + " " + DIM_XSD;
}
public Element disseminateElement(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException
{
if (dso.getType() != Constants.ITEM)
throw new CrosswalkObjectNotSupported("DIMDisseminationCrosswalk can only crosswalk an Item.");
Item item = (Item)dso;
DCValue[] dc = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
Element dim = new Element("dim", DIM_NS);
for (int i = 0; i < dc.length; i++)
{
Element field = new Element("field", DIM_NS);
field.setAttribute("mdschema", dc[i].schema);
field.setAttribute("element", dc[i].element);
if (dc[i].qualifier != null)
field.setAttribute("qualifier", dc[i].qualifier);
if (dc[i].language != null)
field.setAttribute("lang", dc[i].language);
if (dc[i].value != null)
field.setText(dc[i].value);
dim.addContent(field);
}
return dim;
}
public List disseminateList(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException
{
List result = new ArrayList(1);
result.add(disseminateElement(dso));
return result;
}
/* Only interested in disseminating items at this time */
public boolean canDisseminate(DSpaceObject dso)
{
if (dso.getType() == Constants.ITEM)
return true;
else
return false;
}
public boolean preferList()
{
return false;
}
}

View File

@@ -0,0 +1,119 @@
/*
* DIMIngestionCrosswalk.java
*
* Version: $Revision: 1 $
*
* Date: $Date: 2007-07-30 12:26:50 -0500 (Mon, 30 Jul 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.content.crosswalk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Utils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* DIM ingestion crosswalk
* <p>
* Processes metadata encoded in DSpace Intermediate Format, without the overhead of XSLT processing.
*
* @author Alexey Maslov
* @version $Revision: 1 $
*/
public class DIMIngestionCrosswalk
implements IngestionCrosswalk
{
/** log4j category */
private static Logger log = Logger.getLogger(DIMIngestionCrosswalk.class);
private static Namespace DIM_NS = Namespace.getNamespace("http://www.dspace.org/xmlns/dspace/dim");
public void ingest(Context context, DSpaceObject dso, List metadata) throws CrosswalkException, IOException, SQLException, AuthorizeException {
List<Element> elements = metadata;
Element wrapper = new Element("wrap",elements.get(0).getNamespace());
wrapper.addContent(elements);
ingest(context,dso,wrapper);
}
public void ingest(Context context, DSpaceObject dso, Element root) throws CrosswalkException, IOException, SQLException, AuthorizeException {
if (dso.getType() != Constants.ITEM)
throw new CrosswalkObjectNotSupported("DIMIngestionCrosswalk can only crosswalk an Item.");
Item item = (Item)dso;
if (root == null) {
System.err.println("The element received by ingest was null");
return;
}
List<Element> metadata = root.getChildren("field",DIM_NS);
for (Element field : metadata) {
item.addMetadata(field.getAttributeValue("mdschema"), field.getAttributeValue("element"), field.getAttributeValue("qualifier"),
field.getAttributeValue("lang"), field.getText());
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* DIMIngestionCrosswalk.java
*
* Version: $Revision: 1 $
*
* Date: $Date: 2007-07-30 12:26:50 -0500 (Mon, 30 Jul 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.content.crosswalk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.MetadataValue;
import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Utils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* DIM ingestion crosswalk
* <p>
* Processes Dublic Core metadata encased in an oai_dc:dc wrapper
*
* @author Alexey Maslov
* @version $Revision: 1 $
*/
public class OAIDCIngestionCrosswalk
implements IngestionCrosswalk
{
/** log4j category */
private static Logger log = Logger.getLogger(OAIDCIngestionCrosswalk.class);
private static Namespace DC_NS = Namespace.getNamespace("http://www.dspace.org/xmlns/dspace/dim");
private static Namespace OAI_DC_NS = Namespace.getNamespace("http://www.openarchives.org/OAI/2.0/oai_dc/");
public void ingest(Context context, DSpaceObject dso, List metadata) throws CrosswalkException, IOException, SQLException, AuthorizeException {
List<Element> elements = metadata;
Element wrapper = new Element("wrap",elements.get(0).getNamespace());
wrapper.addContent(elements);
ingest(context,dso,wrapper);
}
public void ingest(Context context, DSpaceObject dso, Element root) throws CrosswalkException, IOException, SQLException, AuthorizeException {
if (dso.getType() != Constants.ITEM)
throw new CrosswalkObjectNotSupported("DIMIngestionCrosswalk can only crosswalk an Item.");
Item item = (Item)dso;
if (root == null) {
System.err.println("The element received by ingest was null");
return;
}
List<Element> metadata = root.getChildren();
for (Element element : metadata) {
item.addMetadata("dc", element.getName(), null, null, element.getText());
}
}
}

View File

@@ -0,0 +1,412 @@
/*
* OREDisseminationCrosswalk.java
*
* Version: $Revision: 2108 $
*
* Date: $Date: 2007-07-30 12:26:50 -0500 (Mon, 30 Jul 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.content.crosswalk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Utils;
//import org.dspace.core.Utils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* ORE dissemination crosswalk
* <p>
* Produces an Atom-encoded ORE aggregation of a DSpace item.
*
* @author Alexey Maslov
* @version $Revision: 1 $
*/
public class OREDisseminationCrosswalk
implements DisseminationCrosswalk
{
/** log4j category */
private static Logger log = Logger.getLogger(OREDisseminationCrosswalk.class);
/* Schema for Atom only available in Relax NG format */
public static final String ATOM_RNG = "http://tweety.lanl.gov/public/schemas/2008-06/atom-tron.sch";
/* Namespaces */
public static final Namespace ATOM_NS =
Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom");
private static final Namespace ORE_NS =
Namespace.getNamespace("ore", "http://www.openarchives.org/ore/terms/");
private static final Namespace ORE_ATOM =
Namespace.getNamespace("oreatom", "http://www.openarchives.org/ore/atom/");
private static final Namespace RDF_NS =
Namespace.getNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
private static final Namespace DCTERMS_NS =
Namespace.getNamespace("dcterms", "http://purl.org/dc/terms/");
private static final Namespace DS_NS =
Namespace.getNamespace("ds","http://www.dspace.org/objectModel/");
private static final Namespace namespaces[] = { ATOM_NS, ORE_NS, ORE_ATOM, RDF_NS, DCTERMS_NS, DS_NS };
public Namespace[] getNamespaces()
{
return namespaces;
}
/* There is (and currently can be) no XSD schema that validates Atom feeds, only RNG */
public String getSchemaLocation()
{
return ATOM_NS.getURI() + " " + ATOM_RNG;
}
/**
* Disseminate an Atom-encoded ORE ReM mapped from a DSpace Item
* @param item
* @return
* @throws CrosswalkException
* @throws IOException
* @throws SQLException
* @throws AuthorizeException
*/
private Element disseminateItem(Item item) throws CrosswalkException, IOException, SQLException, AuthorizeException
{
String oaiUrl = null;
String dsUrl = ConfigurationManager.getProperty("dspace.url");
String remSource = ConfigurationManager.getProperty("ore.authoritative.source");
if (remSource == null || remSource.equalsIgnoreCase("oai"))
oaiUrl = ConfigurationManager.getProperty("dspace.oai.url");
else if (remSource.equalsIgnoreCase("xmlui") || remSource.equalsIgnoreCase("manakin"))
oaiUrl = dsUrl;
if (oaiUrl == null)
throw new CrosswalkInternalException("Base uri for the ore generator has not been set. Check the ore.authoritative.source setting.");
String uriA = oaiUrl + "/metadata/handle/" + item.getHandle() + "/ore.xml";
// Top level atom feed element
Element aggregation = new Element("entry",ATOM_NS);
aggregation.addNamespaceDeclaration(ATOM_NS);
aggregation.addNamespaceDeclaration(ORE_NS);
aggregation.addNamespaceDeclaration(ORE_ATOM);
aggregation.addNamespaceDeclaration(DCTERMS_NS);
// Atom-entry specific info
Element atomId = new Element("id",ATOM_NS);
atomId.addContent(uriA);
aggregation.addContent(atomId);
Element aggLink;
DCValue[] uris = item.getMetadata(MetadataSchema.DC_SCHEMA,"identifier","uri",Item.ANY);
for (DCValue uri : uris) {
aggLink = new Element("link",ATOM_NS);
aggLink.setAttribute("rel", "alternate");
aggLink.setAttribute("href", uri.value);
aggregation.addContent(aggLink);
}
// Information about the resource map, as separate entity from the aggregation it describes
Element uriALink = new Element("link",ATOM_NS);
uriALink.setAttribute("rel", "http://www.openarchives.org/ore/terms/describes");
uriALink.setAttribute("href", uriA);
Element uriRLink = new Element("link",ATOM_NS);
uriRLink.setAttribute("rel","self");
uriRLink.setAttribute("href", uriA + "#atom");
uriRLink.setAttribute("type","application/atom+xml");
Element remPublished = new Element("published",ATOM_NS);
remPublished.addContent(Utils.formatISO8601Date(new Date()));
Element remUpdated = new Element("updated",ATOM_NS);
remUpdated.addContent(Utils.formatISO8601Date(new Date()));
Element remCreator = new Element("source",ATOM_NS);
Element remGenerator = new Element("generator",ATOM_NS);
remGenerator.addContent(ConfigurationManager.getProperty("dspace.name"));
remGenerator.setAttribute("uri", oaiUrl);
remCreator.addContent(remGenerator);
aggregation.addContent(uriALink);
aggregation.addContent(uriRLink);
aggregation.addContent(remPublished);
aggregation.addContent(remUpdated);
aggregation.addContent(remCreator);
// Information about the aggregation (item) itself
Element aggTitle = new Element("title",ATOM_NS);
DCValue[] titles = item.getMetadata(MetadataSchema.DC_SCHEMA, "title", null, Item.ANY);
if (titles != null && titles.length>0)
aggTitle.addContent(titles[0].value);
else
aggTitle.addContent("");
aggregation.addContent(aggTitle);
Element aggAuthor;
Element aggAuthorName;
DCValue[] authors = item.getMetadata(MetadataSchema.DC_SCHEMA,"contributor","author",Item.ANY);
for (DCValue author : authors) {
aggAuthor = new Element("author",ATOM_NS);
aggAuthorName = new Element("name",ATOM_NS);
aggAuthorName.addContent(author.value);
aggAuthor.addContent(aggAuthorName);
aggregation.addContent(aggAuthor);
}
Element oreCategory = new Element("category",ATOM_NS);
oreCategory.setAttribute("scheme", ORE_NS.getURI());
oreCategory.setAttribute("term", ORE_NS.getURI()+"Aggregation");
oreCategory.setAttribute("label","Aggregation");
Element updateCategory = new Element("category",ATOM_NS);
updateCategory.setAttribute("scheme", ORE_ATOM.getURI()+"modified");
updateCategory.setAttribute("term", Utils.formatISO8601Date(item.getLastModified()));
Element dsCategory = new Element("category",ATOM_NS);
dsCategory.setAttribute("scheme", DS_NS.getURI());
dsCategory.setAttribute("term", "DSpaceItem");
dsCategory.setAttribute("label", "DSpace Item");
aggregation.addContent(oreCategory);
aggregation.addContent(updateCategory);
aggregation.addContent(dsCategory);
// metadata section
Element arLink;
Element rdfDescription, rdfType, dcModified, dcDesc;
Element triples = new Element("triples", ORE_ATOM);
// metadata about the item
rdfDescription = new Element("Description", RDF_NS);
rdfDescription.setAttribute("about", uriA, RDF_NS);
rdfType = new Element("type", RDF_NS);
rdfType.setAttribute("resource", DS_NS.getURI()+"DSpaceItem", RDF_NS);
dcModified = new Element("modified", DCTERMS_NS);
dcModified.addContent(Utils.formatISO8601Date(item.getLastModified()));
rdfDescription.addContent(rdfType);
rdfDescription.addContent(dcModified);
triples.addContent(rdfDescription);
// Add a link and an oreatom metadata entry for each bitstream in the item
Bundle[] bundles = item.getBundles();
Bitstream[] bitstreams;
for (Bundle bundle : bundles)
{
// Omit the special "ORE" bitstream
if (bundle.getName().equals("ORE"))
continue;
bitstreams = bundle.getBitstreams();
for (Bitstream bs : bitstreams)
{
arLink = new Element("link",ATOM_NS);
arLink.setAttribute("rel", ORE_NS.getURI()+"aggregates");
arLink.setAttribute("href",dsUrl + "/bitstream/handle/" + item.getHandle() + "/" + URLencode(bs.getName()) + "?sequence=" + bs.getSequenceID());
arLink.setAttribute("title",bs.getName());
arLink.setAttribute("type",bs.getFormat().getMIMEType());
arLink.setAttribute("length",Long.toString(bs.getSize()));
aggregation.addContent(arLink);
// metadata about the bitstream
rdfDescription = new Element("Description", RDF_NS);
rdfDescription.setAttribute("about", dsUrl + "/bitstream/handle/" + item.getHandle() + "/" + URLencode(bs.getName()) + "?sequence=" + bs.getSequenceID(), RDF_NS);
rdfType = new Element("type", RDF_NS);
rdfType.setAttribute("resource", DS_NS.getURI()+"DSpaceBitstream", RDF_NS);
dcDesc = new Element("description", DCTERMS_NS);
dcDesc.addContent(bundle.getName());
rdfDescription.addContent(rdfType);
rdfDescription.addContent(dcDesc);
triples.addContent(rdfDescription);
}
}
aggregation.addContent(triples);
// Add a link to the OAI-PMH served metadata (oai_dc is always on)
/*
Element pmhMeta = new Element("entry",ATOM_NS);
pUri = new Element("id",ATOM_NS);
String oaiId = new String("oai:" + ConfigurationManager.getProperty("dspace.hostname") + ":" + item.getHandle());
pUri.addContent(oaiId + "#oai_dc");
pmhMeta.addContent(pUri);
Element pmhAuthor = new Element("author",ATOM_NS);
Element pmhAuthorName = new Element("name",ATOM_NS);
Element pmhAuthorUri = new Element("uri",ATOM_NS);
pmhAuthorName.addContent(ConfigurationManager.getProperty("dspace.name"));
pmhAuthorUri.addContent(oaiUrl);
pmhAuthor.addContent(pmhAuthorName);
pmhAuthor.addContent(pmhAuthorUri);
pmhMeta.addContent(pmhAuthor);
arUri = new Element("link",ATOM_NS);
arUri.setAttribute("rel","alternate");
arUri.setAttribute("href",oaiUrl + "/request?verb=GetRecord&amp;identifier=" + oaiId + "&amp;metadataprefix=oai_dc");
pmhMeta.addContent(arUri);
Element rdfDesc = new Element("Description",RDF_NS);
rdfDesc.setAttribute("about",oaiUrl + "/request?verb=GetRecord&amp;identifier=" + oaiId + "&amp;metadataprefix=oai_dc",RDF_NS);
Element dcTerms = new Element("dcterms",DCTERMS_NS);
dcTerms.setAttribute("resource","http://www.openarchives.org/OAI/2.0/oai_dc/",RDF_NS);
rdfDesc.addContent(dcTerms);
pmhMeta.addContent(rdfDesc);
arUpdated = new Element("updated",ATOM_NS);
arUpdated.addContent(Utils.formatISO8601Date(item.getLastModified()));
pmhMeta.addContent(arUpdated);
arTitle = new Element("title",ATOM_NS);
arTitle.addContent("");
pmhMeta.addContent(arTitle);
aggregation.addContent(pmhMeta);*/
return aggregation;
}
public Element disseminateElement(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException
{
switch(dso.getType()) {
case Constants.ITEM: return disseminateItem((Item)dso);
case Constants.COLLECTION: break;
case Constants.COMMUNITY: break;
default: throw new CrosswalkObjectNotSupported("ORE implementation unable to disseminate unknown DSpace object.");
}
return null;
}
/**
* Helper method to escape all chaacters that are not part of the canon set
* @param sourceString source unescaped string
*/
private String URLencode(String sourceString) {
Character lowalpha[] = {'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ,
'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' ,
's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z'};
Character upalpha[] = {'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' ,
'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,
'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'};
Character digit[] = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9'};
Character mark[] = {'-' , '_' , '.' , '!' , '~' , '*' , '\'' , '(' , ')'};
// reserved
//Character reserved[] = {';' , '/' , '?' , ':' , '@' , '&' , '=' , '+' , '$' , ',' ,'%', '#'};
Set<Character> URLcharsSet = new HashSet<Character>();
URLcharsSet.addAll(Arrays.asList(lowalpha));
URLcharsSet.addAll(Arrays.asList(upalpha));
URLcharsSet.addAll(Arrays.asList(digit));
URLcharsSet.addAll(Arrays.asList(mark));
//URLcharsSet.addAll(Arrays.asList(reserved));
String processedString = new String();
for (int i=0; i<sourceString.length(); i++) {
char ch = sourceString.charAt(i);
if (URLcharsSet.contains(ch)) {
processedString += ch;
}
else {
processedString += "%" + Integer.toHexString((int)ch);
}
}
return processedString;
}
public List disseminateList(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException
{
List result = new ArrayList(1);
result.add(disseminateElement(dso));
return result;
}
/* Only interested in disseminating items at this time */
public boolean canDisseminate(DSpaceObject dso)
{
if (dso.getType() == Constants.ITEM || dso.getType() == Constants.COLLECTION || dso.getType() == Constants.COMMUNITY)
return true;
else
return false;
}
public boolean preferList()
{
return false;
}
}

View File

@@ -0,0 +1,311 @@
/*
* OREIngestionCrosswalk.java
*
* Version: $Revision: 1 $
*
* Date: $Date: 2007-07-30 12:26:50 -0500 (Mon, 30 Jul 2007) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.content.crosswalk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
import org.dspace.content.Bundle;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Utils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jdom.xpath.XPath;
/**
* ORE ingestion crosswalk
* <p>
* Processes an Atom-encoded ORE resource map and attemps to interpret it as a DSpace item
*
* @author Alexey Maslov
* @version $Revision: 1 $
*/
public class OREIngestionCrosswalk
implements IngestionCrosswalk
{
/** log4j category */
private static Logger log = Logger.getLogger(OREDisseminationCrosswalk.class);
/* Namespaces */
public static final Namespace ATOM_NS =
Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom");
private static final Namespace ORE_ATOM =
Namespace.getNamespace("oreatom", "http://www.openarchives.org/ore/atom/");
private static final Namespace ORE_NS =
Namespace.getNamespace("ore", "http://www.openarchives.org/ore/terms/");
private static final Namespace RDF_NS =
Namespace.getNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
private static final Namespace DCTERMS_NS =
Namespace.getNamespace("dcterms", "http://purl.org/dc/terms/");
private static final Namespace DS_NS =
Namespace.getNamespace("ds","http://www.dspace.org/objectModel/");
public void ingest(Context context, DSpaceObject dso, List metadata) throws CrosswalkException, IOException, SQLException, AuthorizeException {
// If this list contains only the root already, just pass it on
List<Element> elements = metadata;
if (elements.size() == 1) {
ingest(context, dso, elements.get(0));
}
// Otherwise, wrap them up
else {
Element wrapper = new Element("wrap",elements.get(0).getNamespace());
wrapper.addContent(elements);
ingest(context,dso,wrapper);
}
}
public void ingest(Context context, DSpaceObject dso, Element root) throws CrosswalkException, IOException, SQLException, AuthorizeException {
Date timeStart = new Date();
if (dso.getType() != Constants.ITEM)
throw new CrosswalkObjectNotSupported("OREIngestionCrosswalk can only crosswalk an Item.");
Item item = (Item)dso;
if (root == null) {
System.err.println("The element received by ingest was null");
return;
}
Document doc = new Document();
doc.addContent(root.detach());
XPath xpathLinks;
List<Element> aggregatedResources;
String entryId;
try {
xpathLinks = XPath.newInstance("/atom:entry/atom:link[@rel=\"" + ORE_NS.getURI()+"aggregates" + "\"]");
xpathLinks.addNamespace(ATOM_NS);
aggregatedResources = xpathLinks.selectNodes(doc);
xpathLinks = XPath.newInstance("/atom:entry/atom:link[@rel='alternate']/@href");
xpathLinks.addNamespace(ATOM_NS);
entryId = ((Attribute)xpathLinks.selectSingleNode(doc)).getValue();
} catch (JDOMException e) {
throw new CrosswalkException("JDOM exception occured while ingesting the ORE");
}
// Next for each resource, create a bitstream
XPath xpathDesc;
NumberFormat nf=NumberFormat.getInstance();
nf.setGroupingUsed(false);
nf.setMinimumIntegerDigits(4);
int countInt=0;
String count;
for (Element resource : aggregatedResources)
{
countInt++;
count = nf.format((long)countInt);
String href = resource.getAttributeValue("href");
log.debug("ORE processing: " + href);
String bundleName;
Element desc = null;
try {
xpathDesc = XPath.newInstance("/atom:entry/oreatom:triples/rdf:Description[@rdf:about=\"" + this.URLencode(href) + "\"][1]");
xpathDesc.addNamespace(ATOM_NS);
xpathDesc.addNamespace(ORE_ATOM);
xpathDesc.addNamespace(RDF_NS);
desc = (Element)xpathDesc.selectSingleNode(doc);
} catch (JDOMException e) {
e.printStackTrace();
}
if (desc != null && desc.getChild("type", RDF_NS).getAttributeValue("resource", RDF_NS).equals(DS_NS.getURI() + "DSpaceBitstream"))
{
bundleName = desc.getChildText("description", DCTERMS_NS);
log.debug("Setting bundle name to: " + bundleName);
}
else {
log.info("Could not obtain bundle name; using 'ORIGINAL'");
bundleName = "ORIGINAL";
}
// Bundle names are not unique, so we just pick the first one if there's more than one.
Bundle[] targetBundles = item.getBundles(bundleName);
Bundle targetBundle;
// if null, create the new bundle and add it in
if (targetBundles.length == 0) {
targetBundle = item.createBundle(bundleName);
item.addBundle(targetBundle);
}
else {
targetBundle = targetBundles[0];
}
URL ARurl = null;
InputStream in = null;
if (href != null) {
try {
// Make sure the url string escapes all the oddball characters
String processedURL = URLencode(href);
// Generate a requeset for the aggregated resource
ARurl = new URL(processedURL);
in = ARurl.openStream();
}
catch(FileNotFoundException fe) {
log.error("The provided URI failed to return a resource: " + href);
}
catch(ConnectException fe) {
log.error("The provided URI was invalid: " + href);
}
}
else {
throw new CrosswalkException("Entry did not contain link to resource: " + entryId);
}
// ingest and update
if (in != null) {
Bitstream newBitstream = targetBundle.createBitstream(in);
String bsName = resource.getAttributeValue("title");
newBitstream.setName(bsName);
// Identify the format
String mimeString = resource.getAttributeValue("type");
BitstreamFormat bsFormat = BitstreamFormat.findByMIMEType(context, mimeString);
if (bsFormat == null) {
bsFormat = FormatIdentifier.guessFormat(context, newBitstream);
}
newBitstream.setFormat(bsFormat);
newBitstream.update();
targetBundle.addBitstream(newBitstream);
targetBundle.update();
}
else {
throw new CrosswalkException("Could not retrieve bitstream: " + entryId);
}
}
log.info("OREIngest for Item "+ item.getID() + " took: " + (new Date().getTime() - timeStart.getTime()) + "ms.");
}
/**
* Helper method to escape all chaacters that are not part of the canon set
* @param sourceString source unescaped string
*/
private String URLencode(String sourceString) {
Character lowalpha[] = {'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' ,
'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' ,
's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z'};
Character upalpha[] = {'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' ,
'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,
'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'};
Character digit[] = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9'};
Character mark[] = {'-' , '_' , '.' , '!' , '~' , '*' , '\'' , '(' , ')'};
// reserved
Character reserved[] = {';' , '/' , '?' , ':' , '@' , '&' , '=' , '+' , '$' , ',' ,'%', '#'};
Set<Character> URLcharsSet = new HashSet<Character>();
URLcharsSet.addAll(Arrays.asList(lowalpha));
URLcharsSet.addAll(Arrays.asList(upalpha));
URLcharsSet.addAll(Arrays.asList(digit));
URLcharsSet.addAll(Arrays.asList(mark));
URLcharsSet.addAll(Arrays.asList(reserved));
String processedString = new String();
for (int i=0; i<sourceString.length(); i++) {
char ch = sourceString.charAt(i);
if (URLcharsSet.contains(ch)) {
processedString += ch;
}
else {
processedString += "%" + Integer.toHexString((int)ch);
}
}
return processedString;
}
}

View File

@@ -0,0 +1,144 @@
/*
* HarvestConsumer.java
*
* Version: $Revision: 3705 $
*
* Date: $Date: 2009-04-11 12:02:24 -0500 (Sat, 11 Apr 2009) $
*
* Copyright (c) 2002-2007, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.harvest;
import org.apache.log4j.Logger;
import org.dspace.content.Item;
import org.dspace.core.*;
import org.dspace.event.Consumer;
import org.dspace.event.Event;
import javax.mail.MessagingException;
import java.util.Date;
/**
* Class for handling cleanup of harvest settings for collections and items
*
*
* @version $Revision: 3705 $
*
* @author Stuart Lewis
* @author Alexey Maslov
*/
public class HarvestConsumer implements Consumer
{
/** log4j logger */
private static Logger log = Logger.getLogger(HarvestConsumer.class);
/**
* Initalise the consumer
*
* @throws Exception
*/
public void initialize()
throws Exception
{
}
/**
* Consume the event
*
* @param context
* @param event
* @throws Exception
*/
public void consume(Context context, Event event)
throws Exception
{
int st = event.getSubjectType();
int et = event.getEventType();
int id = event.getSubjectID();
switch (st)
{
case Constants.ITEM:
if (et == Event.DELETE)
{
HarvestedItem hi = HarvestedItem.find(context, id);
if (hi != null) {
log.debug("Deleted item '" + id + "', also deleting associated harvested_item '" + hi.getOaiID() + "'.");
hi.delete();
hi.update();
}
else
log.debug("Deleted item '" + id + "' and the associated harvested_item.");
}
break;
case Constants.COLLECTION:
if (et == Event.DELETE)
{
HarvestedCollection hc = HarvestedCollection.find(context, id);
if (hc != null) {
log.debug("Deleted collection '" + id + "', also deleting associated harvested_collection '" + hc.getOaiSource() + ":" + hc.getOaiSetId() + "'.");
hc.delete();
hc.update();
}
else
log.debug("Deleted collection '" + id + "' and the associated harvested_collection.");
}
default:
log.warn("consume() got unrecognized event: " + event.toString());
}
}
/**
* Handle the end of the event
*
* @param ctx
* @throws Exception
*/
public void end(Context ctx)
throws Exception
{
}
/**
* Finish the event
*
* @param ctx
*/
public void finish(Context ctx)
{
}
}

View File

@@ -0,0 +1,434 @@
package org.dspace.harvest;
/*
* HarvestedCollection.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2008/01/01 04:11:09 $
*
* Copyright (c) 2002-2007, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.
*/
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.storage.rdbms.TableRow;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* @author Alexey Maslov
*/
public class HarvestedCollection
{
private Context context;
private TableRow harvestRow;
boolean modified;
public static final int TYPE_NONE = 0;
public static final int TYPE_DMD = 1;
public static final int TYPE_DMDREF = 2;
public static final int TYPE_FULL = 3;
public static final int STATUS_READY = 0;
public static final int STATUS_BUSY = 1;
public static final int STATUS_QUEUED = 2;
public static final int STATUS_OAI_ERROR = 3;
public static final int STATUS_UNKNOWN_ERROR = -1;
/*
* collection_id | integer | not null
harvest_type | integer |
oai_source | text |
oai_set_id | text |
harvest_message | text |
metadata_config_id | text |
harvest_status | integer |
harvest_start_time | timestamp with time zone |
*/
// TODO: make sure this guy knows to lock people out if the status is not zero.
// i.e. someone editing a collection's setting from the admin menu should have
// to stop an ongoing harvest before they can edit the settings.
HarvestedCollection(Context c, TableRow row)
{
context = c;
harvestRow = row;
modified = false;
}
public static void exists(Context c) throws SQLException {
DatabaseManager.queryTable(c, "harvested_collection", "SELECT COUNT(*) FROM harvested_collection");
}
/**
* Find the harvest settings corresponding to this collection
* @return a HarvestInstance object corresponding to this collection's settings, null if not found.
*/
public static HarvestedCollection find(Context c, int collectionId) throws SQLException
{
TableRow row = DatabaseManager.findByUnique(c, "harvested_collection", "collection_id", collectionId);
if (row == null) {
return null;
}
return new HarvestedCollection(c, row);
}
/**
* Create a new harvest instance row for a specified collection.
* @return a new HarvestInstance object
*/
public static HarvestedCollection create(Context c, int collectionId) throws SQLException {
TableRow row = DatabaseManager.create(c, "harvested_collection");
row.setColumn("collection_id", collectionId);
row.setColumn("harvest_type", 0);
DatabaseManager.update(c, row);
return new HarvestedCollection(c, row);
}
/** Returns whether the specified collection is harvestable, i.e. whether its harvesting
* options are set up correctly. This is distinct from "ready", since this collection may
* be in process of being harvested.
*/
public static boolean isHarvestable(Context c, int collectionId) throws SQLException
{
HarvestedCollection hc = HarvestedCollection.find(c, collectionId);
if (hc != null && hc.getHarvestType() > 0 && hc.getOaiSource() != null && hc.getOaiSetId() != null &&
hc.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) {
return true;
}
return false;
}
/** Returns whether this harvest instance is actually harvestable, i.e. whether its settings
* options are set up correctly. This is distinct from "ready", since this collection may
* be in process of being harvested.
*/
public boolean isHarvestable() throws SQLException
{
if (this.getHarvestType() > 0 && this.getOaiSource() != null && this.getOaiSetId() != null &&
this.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) {
return true;
}
return false;
}
/** Returns whether the specified collection is ready for immediate harvest.
*/
public static boolean isReady(Context c, int collectionId) throws SQLException
{
HarvestedCollection hc = HarvestedCollection.find(c, collectionId);
return hc.isReady();
}
public boolean isReady() throws SQLException
{
if (this.isHarvestable() && (this.getHarvestStatus() == HarvestedCollection.STATUS_READY || this.getHarvestStatus() == HarvestedCollection.STATUS_OAI_ERROR))
return true;
return false;
}
/** Find all collections that are set up for harvesting
*
* return: list of collection id's
* @throws SQLException
*/
public static List<Integer> findAll(Context c) throws SQLException
{
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection");
List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext())
{
TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id"));
}
return collectionIds;
}
/** Find all collections that are ready for harvesting
*
* return: list of collection id's
* @throws SQLException
*/
public static List<Integer> findReady(Context c) throws SQLException
{
int harvestInterval = ConfigurationManager.getIntProperty("harvester.harvestFrequency");
if (harvestInterval == 0) harvestInterval = 720;
int expirationInterval = ConfigurationManager.getIntProperty("harvester.threadTimeout");
if (expirationInterval == 0) expirationInterval = 24;
Date startTime;
Date expirationTime;
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.MINUTE, -1 * harvestInterval);
startTime = calendar.getTime();
calendar.setTime(startTime);
calendar.add(Calendar.HOUR, -2 * expirationInterval);
expirationTime = calendar.getTime();
/* Select all collections whose last_harvest is before our start time, whose harvest_type *is not* 0 and whose status *is* 0 (available) or 3 (OAI Error). */
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection WHERE (last_harvested < ? or last_harvested is null) and harvest_type > ? and (harvest_status = ? or harvest_status = ? or (harvest_status=? and harvest_start_time < ?)) ORDER BY last_harvested",
new java.sql.Timestamp(startTime.getTime()), 0, HarvestedCollection.STATUS_READY, HarvestedCollection.STATUS_OAI_ERROR, HarvestedCollection.STATUS_BUSY, new java.sql.Timestamp(expirationTime.getTime()));
List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext())
{
TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id"));
}
return collectionIds;
}
/**
* Find all collections with the specified status flag
* @param c
* @param status, see HarvestInstance.STATUS_...
* @return
* @throws SQLException
*/
public static List<Integer> findByStatus(Context c, int status) throws SQLException {
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection WHERE harvest_status = ?", status);
List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext())
{
TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id"));
}
return collectionIds;
}
/** Find the collection that was harvested the longest time ago.
* @throws SQLException
*/
public static Integer findOldestHarvest (Context c) throws SQLException {
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested asc limit 1", 0, 0);
TableRow row = tri.next();
if (row != null)
return row.getIntColumn("collection_id");
else
return -1;
}
/** Find the collection that was harvested most recently.
* @throws SQLException
*/
public static Integer findNewestHarvest (Context c) throws SQLException {
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested desc limit 1", 0, 0);
TableRow row = tri.next();
if (row != null)
return row.getIntColumn("collection_id");
else
return -1;
}
/**
* A function to set all harvesting-related parameters at once
*/
public void setHarvestParams(int type, String oaiSource, String oaiSetId, String mdConfigId) {
setHarvestType(type);
setOaiSource(oaiSource);
setOaiSetId(oaiSetId);
setHarvestMetadataConfig(mdConfigId);
}
/* Setters for the appropriate harverting-related columns */
public void setHarvestType(int type) {
harvestRow.setColumn("harvest_type",type);
modified = true;
}
/**
* Sets the current status of the collection.
*
* @param status a HarvestInstance.STATUS_... constant
*/
public void setHarvestStatus(int status) {
harvestRow.setColumn("harvest_status",status);
modified = true;
}
public void setOaiSource(String oaiSource) {
if (oaiSource == null || oaiSource.length() == 0) {
harvestRow.setColumnNull("oai_source");
}
else {
harvestRow.setColumn("oai_source",oaiSource);
}
modified = true;
}
public void setOaiSetId(String oaiSetId) {
if (oaiSetId == null || oaiSetId.length() == 0) {
harvestRow.setColumnNull("oai_set_id");
}
else {
harvestRow.setColumn("oai_set_id",oaiSetId);
}
modified = true;
}
public void setHarvestMetadataConfig(String mdConfigId) {
if (mdConfigId == null || mdConfigId.length() == 0) {
harvestRow.setColumnNull("metadata_config_id");
}
else {
harvestRow.setColumn("metadata_config_id",mdConfigId);
}
modified = true;
}
public void setHarvestResult(Date date, String message) {
if (date == null) {
harvestRow.setColumnNull("last_harvested");
} else {
harvestRow.setColumn("last_harvested", date);
}
if (message == null || message.length() == 0) {
harvestRow.setColumnNull("harvest_message");
} else {
harvestRow.setColumn("harvest_message", message);
}
modified = true;
}
public void setHarvestMessage(String message) {
if (message == null || message.length() == 0) {
harvestRow.setColumnNull("harvest_message");
} else {
harvestRow.setColumn("harvest_message", message);
}
modified = true;
}
public void setHarvestStartTime(Date date) {
if (date == null) {
harvestRow.setColumnNull("harvest_start_time");
} else {
harvestRow.setColumn("harvest_start_time", date);
}
modified = true;
}
/* Getting for the appropriate harverting-related columns */
public int getCollectionId() {
return harvestRow.getIntColumn("collection_id");
}
public int getHarvestType() {
return harvestRow.getIntColumn("harvest_type");
}
public int getHarvestStatus() {
return harvestRow.getIntColumn("harvest_status");
}
public String getOaiSource() {
return harvestRow.getStringColumn("oai_source");
}
public String getOaiSetId() {
return harvestRow.getStringColumn("oai_set_id");
}
public String getHarvestMetadataConfig() {
return harvestRow.getStringColumn("metadata_config_id");
}
public String getHarvestMessage() {
return harvestRow.getStringColumn("harvest_message");
}
public Date getHarvestDate() {
return harvestRow.getDateColumn("last_harvested");
}
public Date getHarvestStartTime() {
return harvestRow.getDateColumn("harvest_start_time");
}
public void delete() throws SQLException {
DatabaseManager.delete(context, harvestRow);
}
public void update() throws SQLException, IOException, AuthorizeException
{
DatabaseManager.update(context, harvestRow);
}
}

View File

@@ -0,0 +1,203 @@
/*
* Item.java
*
* Version: $Revision: 4196 $
*
* Date: $Date: 2009-08-06 08:29:46 -0500 (Thu, 06 Aug 2009) $
*
* 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 DSpace Foundation nor the names of its
* 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.harvest;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
/**
* @author Alexey Maslov
*/
public class HarvestedItem
{
private Context context;
private TableRow harvestRow;
boolean modified;
HarvestedItem(Context c, TableRow row)
{
context = c;
harvestRow = row;
modified = false;
}
public static void exists(Context c) throws SQLException {
DatabaseManager.queryTable(c, "harvested_item", "SELECT COUNT(*) FROM harvested_item");
}
/**
* Find the harvest parameters corresponding to the specified DSpace item
* @return a HarvestedItem object corresponding to this item, null if not found.
*/
public static HarvestedItem find(Context c, int item_id) throws SQLException
{
TableRow row = DatabaseManager.findByUnique(c, "harvested_item", "item_id", item_id);
if (row == null) {
return null;
}
return new HarvestedItem(c, row);
}
/*
* select foo.item_id from (select item.item_id, item.owning_collection from item join item2bundle on item.item_id=item2bundle.item_id where item2bundle.bundle_id=22) as foo join collection on foo.owning_collection=collection.collection_id where collection.collection_id=5;
*/
/**
* Retrieve a DSpace Item that corresponds to this particular combination of owning collection and OAI ID.
* @param context
* @param itemOaiID the string used by the OAI-PMH provider to identify the item
* @param collectionID id of the local collection that the item should be found in
* @return DSpace Item or null if no item was found
*/
public static Item getItemByOAIId(Context context, String itemOaiID, int collectionID) throws SQLException
{
/*
* FYI: This method has to be scoped to a collection. Otherwise, we could have collisions as more
* than one collection might be importing the same item. That is OAI_ID's might be unique to the
* provider but not to the harvester.
*/
Item resolvedItem = null;
TableRowIterator tri = null;
final String selectItemFromOaiId = "SELECT dsi.item_id FROM " +
"(SELECT item.item_id, item.owning_collection FROM item JOIN harvested_item ON item.item_id=harvested_item.item_id WHERE harvested_item.oai_id=?) " +
"AS dsi JOIN collection ON dsi.owning_collection=collection.collection_id WHERE collection.collection_id=?";
try
{
tri = DatabaseManager.query(context, selectItemFromOaiId, itemOaiID, collectionID);
if (tri.hasNext())
{
TableRow row = tri.next();
int itemID = row.getIntColumn("item_id");
resolvedItem = Item.find(context, itemID);
}
else {
return null;
}
}
finally {
if (tri != null)
tri.close();
}
return resolvedItem;
}
/**
* Create a new harvested item row for a specified item id.
* @return a new HarvestedItem object
*/
public static HarvestedItem create(Context c, int itemId, String itemOAIid) throws SQLException {
TableRow row = DatabaseManager.create(c, "harvested_item");
row.setColumn("item_id", itemId);
row.setColumn("oai_id", itemOAIid);
DatabaseManager.update(c, row);
return new HarvestedItem(c, row);
}
public String getItemID()
{
String oai_id = harvestRow.getStringColumn("item_id");
return oai_id;
}
/**
* Get the oai_id associated with this item
*/
public String getOaiID()
{
String oai_id = harvestRow.getStringColumn("oai_id");
return oai_id;
}
/**
* Set the oai_id associated with this item
*/
public void setOaiID(String itemOaiID)
{
harvestRow.setColumn("oai_id",itemOaiID);
return;
}
public void setHarvestDate(Date date) {
if (date == null) {
date = new Date();
}
harvestRow.setColumn("last_harvested", date);
modified = true;
}
public Date getHarvestDate() {
return harvestRow.getDateColumn("last_harvested");
}
public void delete() throws SQLException {
DatabaseManager.delete(context, harvestRow);
}
public void update() throws SQLException, IOException, AuthorizeException {
DatabaseManager.update(context, harvestRow);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,7 @@ import org.dspace.content.Community;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.FormatIdentifier; import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
@@ -203,7 +204,11 @@ public class EditCommunitiesServlet extends DSpaceServlet
break; break;
case START_EDIT_COLLECTION: case START_EDIT_COLLECTION:
HarvestedCollection hc = HarvestedCollection.find(context, UIUtil.
getIntParameter(request, "collection_id"));
request.setAttribute("harvestInstance", hc);
// Display the relevant "edit collection" page // Display the relevant "edit collection" page
JSPManager.showJSP(request, response, "/tools/edit-collection.jsp"); JSPManager.showJSP(request, response, "/tools/edit-collection.jsp");
@@ -551,6 +556,40 @@ public class EditCommunitiesServlet extends DSpaceServlet
collection.setMetadata("side_bar_text", side); collection.setMetadata("side_bar_text", side);
collection.setMetadata("license", license); collection.setMetadata("license", license);
collection.setMetadata("provenance_description", provenance); collection.setMetadata("provenance_description", provenance);
// Set the harvesting settings
HarvestedCollection hc = HarvestedCollection.find(context, collection.getID());
String contentSource = request.getParameter("source");
// First, if this is not a harvested collection (anymore), set the harvest type to 0; wipe harvest settings
if (contentSource.equals("source_normal"))
{
if (hc != null)
hc.delete();
}
else
{
// create a new harvest instance if all the settings check out
if (hc == null) {
hc = HarvestedCollection.create(context, collection.getID());
}
String oaiProvider = request.getParameter("oai_provider");
String oaiSetId = request.getParameter("oai_setid");
String metadataKey = request.getParameter("metadata_format");
String harvestType = request.getParameter("harvest_level");
hc.setHarvestParams(Integer.parseInt(harvestType), oaiProvider, oaiSetId, metadataKey);
hc.setHarvestStatus(HarvestedCollection.STATUS_READY);
hc.update();
}
// Which button was pressed? // Which button was pressed?
String button = UIUtil.getSubmitButton(request, "submit"); String button = UIUtil.getSubmitButton(request, "submit");

View File

@@ -56,7 +56,10 @@
<%@ page import="org.dspace.content.Item" %> <%@ page import="org.dspace.content.Item" %>
<%@ page import="org.dspace.core.Utils" %> <%@ page import="org.dspace.core.Utils" %>
<%@ page import="org.dspace.eperson.Group" %> <%@ page import="org.dspace.eperson.Group" %>
<%@ page import="org.dspace.harvest.HarvestedCollection" %>
<%@ page import="org.dspace.core.ConfigurationManager" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %>
<%@ page import="java.util.Enumeration" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
@@ -71,6 +74,8 @@
Boolean admin = (Boolean)request.getAttribute("is.admin"); Boolean admin = (Boolean)request.getAttribute("is.admin");
boolean isAdmin = (admin == null ? false : admin.booleanValue()); boolean isAdmin = (admin == null ? false : admin.booleanValue());
HarvestedCollection hc = (HarvestedCollection) request.getAttribute("harvestInstance");
String name = ""; String name = "";
String shortDesc = ""; String shortDesc = "";
String intro = ""; String intro = "";
@@ -78,7 +83,14 @@
String side = ""; String side = "";
String license = ""; String license = "";
String provenance = ""; String provenance = "";
String oaiProviderValue= "";
String oaiSetIdValue= "";
String metadataFormatValue= "";
String lastHarvestMsg= "";
int harvestLevelValue=0;
int harvestStatus= 0;
Group[] wfGroups = new Group[3]; Group[] wfGroups = new Group[3];
wfGroups[0] = null; wfGroups[0] = null;
wfGroups[1] = null; wfGroups[1] = null;
@@ -115,6 +127,17 @@
template = collection.getTemplateItem(); template = collection.getTemplateItem();
logo = collection.getLogo(); logo = collection.getLogo();
/* Harvesting stuff */
if (hc != null) {
oaiProviderValue = hc.getOaiSource();
oaiSetIdValue = hc.getOaiSetId();
metadataFormatValue = hc.getHarvestMetadataConfig();
harvestLevelValue = hc.getHarvestType();
lastHarvestMsg= hc.getHarvestMessage();
harvestStatus = hc.getHarvestStatus();
}
} }
%> %>
@@ -314,6 +337,105 @@
</tr> </tr>
<% } %> <% } %>
<% if(admin_button ) { %>
<%-- ===========================================================
Harvesting Settings
=========================================================== --%>
<tr><td>&nbsp;</td></tr>
<tr><td colspan="2"><center><h3>Harvesting Settings</h3></center></td></tr>
<%--
oaiProviderValue = hc.getOaiSource();
oaiSetIdValue = hc.getOaiSetId();
metadataFormatValue = hc.getHarvestMetadataConfig();
harvestLevelValue = hc.getHarvestType();
String lastHarvestMsg= hc.getHarvestMessage();
int harvestStatus = hc.getHarvestStatus();
if (lastHarvestMsg == null)
lastHarvestMsg = "none";
--%>
<tr>
<td class="submitFormLabel">Content Source</td>
<td>
<input type="radio" value="source_normal" <% if (harvestLevelValue == 0) { %> checked="checked" <% } %> name="source">This is a standard DSpace collection</input><br/>
<input type="radio" value="source_harvested" <% if (harvestLevelValue > 0) { %> checked="checked" <% } %> name="source">This collection harvests its content from an external source</input><br/>
</td>
</tr>
<tr>
<td class="submitFormLabel">OAI Provider</td>
<td><input type="text" name="oai_provider" value="<%= oaiProviderValue %>" size="50" /></td>
</tr>
<tr>
<td class="submitFormLabel">OAI Set Id</td>
<td><input type="text" name="oai_setid" value="<%= oaiSetIdValue %>" size="50" /></td>
</tr>
<tr>
<td class="submitFormLabel">Metadata Format</td>
<td>
<select name="metadata_format" >
<%
// Add an entry for each instance of ingestion crosswalks configured for harvesting
String metaString = "harvester.oai.metadataformats.";
Enumeration pe = ConfigurationManager.propertyNames();
while (pe.hasMoreElements())
{
String key = (String)pe.nextElement();
if (key.startsWith(metaString)) {
String metadataString = ConfigurationManager.getProperty(key);
String metadataKey = key.substring(metaString.length());
String displayName;
if (metadataString.indexOf(',') != -1)
displayName = metadataString.substring(metadataString.indexOf(',') + 1);
else
displayName = metadataKey + "(" + metadataString + ")";
%>
<option value="<%= metadataKey %>"
<% if(metadataKey.equalsIgnoreCase(metadataFormatValue)) { %>
selected="selected" <% } %> >
<%= displayName %></option>
<%
}
}
%>
</select>
</td>
</tr>
<tr>
<td class="submitFormLabel">Content being Harvested</td>
<td>
<input type="radio" value="1" <% if (harvestLevelValue != 2 && harvestLevelValue != 3) { %> checked="checked" <% } %> name="harvest_level">Harvest metadata only.</input><br/>
<input type="radio" value="2" <% if (harvestLevelValue == 2) { %> checked="checked" <% } %> name="harvest_level">Harvest metadata and references to bitstreams (requires ORE support).</input><br/>
<input type="radio" value="3" <% if (harvestLevelValue == 3) { %> checked="checked" <% } %> name="harvest_level">Harvest metadata and bitstreams (requires ORE support).</input><br/>
</td>
</tr>
<tr>
<td class="submitFormLabel">Last Harvest Result</td>
<td><%= lastHarvestMsg %></td>
</tr>
<!--
<tr>
<td class="submitFormLabel">Current Status</td>
<td> </td>
</tr>
-->
<% } %>
</table> </table>
<p>&nbsp;</p> <p>&nbsp;</p>

View File

@@ -44,6 +44,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceException;
@@ -69,6 +70,9 @@ import org.dspace.app.xmlui.wing.element.Table;
import org.dspace.app.xmlui.wing.element.TextArea; import org.dspace.app.xmlui.wing.element.TextArea;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -152,6 +156,27 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
private static final Message T_activity_anonymous = message("xmlui.administrative.ControlPanel.activity_anonymous"); private static final Message T_activity_anonymous = message("xmlui.administrative.ControlPanel.activity_anonymous");
private static final Message T_activity_none = message("xmlui.administrative.ControlPanel.activity_none"); private static final Message T_activity_none = message("xmlui.administrative.ControlPanel.activity_none");
private static final Message T_select_panel = message("xmlui.administrative.ControlPanel.select_panel"); private static final Message T_select_panel = message("xmlui.administrative.ControlPanel.select_panel");
private static final Message T_option_harvest = message("xmlui.administrative.ControlPanel.option_harvest");
private static final Message T_harvest_scheduler_head = message("xmlui.administrative.ControlPanel.harvest_scheduler_head");
private static final Message T_harvest_label_status = message("xmlui.administrative.ControlPanel.harvest_label_status");
private static final Message T_harvest_label_actions = message("xmlui.administrative.ControlPanel.harvest_label_actions");
private static final Message T_harvest_submit_start = message("xmlui.administrative.ControlPanel.harvest_submit_start");
private static final Message T_harvest_submit_reset = message("xmlui.administrative.ControlPanel.harvest_submit_reset");
private static final Message T_harvest_submit_resume = message("xmlui.administrative.ControlPanel.harvest_submit_resume");
private static final Message T_harvest_submit_pause = message("xmlui.administrative.ControlPanel.harvest_submit_pause");
private static final Message T_harvest_submit_stop = message("xmlui.administrative.ControlPanel.harvest_submit_stop");
private static final Message T_harvest_label_collections = message("xmlui.administrative.ControlPanel.harvest_label_collections");
private static final Message T_harvest_label_active = message("xmlui.administrative.ControlPanel.harvest_label_active");
private static final Message T_harvest_label_queued = message("xmlui.administrative.ControlPanel.harvest_label_queued");
private static final Message T_harvest_label_oai_errors = message("xmlui.administrative.ControlPanel.harvest_label_oai_errors");
private static final Message T_harvest_label_internal_errors = message("xmlui.administrative.ControlPanel.harvest_label_internal_errors");
private static final Message T_harvest_head_generator_settings = message("xmlui.administrative.ControlPanel.harvest_head_generator_settings");
private static final Message T_harvest_label_oai_url = message("xmlui.administrative.ControlPanel.harvest_label_oai_url");
private static final Message T_harvest_label_oai_source = message("xmlui.administrative.ControlPanel.harvest_label_oai_source");
private static final Message T_harvest_head_harvester_settings = message("xmlui.administrative.ControlPanel.harvest_head_harvester_settings");
/** /**
* The service manager allows us to access the continuation's * The service manager allows us to access the continuation's
* manager, it is obtained from the servicable API * manager, it is obtained from the servicable API
@@ -159,9 +184,9 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
private ServiceManager serviceManager; private ServiceManager serviceManager;
/** /**
* The four states that this page can be in. * The five states that this page can be in.
*/ */
private enum OPTIONS {java, dspace, alerts, activity}; private enum OPTIONS {java, dspace, alerts, activity, harvest};
/** /**
* From the servicable api, give us a service manager. * From the servicable api, give us a service manager.
@@ -196,6 +221,8 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
option = OPTIONS.alerts; option = OPTIONS.alerts;
if (request.getParameter("activity") != null) if (request.getParameter("activity") != null)
option = OPTIONS.activity; option = OPTIONS.activity;
if (request.getParameter("harvest") != null)
option = OPTIONS.harvest;
Division div = body.addInteractiveDivision("control-panel", contextPath+"/admin/panel", Division.METHOD_POST, "primary administrative"); Division div = body.addInteractiveDivision("control-panel", contextPath+"/admin/panel", Division.METHOD_POST, "primary administrative");
div.setHead(T_head); div.setHead(T_head);
@@ -219,6 +246,11 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
else else
options.addItemXref("?alerts",T_option_alerts); options.addItemXref("?alerts",T_option_alerts);
if (option == OPTIONS.harvest)
options.addItem().addHighlight("bold").addXref("?harvest",T_option_harvest);
else
options.addItemXref("?harvest",T_option_harvest);
String userSortTarget = "?activity"; String userSortTarget = "?activity";
if (request.getParameter("sortBy") != null) if (request.getParameter("sortBy") != null)
userSortTarget += "&sortBy="+request.getParameter("sortBy"); userSortTarget += "&sortBy="+request.getParameter("sortBy");
@@ -237,6 +269,8 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
addAlerts(div); addAlerts(div);
else if (option == OPTIONS.activity) else if (option == OPTIONS.activity)
addActivity(div); addActivity(div);
else if (option == OPTIONS.harvest)
addHarvest(div);
else else
{ {
div.addPara(T_select_panel); div.addPara(T_select_panel);
@@ -622,4 +656,101 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
} }
} }
/**
* Add a section that allows management of the OAI harvester.
* @throws SQLException
*/
private void addHarvest(Division div) throws WingException, SQLException
{
// Remember we're in the harvest section
div.addHidden("harvest").setValue("true");
List harvesterControls = div.addList("oai-harvester-controls",List.TYPE_FORM);
harvesterControls.setHead(T_harvest_scheduler_head);
harvesterControls.addLabel(T_harvest_label_status);
Item status = harvesterControls.addItem();
status.addContent(HarvestScheduler.getStatus());
status.addXref(contextPath + "/admin/panel?harvest", "(refresh)");
harvesterControls.addLabel(T_harvest_label_actions);
Item actionsItem = harvesterControls.addItem();
if (HarvestScheduler.status == HarvestScheduler.HARVESTER_STATUS_STOPPED) {
actionsItem.addButton("submit_harvest_start").setValue(T_harvest_submit_start);
actionsItem.addButton("submit_harvest_reset").setValue(T_harvest_submit_reset);
}
if (HarvestScheduler.status == HarvestScheduler.HARVESTER_STATUS_PAUSED)
actionsItem.addButton("submit_harvest_resume").setValue(T_harvest_submit_resume);
if (HarvestScheduler.status == HarvestScheduler.HARVESTER_STATUS_RUNNING ||
HarvestScheduler.status == HarvestScheduler.HARVESTER_STATUS_SLEEPING)
actionsItem.addButton("submit_harvest_pause").setValue(T_harvest_submit_pause);
if (HarvestScheduler.status != HarvestScheduler.HARVESTER_STATUS_STOPPED)
actionsItem.addButton("submit_harvest_stop").setValue(T_harvest_submit_stop);
// Can be retrieved via "{context-path}/admin/collection?collectionID={id}"
String baseURL = contextPath + "/admin/collection?collectionID=";
harvesterControls.addLabel(T_harvest_label_collections);
Item allCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> allCollections = HarvestedCollection.findAll(context);
for (Integer oaiCollection : allCollections) {
allCollectionsItem.addXref(baseURL + oaiCollection, oaiCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_active);
Item busyCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> busyCollections = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_BUSY);
for (Integer busyCollection : busyCollections) {
busyCollectionsItem.addXref(baseURL + busyCollection, busyCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_queued);
Item queuedCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> queuedCollections = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_QUEUED);
for (Integer queuedCollection : queuedCollections) {
queuedCollectionsItem.addXref(baseURL + queuedCollection, queuedCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_oai_errors);
Item oaiErrorsItem = harvesterControls.addItem();
java.util.List<Integer> oaiErrors = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_OAI_ERROR);
for (Integer oaiError : oaiErrors) {
oaiErrorsItem.addXref(baseURL + oaiError, oaiError.toString());
}
harvesterControls.addLabel(T_harvest_label_internal_errors);
Item internalErrorsItem = harvesterControls.addItem();
java.util.List<Integer> internalErrors = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_UNKNOWN_ERROR);
for (Integer internalError : internalErrors) {
internalErrorsItem.addXref(baseURL + internalError, internalError.toString());
}
// OAI Generator settings
List generatorSettings = div.addList("oai-generator-settings");
generatorSettings.setHead(T_harvest_head_generator_settings);
generatorSettings.addLabel(T_harvest_label_oai_url);
String oaiUrl = ConfigurationManager.getProperty("dspace.oai.url");
if (oaiUrl != null && oaiUrl != "")
generatorSettings.addItem(oaiUrl);
generatorSettings.addLabel(T_harvest_label_oai_source);
String oaiAuthoritativeSource = ConfigurationManager.getProperty("ore.authoritative.source");
if (oaiAuthoritativeSource != null && oaiAuthoritativeSource != "")
generatorSettings.addItem(oaiAuthoritativeSource);
else
generatorSettings.addItem("oai");
// OAI Harvester settings (just iterate over all the values that start with "harvester")
List harvesterSettings = div.addList("oai-harvester-settings");
harvesterSettings.setHead(T_harvest_head_harvester_settings);
String metaString = "harvester.";
Enumeration pe = ConfigurationManager.propertyNames();
while (pe.hasMoreElements())
{
String key = (String)pe.nextElement();
if (key.startsWith(metaString)) {
harvesterSettings.addLabel(key);
harvesterSettings.addItem(ConfigurationManager.getProperty(key) + " ");
}
}
}
} }

View File

@@ -48,6 +48,8 @@ import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.environment.SourceResolver;
import org.dspace.harvest.OAIHarvester;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
/** /**
* Update the alert system based upon the form submitted from the control panel. * Update the alert system based upon the form submitted from the control panel.
@@ -127,7 +129,22 @@ public class ControlPanelAction extends AbstractAction
{ {
SystemwideAlerts.deactivateAlert(); SystemwideAlerts.deactivateAlert();
} }
else if (request.getParameter("submit_harvest_start") != null) {
OAIHarvester.startNewScheduler();
}
else if (request.getParameter("submit_harvest_resume") != null) {
OAIHarvester.resumeScheduler();
}
else if (request.getParameter("submit_harvest_pause") != null) {
OAIHarvester.pauseScheduler();
}
else if (request.getParameter("submit_harvest_stop") != null) {
OAIHarvester.stopScheduler();
}
else if (request.getParameter("submit_harvest_reset") != null) {
OAIHarvester.resetScheduler();
}
return null; return null;
} }

View File

@@ -42,8 +42,13 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Request;
import org.apache.cocoon.servlet.multipart.Part; import org.apache.cocoon.servlet.multipart.Part;
import org.dspace.app.xmlui.utils.UIException; import org.dspace.app.xmlui.utils.UIException;
@@ -51,14 +56,24 @@ import org.dspace.app.xmlui.wing.Message;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.BrowseException;
import org.dspace.browse.IndexBrowse;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Community; import org.dspace.content.Community;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.ItemIterator;
import org.dspace.harvest.OAIHarvester;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
import org.dspace.harvest.OAIHarvester.HarvestingException;
import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
import org.jdom.JDOMException; import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder; import org.jdom.input.SAXBuilder;
import org.xml.sax.SAXException;
/** /**
* Utility methods to processes actions on Communities and Collections. * Utility methods to processes actions on Communities and Collections.
@@ -164,6 +179,203 @@ public class FlowContainerUtils
return result; return result;
} }
/**
* Process the collection harvesting options form.
*
* @param context The current DSpace context.
* @param collectionID The collection id.
* @param request the Cocoon request object
* @return A process result's object.
*/
public static FlowResult processSetupCollectionHarvesting(Context context, int collectionID, Request request) throws SQLException, IOException, AuthorizeException
{
FlowResult result = new FlowResult();
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
String contentSource = request.getParameter("source");
// First, if this is not a harvested collection (anymore), set the harvest type to 0; possibly also wipe harvest settings
if (contentSource.equals("source_normal"))
{
if (hc != null)
hc.delete();
result.setContinue(true);
}
else
{
FlowResult subResult = testOAISettings(context, request);
// create a new harvest instance if all the settings check out
if (hc == null) {
hc = HarvestedCollection.create(context, collectionID);
}
// if the supplied options all check out, set the harvesting parameters on the collection
if (subResult.getErrors().isEmpty()) {
String oaiProvider = request.getParameter("oai_provider");
String oaiSetId = request.getParameter("oai_setid");
String metadataKey = request.getParameter("metadata_format");
String harvestType = request.getParameter("harvest_level");
hc.setHarvestParams(Integer.parseInt(harvestType), oaiProvider, oaiSetId, metadataKey);
hc.setHarvestStatus(HarvestedCollection.STATUS_READY);
}
else {
result.setErrors(subResult.getErrors());
result.setContinue(false);
return result;
}
hc.update();
}
// Save everything
context.commit();
// No notice...
//result.setMessage(new Message("default","Harvesting options successfully modified."));
result.setOutcome(true);
result.setContinue(true);
return result;
}
/**
* Use the collection's harvest settings to immediately perform a harvest cycle.
*
* @param context The current DSpace context.
* @param collectionID The collection id.
* @param request the Cocoon request object
* @return A process result's object.
* @throws TransformerException
* @throws SAXException
* @throws ParserConfigurationException
* @throws CrosswalkException
*/
public static FlowResult processRunCollectionHarvest(Context context, int collectionID, Request request) throws SQLException, IOException, AuthorizeException, CrosswalkException, ParserConfigurationException, SAXException, TransformerException
{
FlowResult result = new FlowResult();
OAIHarvester harvester;
List<String> testErrors = new ArrayList<String>();
Collection collection = Collection.find(context, collectionID);
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
//TODO: is there a cleaner way to do this?
try {
if (HarvestScheduler.status != HarvestScheduler.HARVESTER_STATUS_STOPPED) {
synchronized(HarvestScheduler.lock) {
HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_INSERT_THREAD;
HarvestScheduler.interruptValue = collection.getID();
HarvestScheduler.lock.notify();
}
}
else {
harvester = new OAIHarvester(context, collection, hc);
harvester.runHarvest();
}
}
catch (Exception e) {
testErrors.add(e.getMessage());
result.setErrors(testErrors);
result.setContinue(false);
return result;
}
result.setContinue(true);
return result;
}
/**
* Purge the collection of all items, then run a fresh harvest cycle.
*
* @param context The current DSpace context.
* @param collectionID The collection id.
* @param request the Cocoon request object
* @return A process result's object.
* @throws TransformerException
* @throws SAXException
* @throws ParserConfigurationException
* @throws CrosswalkException
* @throws BrowseException
*/
public static FlowResult processReimportCollection(Context context, int collectionID, Request request) throws SQLException, IOException, AuthorizeException, CrosswalkException, ParserConfigurationException, SAXException, TransformerException, BrowseException
{
FlowResult result = new FlowResult();
Collection collection = Collection.find(context, collectionID);
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
ItemIterator it = collection.getAllItems();
//IndexBrowse ib = new IndexBrowse(context);
while (it.hasNext()) {
Item item = it.next();
//System.out.println("Deleting: " + item.getHandle());
//ib.itemRemoved(item);
collection.removeItem(item);
}
hc.setHarvestResult(null,"");
hc.update();
collection.update();
context.commit();
result = processRunCollectionHarvest(context, collectionID, request);
return result;
}
/**
* Test the supplied OAI settings.
*
* @param context
* @param request
* @return
*/
public static FlowResult testOAISettings(Context context, Request request)
{
FlowResult result = new FlowResult();
String oaiProvider = request.getParameter("oai_provider");
String oaiSetId = request.getParameter("oai_setid");
String metadataKey = request.getParameter("metadata_format");
String harvestType = request.getParameter("harvest_level");
int harvestTypeInt = 0;
if (oaiProvider == null || oaiProvider.length() == 0)
result.addError("oai_provider");
if (oaiSetId == null || oaiSetId.length() == 0)
result.addError("oai_setid");
if (metadataKey == null || metadataKey.length() == 0)
result.addError("metadata_format");
if (harvestType == null || harvestType.length() == 0)
result.addError("harvest_level");
else
harvestTypeInt = Integer.parseInt(harvestType);
if (result.getErrors() == null) {
List<String> testErrors = OAIHarvester.verifyOAIharvester(oaiProvider, oaiSetId, metadataKey, (harvestTypeInt>1));
result.setErrors(testErrors);
}
if (result.getErrors() == null || result.getErrors().isEmpty()) {
result.setOutcome(true);
// On a successful test we still want to stay in the loop, not continue out of it
//result.setContinue(true);
result.setMessage(new Message("default","Harvesting settings are valid."));
}
else {
result.setOutcome(false);
result.setContinue(false);
// don't really need a message when the errors are highlighted already
//result.setMessage(new Message("default","Harvesting is not properly configured."));
}
return result;
}
/** /**
* Look up the id of the template item for a given collection. * Look up the id of the template item for a given collection.

View File

@@ -73,6 +73,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail"); private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail");
private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata"); private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata");
private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles"); private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles");
private static final Message T_options_harvest = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest");
private static final Message T_submit_return = message("xmlui.general.return"); private static final Message T_submit_return = message("xmlui.general.return");
@@ -145,6 +146,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
List options = main.addList("options", List.TYPE_SIMPLE, "horizontal"); List options = main.addList("options", List.TYPE_SIMPLE, "horizontal");
options.addItem().addXref(baseURL+"&submit_metadata",T_options_metadata); options.addItem().addXref(baseURL+"&submit_metadata",T_options_metadata);
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_roles",T_options_roles); options.addItem().addHighlight("bold").addXref(baseURL+"&submit_roles",T_options_roles);
options.addItem().addXref(baseURL+"&submit_harvesting",T_options_harvest);
// The table of admin roles // The table of admin roles
Table rolesTable = main.addTable("roles-table", 6, 5); Table rolesTable = main.addTable("roles-table", 6, 5);

View File

@@ -0,0 +1,222 @@
/*
* EditCollectionHarvestingForm.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2006/07/13 23:20:54 $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.app.xmlui.aspect.administrative.collection;
import java.sql.SQLException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Para;
import org.dspace.app.xmlui.wing.element.Radio;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.core.ConfigurationManager;
/**
* This is the other form that deals with harvesting. This one comes up when the collection is
* edited with the harvesting options set and verified. Allows two actions: "import" and "reingest",
* as well as "change", which takes the user to the other harvesting form.
* @author Alexey Maslov
*/
public class EditCollectionHarvestingForm extends AbstractDSpaceTransformer
{
/** Language Strings */
private static final Message T_dspace_home = message("xmlui.general.dspace_home");
private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail");
private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata");
private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles");
private static final Message T_main_head = message("xmlui.administrative.collection.EditCollectionMetadataForm.main_head");
private static final Message T_options_harvest = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest");
private static final Message T_title = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.title");
private static final Message T_trail = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail");
private static final Message T_label_source = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source");
private static final Message T_source_normal = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal");
private static final Message T_source_harvested = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested");
private static final Message T_submit_return = message("xmlui.general.return");
private static final Message T_submit_save = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save");
private static final Message T_main_settings_head = message("xmlui.administrative.collection.EditCollectionHarvestingForm.main_settings_head");
private static final Message T_label_oai_provider = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_oai_provider");
private static final Message T_label_setid = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_setid");
private static final Message T_label_metadata_format = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_metadata_format");
private static final Message T_label_harvest_level = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_level");
private static final Message T_label_harvest_result = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_result");
private static final Message T_harvest_result_new = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_result_new");
private static final Message T_label_harvest_status = message("xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_status");
private static final Message T_harvest_status_ready = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_ready");
private static final Message T_harvest_status_busy = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_busy");
private static final Message T_harvest_status_queued = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_queued");
private static final Message T_harvest_status_oai_error = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_oai_error");
private static final Message T_harvest_status_unknown_error = message("xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_unknown_error");
private static final Message T_option_md_only = message("xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_only");
private static final Message T_option_md_and_ref = message("xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_ref");
private static final Message T_option_md_and_bs = message("xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_bs");
private static final Message T_submit_change_settings = message("xmlui.administrative.collection.EditCollectionHarvestingForm.submit_change_settings");
private static final Message T_submit_import_now = message("xmlui.administrative.collection.EditCollectionHarvestingForm.submit_import_now");
private static final Message T_submit_reimport_collection = message("xmlui.administrative.collection.EditCollectionHarvestingForm.submit_reimport_collection");
public void addPageMeta(PageMeta pageMeta) throws WingException
{
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
pageMeta.addTrail().addContent(T_collection_trail);
pageMeta.addTrail().addContent(T_trail);
}
public void addBody(Body body) throws WingException, SQLException, AuthorizeException
{
int collectionID = parameters.getParameterAsInteger("collectionID", -1);
Collection thisCollection = Collection.find(context, collectionID);
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
Request request = ObjectModelHelper.getRequest(objectModel);
String baseURL = contextPath + "/admin/collection?administrative-continue=" + knot.getId();
String oaiProviderValue = hc.getOaiSource();
String oaiSetIdValue = hc.getOaiSetId();
String metadataFormatValue = hc.getHarvestMetadataConfig();
int harvestLevelValue = hc.getHarvestType();
int harvestStatusValue = hc.getHarvestStatus();
// DIVISION: main
Division main = body.addInteractiveDivision("collection-harvesting-edit",contextPath+"/admin/collection",Division.METHOD_MULTIPART,"primary administrative collection");
main.setHead(T_main_head.parameterize(thisCollection.getMetadata("name")));
List options = main.addList("options",List.TYPE_SIMPLE,"horizontal");
options.addItem().addXref(baseURL+"&submit_metadata",T_options_metadata);
options.addItem().addXref(baseURL+"&submit_roles",T_options_roles);
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_harvesting",T_options_harvest);
// The top-level, all-setting, countent source radio button
List harvestSource = main.addList("harvestSource", "form");
harvestSource.addLabel(T_label_source);
Radio source = harvestSource.addItem().addRadio("source");
source.addOption(hc == null, "source_normal", T_source_normal);
source.addOption(hc != null, "source_harvested", T_source_harvested);
List settings = main.addList("harvestSettings", "form");
settings.setHead(T_main_settings_head);
settings.addLabel(T_label_oai_provider);
settings.addItem(oaiProviderValue);
settings.addLabel(T_label_setid);
settings.addItem(oaiSetIdValue);
// The big complex way of getting to our metadata
settings.addLabel(T_label_metadata_format);
String key = "harvester.oai.metadataformats." + metadataFormatValue;
String metadataString = ConfigurationManager.getProperty(key);
String displayName;
if (metadataString.indexOf(',') != -1)
displayName = metadataString.substring(metadataString.indexOf(',') + 1);
else
displayName = metadataFormatValue + "(" + metadataString + ")";
settings.addItem(displayName);
settings.addLabel(T_label_harvest_level);
Item harvestLevel = settings.addItem();
switch (harvestLevelValue) {
case 1: harvestLevel.addContent(T_option_md_only); break;
case 2: harvestLevel.addContent(T_option_md_and_ref); break;
default: harvestLevel.addContent(T_option_md_and_bs); break;
}
/* Results of the last harvesting cycle */
if (harvestLevelValue > 0) {
settings.addLabel(T_label_harvest_result);
Item harvestResult = settings.addItem();
if (hc.getHarvestMessage() != null) {
harvestResult.addContent(hc.getHarvestMessage() + " on " + hc.getHarvestStartTime());
}
else {
harvestResult.addContent(T_harvest_result_new);
}
}
/* Current status */
settings.addLabel(T_label_harvest_status);
Item harvestStatus = settings.addItem();
switch(harvestStatusValue) {
case HarvestedCollection.STATUS_READY: harvestStatus.addContent(T_harvest_status_ready); break;
case HarvestedCollection.STATUS_BUSY: harvestStatus.addContent(T_harvest_status_busy); break;
case HarvestedCollection.STATUS_QUEUED: harvestStatus.addContent(T_harvest_status_queued); break;
case HarvestedCollection.STATUS_OAI_ERROR: harvestStatus.addContent(T_harvest_status_oai_error); break;
case HarvestedCollection.STATUS_UNKNOWN_ERROR: harvestStatus.addContent(T_harvest_status_unknown_error); break;
}
settings.addLabel();
Item harvestButtons = settings.addItem();
harvestButtons.addButton("submit_change").setValue(T_submit_change_settings);
harvestButtons.addButton("submit_import_now").setValue(T_submit_import_now);
harvestButtons.addButton("submit_reimport").setValue(T_submit_reimport_collection);
Para buttonList = main.addPara();
buttonList.addButton("submit_save").setValue(T_submit_save);
buttonList.addButton("submit_return").setValue(T_submit_return);
main.addHidden("administrative-continue").setValue(knot.getId());
}
}

View File

@@ -73,6 +73,7 @@ public class EditCollectionMetadataForm extends AbstractDSpaceTransformer
private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail"); private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail");
private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata"); private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata");
private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles"); private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles");
private static final Message T_options_harvest = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest");
private static final Message T_submit_return = message("xmlui.general.return"); private static final Message T_submit_return = message("xmlui.general.return");
@@ -135,6 +136,7 @@ public class EditCollectionMetadataForm extends AbstractDSpaceTransformer
List options = main.addList("options",List.TYPE_SIMPLE,"horizontal"); List options = main.addList("options",List.TYPE_SIMPLE,"horizontal");
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_metadata",T_options_metadata); options.addItem().addHighlight("bold").addXref(baseURL+"&submit_metadata",T_options_metadata);
options.addItem().addXref(baseURL+"&submit_roles",T_options_roles); options.addItem().addXref(baseURL+"&submit_roles",T_options_roles);
options.addItem().addXref(baseURL+"&submit_harvesting",T_options_harvest);
// The grand list of metadata options // The grand list of metadata options

View File

@@ -0,0 +1,278 @@
/*
* SetupCollectionHarvestingForm.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2006/07/13 23:20:54 $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.app.xmlui.aspect.administrative.collection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.dspace.app.xmlui.aspect.administrative.FlowContainerUtils;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Button;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.Option;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Para;
import org.dspace.app.xmlui.wing.element.Radio;
import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Text;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester;
import org.dspace.core.ConfigurationManager;
/**
* Presents the user (in this case an administrator over the collection) with the
* form to edit that collection's metadata, logo, and item template.
* @author Alexey Maslov
*/
public class SetupCollectionHarvestingForm extends AbstractDSpaceTransformer
{
/** Language Strings */
private static final Message T_dspace_home =
message("xmlui.general.dspace_home");
private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail");
private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata");
private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles");
private static final Message T_main_head = message("xmlui.administrative.collection.EditCollectionMetadataForm.main_head");
private static final Message T_options_harvest = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest");
private static final Message T_title = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.title");
private static final Message T_trail = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail");
private static final Message T_label_source = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source");
private static final Message T_source_normal = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal");
private static final Message T_source_harvested = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested");
private static final Message T_submit_return = message("xmlui.general.return");
private static final Message T_submit_save = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save");
private static final Message T_main_settings_head = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.main_settings_head");
private static final Message T_options_head = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.options_head");
private static final Message T_label_oai_provider = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.label_oai_provider");
private static final Message T_label_setid = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.label_setid");
private static final Message T_label_metadata_format = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.label_metadata_format");
private static final Message T_help_oaiurl = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaiurl");
private static final Message T_error_oaiurl = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaiurl");
private static final Message T_help_oaisetid = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaisetid");
private static final Message T_error_oaisetid = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaisetid");
private static final Message T_label_harvest_level = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level");
private static final Message T_option_md_only = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_only");
private static final Message T_option_md_and_ref = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_ref");
private static final Message T_option_md_and_bs = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_bs");
private static final Message T_submit_test = message("xmlui.administrative.collection.SetupCollectionHarvestingForm.submit_test");
public void addPageMeta(PageMeta pageMeta) throws WingException
{
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
pageMeta.addTrail().addContent(T_collection_trail);
pageMeta.addTrail().addContent(T_trail);
}
public void addBody(Body body) throws WingException, SQLException, AuthorizeException
{
int collectionID = parameters.getParameterAsInteger("collectionID", -1);
Collection thisCollection = Collection.find(context, collectionID);
Request request = ObjectModelHelper.getRequest(objectModel);
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
String baseURL = contextPath + "/admin/collection?administrative-continue=" + knot.getId();
String errorString = parameters.getParameter("errors",null);
String[] errors = errorString.split(",");
HashMap<String,String> errorMap = new HashMap<String,String>();
for (String error : errors) {
//System.out.println(errorString);
String[] errorPieces = error.split(":",2);
if (errorPieces.length > 1)
errorMap.put(errorPieces[0], errorPieces[1]);
else
errorMap.put(errorPieces[0], errorPieces[0]);
}
String oaiProviderValue;
String oaiSetIdValue;
String metadataFormatValue;
int harvestLevelValue;
if (hc != null && request.getParameter("submit_test") == null) {
oaiProviderValue = hc.getOaiSource();
oaiSetIdValue = hc.getOaiSetId();
metadataFormatValue = hc.getHarvestMetadataConfig();
harvestLevelValue = hc.getHarvestType();
}
else {
oaiProviderValue = parameters.getParameter("oaiProviderValue", "");
oaiSetIdValue = parameters.getParameter("oaiSetIdValue", "");
metadataFormatValue = parameters.getParameter("metadataFormatValue", "");
String harvestLevelString = parameters.getParameter("harvestLevelValue","0");
if (harvestLevelString.length() == 0)
harvestLevelValue = 0;
else
harvestLevelValue = Integer.parseInt(harvestLevelString);
}
// DIVISION: main
Division main = body.addInteractiveDivision("collection-harvesting-setup",contextPath+"/admin/collection",Division.METHOD_MULTIPART,"primary administrative collection");
main.setHead(T_main_head.parameterize(thisCollection.getMetadata("name")));
List options = main.addList("options",List.TYPE_SIMPLE,"horizontal");
options.addItem().addXref(baseURL+"&submit_metadata",T_options_metadata);
options.addItem().addXref(baseURL+"&submit_roles",T_options_roles);
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_harvesting",T_options_harvest);
// The top-level, all-setting, countent source radio button
List harvestSource = main.addList("harvestSource", "form");
harvestSource.addLabel(T_label_source);
Radio source = harvestSource.addItem().addRadio("source");
source.addOption(hc == null || harvestLevelValue == -1, "source_normal", T_source_normal);
source.addOption(hc != null, "source_harvested", T_source_harvested);
List settings = main.addList("harvestSettings", "form");
settings.setHead(T_main_settings_head);
settings.addLabel(T_label_oai_provider);
Text oaiProvider = settings.addItem().addText("oai_provider");
oaiProvider.setSize(40);
oaiProvider.setValue(oaiProviderValue);
oaiProvider.setHelp(T_help_oaiurl);
if (errorMap.containsKey(OAIHarvester.OAI_ADDRESS_ERROR)) {
oaiProvider.addError(errorMap.get(OAIHarvester.OAI_ADDRESS_ERROR));
}
if (errorMap.containsKey("oai_provider")) {
oaiProvider.addError(T_error_oaiurl);
//oaiProvider.addError("You must provide a set id of the target collection.");
}
settings.addLabel(T_label_setid);
Text oaiSetId = settings.addItem().addText("oai_setid");
oaiSetId.setSize(40);
oaiSetId.setValue(oaiSetIdValue);
oaiSetId.setHelp(T_help_oaisetid);
if (errorMap.containsKey(OAIHarvester.OAI_SET_ERROR)) {
oaiSetId.addError(errorMap.get(OAIHarvester.OAI_SET_ERROR));
}
if (errorMap.containsKey("oai_setid")) {
oaiSetId.addError(T_error_oaisetid);
}
settings.addLabel(T_label_metadata_format);
Select metadataFormat = settings.addItem().addSelect("metadata_format");
if (errorMap.containsKey(OAIHarvester.OAI_ORE_ERROR)) {
metadataFormat.addError(errorMap.get(OAIHarvester.OAI_ORE_ERROR));
}
if (errorMap.containsKey(OAIHarvester.OAI_DMD_ERROR)) {
metadataFormat.addError(errorMap.get(OAIHarvester.OAI_DMD_ERROR));
}
// Add an entry for each instance of ingestion crosswalks configured for harvesting
String metaString = "harvester.oai.metadataformats.";
Enumeration pe = ConfigurationManager.propertyNames();
while (pe.hasMoreElements())
{
String key = (String)pe.nextElement();
if (key.startsWith(metaString)) {
String metadataString = ConfigurationManager.getProperty(key);
String metadataKey = key.substring(metaString.length());
String displayName;
if (metadataString.indexOf(',') != -1)
displayName = metadataString.substring(metadataString.indexOf(',') + 1);
else
displayName = metadataKey + "(" + metadataString + ")";
metadataFormat.addOption(metadataKey.equalsIgnoreCase(metadataFormatValue), metadataKey, displayName);
}
}
settings.addLabel();
Item harvestButtons = settings.addItem();
harvestButtons.addButton("submit_test").setValue(T_submit_test);
// Various non-critical harvesting options
//Division optionsDiv = main.addDivision("collection-harvesting-options","secondary");
//optionsDiv.setHead(T_options_head);
List harvestOptions = main.addList("harvestOptions", "form");
harvestOptions.setHead(T_options_head);
harvestOptions.addLabel(T_label_harvest_level);
Radio harvestLevel = harvestOptions.addItem().addRadio("harvest_level");
harvestLevel.addOption(harvestLevelValue == 1, 1, T_option_md_only);
harvestLevel.addOption(harvestLevelValue == 2, 2, T_option_md_and_ref);
harvestLevel.addOption(harvestLevelValue != 1 && harvestLevelValue != 2, 3, T_option_md_and_bs);
Para buttonList = main.addPara();
buttonList.addButton("submit_save").setValue(T_submit_save);
buttonList.addButton("submit_return").setValue(T_submit_return);
main.addHidden("administrative-continue").setValue(knot.getId());
}
}

View File

@@ -0,0 +1,145 @@
/*
* ToggleCollectionHarvestingForm.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2006/07/13 23:20:54 $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.app.xmlui.aspect.administrative.collection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.dspace.app.xmlui.aspect.administrative.FlowContainerUtils;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Button;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.Option;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Para;
import org.dspace.app.xmlui.wing.element.Radio;
import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Text;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester;
import org.dspace.core.ConfigurationManager;
/**
* The form displayed for collections that do not have any harvesting settings active
* (i.e. do not have a row in the harvest_instance table)
*
* @author Alexey Maslov
*/
public class ToggleCollectionHarvestingForm extends AbstractDSpaceTransformer
{
/** Language Strings */
private static final Message T_dspace_home =
message("xmlui.general.dspace_home");
private static final Message T_collection_trail = message("xmlui.administrative.collection.general.collection_trail");
private static final Message T_options_metadata = message("xmlui.administrative.collection.general.options_metadata");
private static final Message T_options_roles = message("xmlui.administrative.collection.general.options_roles");
private static final Message T_main_head = message("xmlui.administrative.collection.EditCollectionMetadataForm.main_head");
private static final Message T_options_harvest = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest");
private static final Message T_title = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.title");
private static final Message T_trail = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail");
private static final Message T_label_source = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source");
private static final Message T_source_normal = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal");
private static final Message T_source_harvested = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested");
private static final Message T_submit_return = message("xmlui.general.return");
private static final Message T_submit_save = message("xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save");
public void addPageMeta(PageMeta pageMeta) throws WingException
{
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
pageMeta.addTrail().addContent(T_collection_trail);
pageMeta.addTrail().addContent(T_trail);
}
public void addBody(Body body) throws WingException, SQLException, AuthorizeException
{
int collectionID = parameters.getParameterAsInteger("collectionID", -1);
Collection thisCollection = Collection.find(context, collectionID);
// This should always be null; it's an error condition for this tranformer to be called when
// a harvest instance exists for this collection
HarvestedCollection hc = HarvestedCollection.find(context, collectionID);
String baseURL = contextPath + "/admin/collection?administrative-continue=" + knot.getId();
// DIVISION: main
Division main = body.addInteractiveDivision("collection-harvesting-setup",contextPath+"/admin/collection",Division.METHOD_MULTIPART,"primary administrative collection");
main.setHead(T_main_head.parameterize(thisCollection.getMetadata("name")));
List options = main.addList("options",List.TYPE_SIMPLE,"horizontal");
options.addItem().addXref(baseURL+"&submit_metadata",T_options_metadata);
options.addItem().addXref(baseURL+"&submit_roles",T_options_roles);
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_harvesting",T_options_harvest);
// The top-level, all-setting, countent source radio button
List harvestSource = main.addList("harvestSource", "form");
harvestSource.addLabel(T_label_source);
Radio source = harvestSource.addItem().addRadio("source");
source.addOption(hc == null, "source_normal", T_source_normal);
source.addOption(hc != null, "source_harvested", T_source_harvested);
Para buttonList = main.addPara();
buttonList.addButton("submit_save").setValue(T_submit_save);
buttonList.addButton("submit_return").setValue(T_submit_return);
main.addHidden("administrative-continue").setValue(knot.getId());
}
}

View File

@@ -58,6 +58,7 @@ import org.dspace.app.xmlui.configuration.XMLUIConfiguration;
import org.dspace.app.xmlui.utils.AuthenticationUtil; import org.dspace.app.xmlui.utils.AuthenticationUtil;
import org.dspace.app.xmlui.utils.ContextUtil; import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.harvest.OAIHarvester;
/** /**
* This is a wrapper servlet around the cocoon servlet that prefroms two functions, 1) it * This is a wrapper servlet around the cocoon servlet that prefroms two functions, 1) it
@@ -212,6 +213,16 @@ public class DSpaceCocoonServletFilter implements Filter
"DSpace configuration directory. \n\n",t); "DSpace configuration directory. \n\n",t);
} }
if (ConfigurationManager.getBooleanProperty("harvester.autoStart"))
{
try {
OAIHarvester.startNewScheduler();
}
catch (Throwable t)
{
//ignore
}
}
} }

View File

@@ -0,0 +1,166 @@
/*
* DSpaceOREGenerator.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2008/06/30 05:30:55 $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. 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.app.xmlui.cocoon;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.http.HttpServletResponse;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.generation.AbstractGenerator;
import org.dspace.app.xmlui.objectmanager.AbstractAdapter;
import org.dspace.app.xmlui.objectmanager.ContainerAdapter;
import org.dspace.app.xmlui.objectmanager.ItemAdapter;
import org.dspace.app.xmlui.objectmanager.RepositoryAdapter;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.content.crosswalk.DisseminationCrosswalk;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.core.PluginManager;
import org.dspace.handle.HandleManager;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.output.SAXOutputter;
import org.xml.sax.SAXException;
/**
* Generate an ORE aggregation of a DSpace Item. The object to be rendered should be an item identified by pasing
* in one of the two parameters: handle or internal. The fragment parameter determines the encoding format for
* the aggregation; only Atom is supported at this time.
* @author Alexey Maslov
*/
public class DSpaceOREGenerator extends AbstractGenerator
{
/**
* Generate the ORE Aggregation.
*/
public void generate() throws IOException, SAXException,
ProcessingException {
try {
// Grab the context.
Context context = ContextUtil.obtainContext(objectModel);
Item item = getItem(context);
if (item == null)
throw new ResourceNotFoundException("Unable to locate object.");
// Instantiate and execute the ORE plugin
SAXOutputter out = new SAXOutputter(contentHandler);
DisseminationCrosswalk xwalk = (DisseminationCrosswalk)PluginManager.getNamedPlugin(DisseminationCrosswalk.class,"ore");
Element ore = xwalk.disseminateElement(item);
out.output(ore);
/* Generate the METS document
contentHandler.startDocument();
adapter.renderMETS(contentHandler,lexicalHandler);
contentHandler.endDocument();*/
} catch (JDOMException je) {
throw new ProcessingException(je);
} catch (AuthorizeException ae) {
throw new ProcessingException(ae);
} catch (CrosswalkException ce) {
throw new ProcessingException(ce);
} catch (SQLException sqle) {
throw new ProcessingException(sqle);
}
}
private Item getItem(Context context) throws SQLException, CrosswalkException
{
Request request = ObjectModelHelper.getRequest(objectModel);
String contextPath = request.getContextPath();
// Determine the correct adatper to use for this item
String handle = parameters.getParameter("handle",null);
String internal = parameters.getParameter("internal",null);
if (handle != null)
{
// Specified using a regular handle.
DSpaceObject dso = HandleManager.resolveToObject(context, handle);
// Handles can be either items or containers.
if (dso instanceof Item)
return (Item)dso;
else
throw new CrosswalkException("ORE dissemination only available for DSpace Items.");
}
else if (internal != null)
{
// Internal identifier, format: "type:id".
String[] parts = internal.split(":");
if (parts.length == 2)
{
String type = parts[0];
int id = Integer.valueOf(parts[1]);
if ("item".equals(type))
{
Item item = Item.find(context,id);
return item;
}
else
throw new CrosswalkException("ORE dissemination only available for DSpace Items.");
}
}
return null;
}
}

View File

@@ -47,6 +47,7 @@ importClass(Packages.org.dspace.content.Bundle);
importClass(Packages.org.dspace.content.Item); importClass(Packages.org.dspace.content.Item);
importClass(Packages.org.dspace.content.Collection); importClass(Packages.org.dspace.content.Collection);
importClass(Packages.org.dspace.content.Community); importClass(Packages.org.dspace.content.Community);
importClass(Packages.org.dspace.harvest.HarvestedCollection);
importClass(Packages.org.dspace.eperson.EPerson); importClass(Packages.org.dspace.eperson.EPerson);
importClass(Packages.org.dspace.eperson.Group); importClass(Packages.org.dspace.eperson.Group);
@@ -2217,6 +2218,11 @@ function doEditCollection(collectionID,newCollectionP)
// go assign colection roles // go assign colection roles
doAssignCollectionRoles(collectionID); doAssignCollectionRoles(collectionID);
} }
else if (cocoon.request.get("submit_harvesting"))
{
// edit collection harvesting settings
doEditCollectionHarvesting(collectionID);
}
else else
{ {
// This case should never happen but to prevent an infinite loop // This case should never happen but to prevent an infinite loop
@@ -2243,7 +2249,8 @@ function doEditCollectionMetadata(collectionID)
assertEditCollection(collectionID); assertEditCollection(collectionID);
result=null; result=null;
if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") || cocoon.request.get("submit_roles")) if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") ||
cocoon.request.get("submit_roles") || cocoon.request.get("submit_harvesting"))
{ {
// return to the editCollection function which will determine where to go next. // return to the editCollection function which will determine where to go next.
return null; return null;
@@ -2299,7 +2306,8 @@ function doAssignCollectionRoles(collectionID)
result = null; result = null;
if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") || cocoon.request.get("submit_roles")) if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") ||
cocoon.request.get("submit_roles") || cocoon.request.get("submit_harvesting"))
{ {
// return to the editCollection function which will determine where to go next. // return to the editCollection function which will determine where to go next.
return null; return null;
@@ -2391,6 +2399,110 @@ function doAssignCollectionRoles(collectionID)
}while(true); }while(true);
} }
/**
* Set up various harvesting options.
* From here the user can also move on to edit roles and edit metadata screen.
*/
function doSetupCollectionHarvesting(collectionID)
{
assertEditCollection(collectionID);
var result = null;
var oaiProviderValue = null;
var oaiSetIdValue = null;
var metadataFormatValue = null;
var harvestLevelValue = null;
do {
sendPageAndWait("admin/collection/setupHarvesting",{"collectionID":collectionID,"oaiProviderValue":oaiProviderValue,"oaiSetIdValue":oaiSetIdValue,"metadataFormatValue":metadataFormatValue,"harvestLevelValue":harvestLevelValue},result);
result = null;
oaiProviderValue = cocoon.request.get("oai_provider");
oaiSetIdValue = cocoon.request.get("oai_setid");
metadataFormatValue = cocoon.request.get("metadata_format");
harvestLevelValue = cocoon.request.get("harvest_level");
assertEditCollection(collectionID);
if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") ||
cocoon.request.get("submit_roles") || cocoon.request.get("submit_harvesting"))
{
// return to the editCollection function which will determine where to go next.
return null;
}
else if (cocoon.request.get("submit_save"))
{
// Save updates
result = FlowContainerUtils.processSetupCollectionHarvesting(getDSContext(), collectionID, cocoon.request);
}
else if (cocoon.request.get("submit_test"))
{
// Ping the OAI server and verify that the address/set/metadata combo is present there
// Can get this either in a single GetRecords OAI request or via two separate ones: ListSets and ListMetadataFormats
result = FlowContainerUtils.testOAISettings(getDSContext(), cocoon.request);
}
} while (!result.getContinue());
}
/**
* Edit existing harvesting options.
* From here the user can also move on to edit roles and edit metadata screen.
*/
function doEditCollectionHarvesting(collectionID)
{
assertEditCollection(collectionID);
var result = null;
do
{
// If this collection's havresting is not set up properly, redirect to the setup screen
if (HarvestedCollection.find(getDSContext(), collectionID) == null) {
sendPageAndWait("admin/collection/toggleHarvesting",{"collectionID":collectionID},result);
}
else if (!HarvestedCollection.isHarvestable(getDSContext(), collectionID)) {
doSetupCollectionHarvesting(collectionID);
}
else {
sendPageAndWait("admin/collection/editHarvesting",{"collectionID":collectionID},result);
}
result = null;
assertEditCollection(collectionID);
if (cocoon.request.get("submit_return") || cocoon.request.get("submit_metadata") ||
cocoon.request.get("submit_roles") || cocoon.request.get("submit_harvesting"))
{
// return to the editCollection function which will determine where to go next.
return null;
}
else if (cocoon.request.get("submit_save"))
{
// Save updates
result = FlowContainerUtils.processSetupCollectionHarvesting(getDSContext(), collectionID, cocoon.request);
}
else if (cocoon.request.get("submit_import_now"))
{
// Test the settings and run the import immediately
result = FlowContainerUtils.processRunCollectionHarvest(getDSContext(), collectionID, cocoon.request);
}
else if (cocoon.request.get("submit_reimport"))
{
// Test the settings and run the import immediately
result = FlowContainerUtils.processReimportCollection(getDSContext(), collectionID, cocoon.request);
}
else if (cocoon.request.get("submit_change"))
{
doSetupCollectionHarvesting(collectionID);
}
} while (true);
}
/** /**
* Delete a specified collection role. Under the current implementation, the only roles this applies to * Delete a specified collection role. Under the current implementation, the only roles this applies to
* directly are the workflow steps. Admin and submitter authorizations cannot be deleted once formed, and * directly are the workflow steps. Admin and submitter authorizations cannot be deleted once formed, and

View File

@@ -85,6 +85,9 @@ to administer DSpace.
<map:transformer name="SearchItemForm" src="org.dspace.app.xmlui.aspect.administrative.mapper.SearchItemForm"/> <map:transformer name="SearchItemForm" src="org.dspace.app.xmlui.aspect.administrative.mapper.SearchItemForm"/>
<map:transformer name="EditCollectionMetadataForm" src="org.dspace.app.xmlui.aspect.administrative.collection.EditCollectionMetadataForm"/> <map:transformer name="EditCollectionMetadataForm" src="org.dspace.app.xmlui.aspect.administrative.collection.EditCollectionMetadataForm"/>
<map:transformer name="ToggleCollectionHarvestingForm" src="org.dspace.app.xmlui.aspect.administrative.collection.ToggleCollectionHarvestingForm"/>
<map:transformer name="SetupCollectionHarvestingForm" src="org.dspace.app.xmlui.aspect.administrative.collection.SetupCollectionHarvestingForm"/>
<map:transformer name="EditCollectionHarvestingForm" src="org.dspace.app.xmlui.aspect.administrative.collection.EditCollectionHarvestingForm"/>
<map:transformer name="AssignCollectionRoles" src="org.dspace.app.xmlui.aspect.administrative.collection.AssignCollectionRoles"/> <map:transformer name="AssignCollectionRoles" src="org.dspace.app.xmlui.aspect.administrative.collection.AssignCollectionRoles"/>
<map:transformer name="DeleteCollectionRoleConfirm" src="org.dspace.app.xmlui.aspect.administrative.collection.DeleteCollectionRoleConfirm"/> <map:transformer name="DeleteCollectionRoleConfirm" src="org.dspace.app.xmlui.aspect.administrative.collection.DeleteCollectionRoleConfirm"/>
<map:transformer name="DeleteCollectionConfirm" src="org.dspace.app.xmlui.aspect.administrative.collection.DeleteCollectionConfirm"/> <map:transformer name="DeleteCollectionConfirm" src="org.dspace.app.xmlui.aspect.administrative.collection.DeleteCollectionConfirm"/>
@@ -636,6 +639,37 @@ to administer DSpace.
</map:transform> </map:transform>
</map:match> </map:match>
<!-- Harvesting options setup form, used for collections that are being edited or set up
for the first time -->
<map:match pattern="admin/collection/setupHarvesting">
<map:transform type="SetupCollectionHarvestingForm">
<map:parameter name="collectionID" value="{flow-attribute:collectionID}"/>
<map:parameter name="errors" value="{flow-attribute:errors}"/>
<map:parameter name="oaiProviderValue" value="{flow-attribute:oaiProviderValue}"/>
<map:parameter name="oaiSetIdValue" value="{flow-attribute:oaiSetIdValue}"/>
<map:parameter name="metadataFormatValue" value="{flow-attribute:metadataFormatValue}"/>
<map:parameter name="harvestLevelValue" value="{flow-attribute:harvestLevelValue}"/>
</map:transform>
</map:match>
<!-- Harvesting options setup form, used for collections that are being edited or set up
for the first time -->
<map:match pattern="admin/collection/editHarvesting">
<map:transform type="EditCollectionHarvestingForm">
<map:parameter name="collectionID" value="{flow-attribute:collectionID}"/>
<map:parameter name="errors" value="{flow-attribute:errors}"/>
</map:transform>
</map:match>
<!-- Initial toggle -->
<map:match pattern="admin/collection/toggleHarvesting">
<map:transform type="ToggleCollectionHarvestingForm">
<map:parameter name="collectionID" value="{flow-attribute:collectionID}"/>
</map:transform>
</map:match>
<!-- Confirmation screen for deleteing one of the standard authorization groups --> <!-- Confirmation screen for deleteing one of the standard authorization groups -->
<map:match pattern="admin/collection/deleteRole"> <map:match pattern="admin/collection/deleteRole">
<map:transform type="DeleteCollectionRoleConfirm"> <map:transform type="DeleteCollectionRoleConfirm">

View File

@@ -1470,6 +1470,72 @@
<message key="xmlui.administrative.collection.CreateCollectionForm.trail">Create Collection</message> <message key="xmlui.administrative.collection.CreateCollectionForm.trail">Create Collection</message>
<message key="xmlui.administrative.collection.CreateCollectionForm.main_head">Enter Metadata for a New Collection of {0}</message> <message key="xmlui.administrative.collection.CreateCollectionForm.main_head">Enter Metadata for a New Collection of {0}</message>
<message key="xmlui.administrative.collection.CreateCollectionForm.submit_save">Create</message> <message key="xmlui.administrative.collection.CreateCollectionForm.submit_save">Create</message>
<!-- General to the harvesting options under collection -->
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.title">Collection Harvesting Settings</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail">Harvesting</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest">Content Source</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source">Content source</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal">This is a standard DSpace collection</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested">This collection harvests its content from an external source</message>
<message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save">Save</message>
<!-- org.dspace.app.xmlui.administrative.collection.SetupCollectionHarvestingForm.java -->
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.main_settings_head">Harvested Collection Location</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.options_head">Harvesting Options</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_oai_provider">OAI Provider</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_setid">OAI Set id</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_metadata_format">Metadata Format</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaiurl">The url of the target repository's OAI provider service</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaiurl">You must provide a set id of the target collection.</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaisetid">The persistent identifier used by the OAI provider to desginate the target collection</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaisetid">You must provide a set id of the target collection.</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Content being harvested</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Content being harvested</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_only">Harvest metadata only.</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_ref">Harvest metadata and references to bitstreams (requires ORE support).</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_bs">Harvest metadata and bitstreams (requires ORE support).</message>
<message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.submit_test">Test Settings</message>
<!-- org.dspace.app.xmlui.administrative.collection.EditCollectionHarvestingForm.java -->
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.main_settings_head">Harvested Collection Location</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_oai_provider">OAI Provider</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_setid">OAI Set id</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_metadata_format">Metadata format</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_level">Content being harvested</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_result">Last Harvest Result</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_result_new">This collection has not yet been harvested.</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_status">Current harvest status</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_ready">Collection ready for harvest</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_busy">Collection is currently being harvested</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_queued">Collection is in queue for harvest</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_oai_error">OAI error occured during last harvest</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_unknown_error">Unexpected error occured during last harvest</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_only">Harvest metadata only.</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_ref">Harvest metadata and references to bitstreams.</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_bs">Harvest metadata and bitstreams (full replication).</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_change_settings">Change Settings</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_import_now">Import Now</message>
<message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_reimport_collection">Reset and Reimport Collection</message>
<message key="xmlui.administrative.ControlPanel.option_harvest">Harvesting</message>
<message key="xmlui.administrative.ControlPanel.harvest_scheduler_head">Harvest Scheduler Controls</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_status">Status</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_actions">Actions</message>
<message key="xmlui.administrative.ControlPanel.harvest_submit_start">Start Harvester</message>
<message key="xmlui.administrative.ControlPanel.harvest_submit_reset">Reset Harvest Status</message>
<message key="xmlui.administrative.ControlPanel.harvest_submit_resume">Resume</message>
<message key="xmlui.administrative.ControlPanel.harvest_submit_pause">Pause</message>
<message key="xmlui.administrative.ControlPanel.harvest_submit_stop">Stop</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_collections">Collections set up for harvesting</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_active">Active harvests</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_queued">Queued harvests</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_oai_errors">OAI errors</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_internal_errors">Internal errors</message>
<message key="xmlui.administrative.ControlPanel.harvest_head_generator_settings">Generator Settings</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_oai_url">OAI-PMH URL</message>
<message key="xmlui.administrative.ControlPanel.harvest_label_oai_source">ORE source</message>
<message key="xmlui.administrative.ControlPanel.harvest_head_harvester_settings">Harvester Settings</message>
<!-- General tags for community management --> <!-- General tags for community management -->
<message key="xmlui.administrative.community.general.community_trail">Communities</message> <message key="xmlui.administrative.community.general.community_trail">Communities</message>

View File

@@ -47,6 +47,7 @@
pool-max="16" src="org.apache.cocoon.generation.DirectoryGenerator"/> pool-max="16" src="org.apache.cocoon.generation.DirectoryGenerator"/>
<map:generator name="DSpaceFeedGenerator" src="org.dspace.app.xmlui.cocoon.DSpaceFeedGenerator"/> <map:generator name="DSpaceFeedGenerator" src="org.dspace.app.xmlui.cocoon.DSpaceFeedGenerator"/>
<map:generator name="DSpaceMETSGenerator" src="org.dspace.app.xmlui.cocoon.DSpaceMETSGenerator"/> <map:generator name="DSpaceMETSGenerator" src="org.dspace.app.xmlui.cocoon.DSpaceMETSGenerator"/>
<map:generator name="DSpaceOREGenerator" src="org.dspace.app.xmlui.cocoon.DSpaceOREGenerator"/>
<map:generator name="notifying" src="org.apache.cocoon.sitemap.NotifyingGenerator"/> <map:generator name="notifying" src="org.apache.cocoon.sitemap.NotifyingGenerator"/>
<map:generator name="exception" src="org.apache.cocoon.generation.ExceptionGenerator"/> <map:generator name="exception" src="org.apache.cocoon.generation.ExceptionGenerator"/>
</map:generators> </map:generators>
@@ -309,16 +310,30 @@
<map:match pattern="metadata/**"> <map:match pattern="metadata/**">
<map:match pattern="metadata/handle/*/*/**"> <map:match pattern="metadata/handle/*/*/mets.xml">
<map:generate type="DSpaceMETSGenerator"> <map:generate type="DSpaceMETSGenerator">
<map:parameter name="handle" value="{1}/{2}"/>
<!--<map:parameter name="extra" value="{3}"/>-->
</map:generate>
<map:serialize type="xml"/>
</map:match>
<map:match pattern="metadata/internal/*/*/mets.xml">
<map:generate type="DSpaceMETSGenerator">
<map:parameter name="internal" value="{1}:{2}"/>
<!--<map:parameter name="extra" value="{3}"/>-->
</map:generate>
<map:serialize type="xml"/>
</map:match>
<map:match pattern="metadata/handle/*/*/ore.xml**">
<map:generate type="DSpaceOREGenerator">
<map:parameter name="handle" value="{1}/{2}"/> <map:parameter name="handle" value="{1}/{2}"/>
<map:parameter name="extra" value="{3}"/> <map:parameter name="extra" value="{3}"/>
</map:generate> </map:generate>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<map:match pattern="metadata/internal/*/*/ore.xml**">
<map:match pattern="metadata/internal/*/*/**"> <map:generate type="DSpaceOREGenerator">
<map:generate type="DSpaceMETSGenerator">
<map:parameter name="internal" value="{1}:{2}"/> <map:parameter name="internal" value="{1}:{2}"/>
<map:parameter name="extra" value="{3}"/> <map:parameter name="extra" value="{3}"/>
</map:generate> </map:generate>

View File

@@ -53,6 +53,9 @@
xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" xmlns:dim="http://www.dspace.org/xmlns/dspace/dim"
xmlns:xlink="http://www.w3.org/TR/xlink/" xmlns:xlink="http://www.w3.org/TR/xlink/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:ore="http://www.openarchives.org/ore/terms/"
xmlns:oreatom="http://www.openarchives.org/ore/atom/"
xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"
xmlns:xalan="http://xml.apache.org/xalan" xmlns:xalan="http://xml.apache.org/xalan"
xmlns:encoder="xalan://java.net.URLEncoder" xmlns:encoder="xalan://java.net.URLEncoder"
@@ -394,28 +397,32 @@
<!-- Generate the bitstream information from the file section --> <!-- Generate the bitstream information from the file section -->
<xsl:choose> <xsl:choose>
<xsl:when test="not(./mets:fileSec/mets:fileGrp[@USE='CONTENT'])"> <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']">
<h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2> <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']">
<table class="ds-table file-list"> <xsl:with-param name="context" select="."/>
<tr class="ds-table-header-row"> <xsl:with-param name="primaryBitstream" select="./mets:structMap[@TYPE='LOGICAL']/mets:div[@TYPE='DSpace Item']/mets:fptr/@FILEID"/>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th> </xsl:apply-templates>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th> </xsl:when>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th> <!-- Special case for handling ORE resource maps stored as DSpace bitstreams -->
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th> <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='ORE']">
</tr> <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='ORE']"/>
<tr> </xsl:when>
<td colspan="4"> <xsl:otherwise>
<p><i18n:text>xmlui.dri2xhtml.METS-1.0.item-no-files</i18n:text></p> <h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2>
</td> <table class="ds-table file-list">
</tr> <tr class="ds-table-header-row">
</table> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th>
</xsl:when> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th>
<xsl:otherwise> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th>
<xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CONTENT']"> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th>
<xsl:with-param name="context" select="."/> </tr>
<xsl:with-param name="primaryBitstream" select="./mets:structMap[@TYPE='LOGICAL']/mets:div[@TYPE='DSpace Item']/mets:fptr/@FILEID"/> <tr>
</xsl:apply-templates> <td colspan="4">
</xsl:otherwise> <p><i18n:text>xmlui.dri2xhtml.METS-1.0.item-no-files</i18n:text></p>
</td>
</tr>
</table>
</xsl:otherwise>
</xsl:choose> </xsl:choose>
<!-- Generate the license information from the file section --> <!-- Generate the license information from the file section -->
@@ -633,28 +640,32 @@
<!-- Generate the bitstream information from the file section --> <!-- Generate the bitstream information from the file section -->
<xsl:choose> <xsl:choose>
<xsl:when test="not(./mets:fileSec/mets:fileGrp[@USE='CONTENT'])"> <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']">
<h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2> <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']">
<table class="ds-table file-list"> <xsl:with-param name="context" select="."/>
<tr class="ds-table-header-row"> <xsl:with-param name="primaryBitstream" select="./mets:structMap[@TYPE='LOGICAL']/mets:div[@TYPE='DSpace Item']/mets:fptr/@FILEID"/>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th> </xsl:apply-templates>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th> </xsl:when>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th> <!-- Special case for handling ORE resource maps stored as DSpace bitstreams -->
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th> <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='ORE']">
</tr> <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='ORE']"/>
<tr> </xsl:when>
<td colspan="4"> <xsl:otherwise>
<p><i18n:text>xmlui.dri2xhtml.METS-1.0.item-no-files</i18n:text></p> <h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2>
</td> <table class="ds-table file-list">
</tr> <tr class="ds-table-header-row">
</table> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th>
</xsl:when> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th>
<xsl:otherwise> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th>
<xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CONTENT']"> <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th>
<xsl:with-param name="context" select="."/> </tr>
<xsl:with-param name="primaryBitstream" select="./mets:structMap[@TYPE='LOGICAL']/mets:div[@TYPE='DSpace Item']/mets:fptr/@FILEID"/> <tr>
</xsl:apply-templates> <td colspan="4">
</xsl:otherwise> <p><i18n:text>xmlui.dri2xhtml.METS-1.0.item-no-files</i18n:text></p>
</td>
</tr>
</table>
</xsl:otherwise>
</xsl:choose> </xsl:choose>
@@ -749,8 +760,111 @@
<!-- Rendering the file list from an Atom ReM bitstream stored in the ORE bundle -->
<xsl:template match="mets:fileGrp[@USE='ORE']">
<xsl:variable name="AtomMapURL" select="concat('cocoon:/',substring-after(mets:file/mets:FLocat[@LOCTYPE='URL']//@*[local-name(.)='href'],$context-path))"/>
<h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2>
<table class="ds-table file-list">
<thead>
<tr class="ds-table-header-row">
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th>
<th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="document($AtomMapURL)/atom:entry/atom:link[@rel='http://www.openarchives.org/ore/terms/aggregates']">
<xsl:sort select="@title"/>
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<!-- Iterate over the links in the ORE resource maps and make them into bitstream references in the file section -->
<xsl:template match="atom:link[@rel='http://www.openarchives.org/ore/terms/aggregates']">
<tr>
<xsl:attribute name="class">
<xsl:text>ds-table-row </xsl:text>
<xsl:if test="(position() mod 2 = 0)">even </xsl:if>
<xsl:if test="(position() mod 2 = 1)">odd </xsl:if>
</xsl:attribute>
<td>
<a>
<xsl:attribute name="href">
<xsl:value-of select="@href"/>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:choose>
<xsl:when test="@title">
<xsl:value-of select="@title"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@href"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:choose>
<xsl:when test="string-length(@title) > 50">
<xsl:variable name="title_length" select="string-length(@title)"/>
<xsl:value-of select="substring(@title,1,15)"/>
<xsl:text> ... </xsl:text>
<xsl:value-of select="substring(@title,$title_length - 25,$title_length)"/>
</xsl:when>
<xsl:when test="@title">
<xsl:value-of select="@title"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@href"/>
</xsl:otherwise>
</xsl:choose>
</a>
</td>
<!-- File size always comes in bytes and thus needs conversion -->
<td>
<xsl:choose>
<xsl:when test="@length &lt; 1000">
<xsl:value-of select="@length"/>
<i18n:text>xmlui.dri2xhtml.METS-1.0.size-bytes</i18n:text>
</xsl:when>
<xsl:when test="@length &lt; 1000000">
<xsl:value-of select="substring(string(@length div 1000),1,5)"/>
<i18n:text>xmlui.dri2xhtml.METS-1.0.size-kilobytes</i18n:text>
</xsl:when>
<xsl:when test="@length &lt; 1000000001">
<xsl:value-of select="substring(string(@length div 1000000),1,5)"/>
<i18n:text>xmlui.dri2xhtml.METS-1.0.size-megabytes</i18n:text>
</xsl:when>
<xsl:when test="@length &gt; 1000000000">
<xsl:value-of select="substring(string(@length div 1000000000),1,5)"/>
<i18n:text>xmlui.dri2xhtml.METS-1.0.size-gigabytes</i18n:text>
</xsl:when>
<!-- When one isn't available -->
<xsl:otherwise><xsl:text>n/a</xsl:text></xsl:otherwise>
</xsl:choose>
</td>
<!-- Currently format carries forward the mime type. In the original DSpace, this
would get resolved to an application via the Bitstream Registry, but we are
constrained by the capabilities of METS and can't really pass that info through. -->
<td>
<xsl:value-of select="substring-before(@type,'/')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="substring-after(@type,'/')"/>
</td>
<td>
<a>
<xsl:attribute name="href">
<xsl:value-of select="@href"/>
</xsl:attribute>
<i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-viewOpen</i18n:text>
</a>
</td>
</tr>
</xsl:template>
<!-- A community rendered in the detailView pattern; default way of viewing a community. --> <!-- A community rendered in the detailView pattern; default way of viewing a community. -->
<xsl:template name="communityDetailView-DIM"> <xsl:template name="communityDetailView-DIM">
<div class="detail-view">&#160; <div class="detail-view">&#160;

View File

@@ -78,6 +78,12 @@
<version>1.0.0</version> <version>1.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>commons-jxpath</groupId>
<artifactId>commons-jxpath</artifactId>
<version>1.3</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -35,6 +35,9 @@ dspace.url = http://localhost:8080/jspui
# DSpace host name - should match base URL. Do not include port number # DSpace host name - should match base URL. Do not include port number
dspace.hostname = localhost dspace.hostname = localhost
# The base URL of the OAI webapp (do not include /request).
dspace.oai.url = ${dspace.hostname}/oai
# Name of the site # Name of the site
dspace.name = DSpace at My University dspace.name = DSpace at My University
@@ -650,7 +653,11 @@ mets.submission.useCollectionTemplate = false
# Crosswalk Plugins: # Crosswalk Plugins:
plugin.named.org.dspace.content.crosswalk.IngestionCrosswalk = \ plugin.named.org.dspace.content.crosswalk.IngestionCrosswalk = \
org.dspace.content.crosswalk.PREMISCrosswalk = PREMIS \ org.dspace.content.crosswalk.PREMISCrosswalk = PREMIS \
org.dspace.content.crosswalk.NullIngestionCrosswalk = NIL org.dspace.content.crosswalk.OREIngestionCrosswalk = ore \
org.dspace.content.crosswalk.NullIngestionCrosswalk = NIL \
org.dspace.content.crosswalk.QDCCrosswalk = qdc \
org.dspace.content.crosswalk.OAIDCIngestionCrosswalk = dc \
org.dspace.content.crosswalk.DIMIngestionCrosswalk = dim
plugin.selfnamed.org.dspace.content.crosswalk.IngestionCrosswalk = \ plugin.selfnamed.org.dspace.content.crosswalk.IngestionCrosswalk = \
org.dspace.content.crosswalk.XSLTIngestionCrosswalk org.dspace.content.crosswalk.XSLTIngestionCrosswalk
@@ -660,7 +667,11 @@ plugin.named.org.dspace.content.crosswalk.DisseminationCrosswalk = \
org.dspace.content.crosswalk.SimpleDCDisseminationCrosswalk = dc \ org.dspace.content.crosswalk.SimpleDCDisseminationCrosswalk = dc \
org.dspace.content.crosswalk.PREMISCrosswalk = PREMIS \ org.dspace.content.crosswalk.PREMISCrosswalk = PREMIS \
org.dspace.content.crosswalk.METSDisseminationCrosswalk = METS \ org.dspace.content.crosswalk.METSDisseminationCrosswalk = METS \
org.dspace.content.crosswalk.METSDisseminationCrosswalk = mets org.dspace.content.crosswalk.METSDisseminationCrosswalk = mets \
org.dspace.content.crosswalk.OREDisseminationCrosswalk = ore \
org.dspace.content.crosswalk.QDCCrosswalk = qdc \
org.dspace.content.crosswalk.DIMDisseminationCrosswalk = dim
plugin.selfnamed.org.dspace.content.crosswalk.DisseminationCrosswalk = \ plugin.selfnamed.org.dspace.content.crosswalk.DisseminationCrosswalk = \
org.dspace.content.crosswalk.MODSDisseminationCrosswalk , \ org.dspace.content.crosswalk.MODSDisseminationCrosswalk , \
@@ -681,7 +692,7 @@ plugin.named.org.dspace.content.packager.PackageIngester = \
# default synchronous dispatcher (same behavior as traditional DSpace) # default synchronous dispatcher (same behavior as traditional DSpace)
event.dispatcher.default.class = org.dspace.event.BasicDispatcher event.dispatcher.default.class = org.dspace.event.BasicDispatcher
event.dispatcher.default.consumers = search, browse, eperson event.dispatcher.default.consumers = search, browse, eperson, harvester
# The noindex dispatcher will not create search or browse indexs (usefull for batch item imports) # The noindex dispatcher will not create search or browse indexs (usefull for batch item imports)
event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher
@@ -699,6 +710,10 @@ event.consumer.browse.filters = Community|Collection|Item|Bundle+Add|Create|Modi
event.consumer.eperson.class = org.dspace.eperson.EPersonConsumer event.consumer.eperson.class = org.dspace.eperson.EPersonConsumer
event.consumer.eperson.filters = EPerson+Create event.consumer.eperson.filters = EPerson+Create
# consumer to clean up harvesting data
event.consumer.harvester.class = org.dspace.harvest.HarvestConsumer
event.consumer.harvester.filters = Item+Delete
# test consumer for debugging and monitoring # test consumer for debugging and monitoring
#event.consumer.test.class = org.dspace.event.TestConsumer #event.consumer.test.class = org.dspace.event.TestConsumer
#event.consumer.test.filters = All+All #event.consumer.test.filters = All+All
@@ -1688,3 +1703,48 @@ sword.on-behalf-of.enable = true
plugin.named.org.dspace.sword.SWORDIngester = \ plugin.named.org.dspace.sword.SWORDIngester = \
org.dspace.sword.SWORDMETSIngester = http://purl.org/net/sword-types/METSDSpaceSIP \ org.dspace.sword.SWORDMETSIngester = http://purl.org/net/sword-types/METSDSpaceSIP \
org.dspace.sword.SimpleFileIngester = SimpleFileIngester org.dspace.sword.SimpleFileIngester = SimpleFileIngester
#---------------------------------------------------------------#
#--------------OAI HARVESTING CONFIGURATIONS--------------------#
#---------------------------------------------------------------#
# These configs are only used by the OAI-ORE related functions #
#---------------------------------------------------------------#
### Harvester settings
# Crosswalk settings; the {name} value must correspond to a declated ingestion crosswalk
# harvester.oai.metadataformats.{name} = {namespace},{optional display name}
harvester.oai.metadataformats.dc = http://www.openarchives.org/OAI/2.0/oai_dc/, Simple Dublin Core
harvester.oai.metadataformats.qdc = http://purl.org/dc/terms/, Qualified Dublin Core
harvester.oai.metadataformats.dim = http://www.dspace.org/xmlns/dspace/dim, DSpace Intermediate Metadata
# Determines whether the harvester scheduling process should be started
# automatically when the DSpace webapp is deployed.
# default: false
harvester.autoStart=false
# How frequently the harvest scheduler checks the remote provider for updates,
# messured in minutes. The default vaule is 12 hours (or 720 minutes)
#harvester.harvestFrequency = 720
# How many harvest process threads the scheduler can spool up at once. Default value is 3.
#harvester.maxThreads = 3
# How much time passess before a harvest thread is terminated. The termination process
# waits for the current item to complete ingest and saves progress made up to that point.
# Measured in hours. Default value is 24.
#harvester.threadTimeout = 24
# When harvesting an item that contains an unknown schema or field within a schema what
# should the harvester do? Either add a new registry item for the field or schema, ignore
# the specific field or schema (importing everything else about the item), or fail with
# an error. The default value if undefined is: fail.
# Possible values: 'fail', 'add', or 'ignore'
harvester.unknownField = add
harvester.unknownSchema = fail

View File

@@ -0,0 +1,20 @@
# E-mail sent to designated address when a harvest process fails
#
# Parameters: {0} Collection id
# {1} Date & time
# {2} Status flag
# {3} Exception message
# {4} Exception stack trace
#
# See org.dspace.core.Email for information on the format of this file.
#
Subject: DSpace: Harvesting Error
Collection {0} failed on harvest:
Date: {1}
Status Flag: {2}
{3}
Exception:
{4}

View File

@@ -38,3 +38,4 @@ Crosswalks.rdf=org.dspace.app.oai.RDFCrosswalk
# Crosswalks.mods=org.dspace.app.oai.PluginCrosswalk # Crosswalks.mods=org.dspace.app.oai.PluginCrosswalk
# Crosswalks.mets=org.dspace.app.oai.PluginCrosswalk # Crosswalks.mets=org.dspace.app.oai.PluginCrosswalk
# Crosswalks.qdc=org.dspace.app.oai.PluginCrosswalk # Crosswalks.qdc=org.dspace.app.oai.PluginCrosswalk
# Crosswalks.dim=org.dspace.app.oai.PluginCrosswalk

View File

@@ -109,6 +109,8 @@ CREATE SEQUENCE metadatavalue_seq;
CREATE SEQUENCE group2group_seq; CREATE SEQUENCE group2group_seq;
CREATE SEQUENCE group2groupcache_seq; CREATE SEQUENCE group2groupcache_seq;
CREATE SEQUENCE harvested_collection_seq;
CREATE SEQUENCE harvested_item_seq;
------------------------------------------------------- -------------------------------------------------------
-- BitstreamFormatRegistry table -- BitstreamFormatRegistry table
@@ -739,4 +741,41 @@ values
-------------------------------------------------------
-- Create the harvest settings table
-------------------------------------------------------
-- Values used by the OAIHarvester to harvest a collection
-- HarvestInstance is the DAO class for this table
CREATE TABLE harvested_collection
(
collection_id INTEGER REFERENCES collection(collection_id) ON DELETE CASCADE,
harvest_type INTEGER,
oai_source VARCHAR,
oai_set_id VARCHAR,
harvest_message VARCHAR,
metadata_config_id VARCHAR,
harvest_status INTEGER,
harvest_start_time TIMESTAMP WITH TIME ZONE,
last_harvested TIMESTAMP WITH TIME ZONE,
id INTEGER PRIMARY KEY
);
CREATE INDEX harvested_collection_fk_idx ON harvested_collection(collection_id);
CREATE TABLE harvested_item
(
item_id INTEGER REFERENCES item(item_id) ON DELETE CASCADE,
last_harvested TIMESTAMP WITH TIME ZONE,
oai_id VARCHAR,
id INTEGER PRIMARY KEY
);
CREATE INDEX harvested_item_fk_idx ON harvested_item(item_id);

View File

@@ -494,6 +494,11 @@
<artifactId>ojdbc14</artifactId> <artifactId>ojdbc14</artifactId>
<version>10.2.0.2.0</version> <version>10.2.0.2.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>oclc-harvester2</artifactId>
<version>0.1.12</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>