mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-12 12:33:18 +00:00
Merging in DSpace Event Mechanism Branch
git-svn-id: http://scm.dspace.org/svn/repo/trunk@2074 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
@@ -258,6 +258,7 @@ public class ChecksumChecker
|
||||
checker.setDispatcher(dispatcher);
|
||||
checker.setCollector(logger);
|
||||
checker.process();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -170,6 +170,7 @@ public class ItemImport
|
||||
String mapfile = null;
|
||||
String eperson = null; // db ID or email
|
||||
String[] collections = null; // db ID or handles
|
||||
int status = 0;
|
||||
|
||||
if (line.hasOption('h'))
|
||||
{
|
||||
@@ -439,6 +440,7 @@ public class ItemImport
|
||||
c.abort();
|
||||
e.printStackTrace();
|
||||
System.out.println(e);
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (mapOut != null)
|
||||
@@ -450,6 +452,7 @@ public class ItemImport
|
||||
{
|
||||
System.out.println("***End of Test Run***");
|
||||
}
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
private void addItems(Context c, Collection[] mycollections,
|
||||
|
@@ -101,6 +101,8 @@ public class MediaFilterManager
|
||||
// create an options object and populate it
|
||||
CommandLineParser parser = new PosixParser();
|
||||
|
||||
int status = 0;
|
||||
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption("v", "verbose", false,
|
||||
@@ -217,6 +219,10 @@ public class MediaFilterManager
|
||||
c.complete();
|
||||
c = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (c != null)
|
||||
@@ -224,6 +230,7 @@ public class MediaFilterManager
|
||||
c.abort();
|
||||
}
|
||||
}
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
public static void applyFiltersAllItems(Context c) throws Exception
|
||||
|
@@ -215,6 +215,7 @@ public class METSExport
|
||||
}
|
||||
|
||||
context.abort();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -138,6 +138,7 @@ public class FixDefaultPolicies
|
||||
}
|
||||
|
||||
c.complete();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -99,6 +99,7 @@ public class PolicySet
|
||||
groupID, isReplace, false);
|
||||
|
||||
c.complete();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
162
dspace-api/src/main/java/org/dspace/browse/BrowseConsumer.java
Normal file
162
dspace-api/src/main/java/org/dspace/browse/BrowseConsumer.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* BrowseConsumer.java
|
||||
*
|
||||
* Version: $Revision: 1.4 $
|
||||
*
|
||||
* Date: $Date: 2006/04/10 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.
|
||||
*/
|
||||
|
||||
package org.dspace.browse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.dspace.browse.Browse;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.LogManager;
|
||||
|
||||
import org.dspace.event.Consumer;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.event.EventManager;
|
||||
|
||||
/**
|
||||
* Class for updating browse system from content events.
|
||||
* Prototype: only Item events recognized.
|
||||
*
|
||||
* XXX FIXME NOTE: The Browse Consumer is INCOMPLETE because the
|
||||
* deletion of an Item CANNOT be implemented as an event consumer:
|
||||
* When an Item is deleted, the browse tables must be updated
|
||||
* immediately, within the same transaction, to maintain referential
|
||||
* consistency. It cannot be handled in an Event consumer since by
|
||||
* definition that runs after the transaction is committed.
|
||||
* Perhaps this can be addressed if the Browse system is replaced.
|
||||
*
|
||||
* To handle create/modify events: accumulate Sets of Items to be added
|
||||
* and updated out of the event stream. Process them in endEvents()
|
||||
* filter out update requests for Items that were just created.
|
||||
*
|
||||
* Recommended filter: Item+Create|Modify|Modify_Metadata:Collection+Add|Remove
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public class BrowseConsumer implements Consumer
|
||||
{
|
||||
/** log4j logger */
|
||||
private static Logger log = Logger.getLogger(BrowseConsumer.class);
|
||||
|
||||
// items to be added to browse index
|
||||
private Set toAdd = null;
|
||||
|
||||
// items to be updated in browse index
|
||||
private Set toUpdate = null;
|
||||
|
||||
|
||||
public void initialize()
|
||||
throws Exception
|
||||
{
|
||||
toAdd = new HashSet();
|
||||
toUpdate = new HashSet();
|
||||
}
|
||||
|
||||
public void consume(Context ctx, Event event)
|
||||
throws Exception
|
||||
{
|
||||
DSpaceObject subj = event.getSubject(ctx);
|
||||
int et = event.getEventType();
|
||||
|
||||
// If an Item is added or modified..
|
||||
if (subj != null && subj.getType() == Constants.ITEM)
|
||||
{
|
||||
if (et == Event.CREATE)
|
||||
toAdd.add(subj);
|
||||
else
|
||||
toUpdate.add(subj);
|
||||
|
||||
// track ADD and REMOVE from collections, that changes browse index.
|
||||
} else if (subj != null && subj.getType() == Constants.COLLECTION &&
|
||||
event.getObjectType() == Constants.ITEM &&
|
||||
(et == Event.ADD || et == Event.REMOVE))
|
||||
{
|
||||
DSpaceObject obj = event.getObject(ctx);
|
||||
if (obj != null)
|
||||
toUpdate.add(obj);
|
||||
}
|
||||
else if (subj != null)
|
||||
log.warn("consume() got unrecognized event: "+event.toString());
|
||||
}
|
||||
|
||||
public void end(Context ctx)
|
||||
throws Exception
|
||||
{
|
||||
for (Iterator ai = toAdd.iterator(); ai.hasNext();)
|
||||
{
|
||||
Item i = (Item)ai.next();
|
||||
Browse.itemAdded(ctx, i);
|
||||
toUpdate.remove(i);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Added browse indices for Item id="+String.valueOf(i.getID())+", hdl="+i.getHandle());
|
||||
}
|
||||
|
||||
// don't update an item we've just added.
|
||||
for (Iterator ui = toUpdate.iterator(); ui.hasNext();)
|
||||
{
|
||||
Item i = (Item)ui.next();
|
||||
Browse.itemChanged(ctx, i);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Updated browse indices for Item id="+String.valueOf(i.getID())+", hdl="+i.getHandle());
|
||||
}
|
||||
|
||||
// NOTE: Removed items are necessarily handled inline (ugh).
|
||||
|
||||
// browse updates wrote to the DB, so we have to commit.
|
||||
ctx.getDBConnection().commit();
|
||||
|
||||
// clean out toAdd & toUpdate
|
||||
toAdd.clear();
|
||||
toUpdate.clear();
|
||||
}
|
||||
|
||||
public void finish(Context ctx) {
|
||||
|
||||
toAdd = toUpdate = null;
|
||||
return;
|
||||
}
|
||||
}
|
@@ -65,6 +65,7 @@ public class InitializeBrowse
|
||||
public static void main(String[] argv)
|
||||
{
|
||||
Context context = null;
|
||||
int status = 0;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -78,6 +79,7 @@ public class InitializeBrowse
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
status = 1;
|
||||
if (context != null)
|
||||
{
|
||||
context.abort();
|
||||
@@ -86,5 +88,9 @@ public class InitializeBrowse
|
||||
System.err.println("Error: Browse index NOT created");
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.exit(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
104
dspace-api/src/main/java/org/dspace/checker/CheckerConsumer.java
Normal file
104
dspace-api/src/main/java/org/dspace/checker/CheckerConsumer.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* CheckerConsumer.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.checker;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.event.Consumer;
|
||||
import org.dspace.event.Event;
|
||||
|
||||
/**
|
||||
* Class for removing Checker data for a Bitstreams based on deletion events.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class CheckerConsumer implements Consumer
|
||||
{
|
||||
/** log4j logger */
|
||||
private static Logger log = Logger.getLogger(CheckerConsumer.class);
|
||||
|
||||
private BitstreamInfoDAO bitstreamInfoDAO = new BitstreamInfoDAO();
|
||||
|
||||
/**
|
||||
* Initialize - allocate any resources required to operate.
|
||||
* Called at the start of ANY sequence of event consume() calls.
|
||||
*/
|
||||
public void initialize() throws Exception
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume an event
|
||||
*
|
||||
* @param ctx the execution context object
|
||||
*
|
||||
* @param event the content event
|
||||
*/
|
||||
public void consume(Context ctx, Event event) throws Exception
|
||||
{
|
||||
|
||||
if (event.getEventType() == Event.DELETE)
|
||||
{
|
||||
log.debug("Attempting to remove Checker Info");
|
||||
bitstreamInfoDAO.deleteBitstreamInfoWithHistory(event.getSubjectID());
|
||||
log.debug("Completed removing Checker Info");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal that there are no more events queued in this
|
||||
* event stream.
|
||||
*/
|
||||
public void end(Context ctx) throws Exception
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish - free any allocated resources.
|
||||
* Called when consumer is being released
|
||||
*/
|
||||
public void finish(Context ctx) throws Exception
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
@@ -52,6 +52,7 @@ import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.storage.bitstore.BitstreamStorageManager;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
@@ -81,6 +82,12 @@ public class Bitstream extends DSpaceObject
|
||||
/** The bitstream format corresponding to this bitstream */
|
||||
private BitstreamFormat bitstreamFormat;
|
||||
|
||||
/** Flag set when data is modified, for events */
|
||||
private boolean modified;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Private constructor for creating a Bitstream object based on the contents
|
||||
* of a DB table row.
|
||||
@@ -114,6 +121,9 @@ public class Bitstream extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("bitstream_id"));
|
||||
|
||||
modified = modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,6 +200,8 @@ public class Bitstream extends DSpaceObject
|
||||
Bitstream bitstream = find(context, bitstreamID);
|
||||
bitstream.setFormat(null);
|
||||
|
||||
context.addEvent(new Event(Event.CREATE, Constants.BITSTREAM, bitstreamID, null));
|
||||
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
@@ -223,6 +235,8 @@ public class Bitstream extends DSpaceObject
|
||||
Bitstream bitstream = find(context, bitstreamID);
|
||||
bitstream.setFormat(null);
|
||||
|
||||
context.addEvent(new Event(Event.CREATE, Constants.BITSTREAM, bitstreamID, "REGISTER"));
|
||||
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
@@ -261,6 +275,8 @@ public class Bitstream extends DSpaceObject
|
||||
public void setSequenceID(int sid)
|
||||
{
|
||||
bRow.setColumn("sequence_id", sid);
|
||||
modifiedMetadata = true;
|
||||
addDetails("SequenceID");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,6 +299,8 @@ public class Bitstream extends DSpaceObject
|
||||
public void setName(String n)
|
||||
{
|
||||
bRow.setColumn("name", n);
|
||||
modifiedMetadata = true;
|
||||
addDetails("Name");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,6 +324,8 @@ public class Bitstream extends DSpaceObject
|
||||
public void setSource(String n)
|
||||
{
|
||||
bRow.setColumn("source", n);
|
||||
modifiedMetadata = true;
|
||||
addDetails("Source");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,6 +348,8 @@ public class Bitstream extends DSpaceObject
|
||||
public void setDescription(String n)
|
||||
{
|
||||
bRow.setColumn("description", n);
|
||||
modifiedMetadata = true;
|
||||
addDetails("Description");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,6 +396,8 @@ public class Bitstream extends DSpaceObject
|
||||
// but we need to find the unknown format!
|
||||
setFormat(null);
|
||||
bRow.setColumn("user_format_description", desc);
|
||||
modifiedMetadata = true;
|
||||
addDetails("UserFormatDescription");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,6 +475,7 @@ public class Bitstream extends DSpaceObject
|
||||
|
||||
// Update the ID in the table row
|
||||
bRow.setColumn("bitstream_format_id", bitstreamFormat.getID());
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,6 +493,18 @@ public class Bitstream extends DSpaceObject
|
||||
log.info(LogManager.getHeader(bContext, "update_bitstream",
|
||||
"bitstream_id=" + getID()));
|
||||
|
||||
if (modified)
|
||||
{
|
||||
bContext.addEvent(new Event(Event.MODIFY, Constants.BITSTREAM, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
bContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.BITSTREAM, getID(), getDetails()));
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
DatabaseManager.update(bContext, bRow);
|
||||
}
|
||||
|
||||
@@ -490,6 +527,8 @@ public class Bitstream extends DSpaceObject
|
||||
log.info(LogManager.getHeader(bContext, "delete_bitstream",
|
||||
"bitstream_id=" + getID()));
|
||||
|
||||
bContext.addEvent(new Event(Event.DELETE, Constants.BITSTREAM, getID(), String.valueOf(getSequenceID())));
|
||||
|
||||
// Remove from cache
|
||||
bContext.removeCached(this, getID());
|
||||
|
||||
@@ -541,7 +580,7 @@ public class Bitstream extends DSpaceObject
|
||||
bRow.getIntColumn("bitstream_id"));
|
||||
|
||||
// Build a list of Bundle objects
|
||||
List bundles = new ArrayList();
|
||||
List<Bundle> bundles = new ArrayList<Bundle>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
|
@@ -53,6 +53,7 @@ import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -80,7 +81,13 @@ public class Bundle extends DSpaceObject
|
||||
private TableRow bundleRow;
|
||||
|
||||
/** The bitstreams in this bundle */
|
||||
private List bitstreams;
|
||||
private List<Bitstream> bitstreams;
|
||||
|
||||
/** Flag set when data is modified, for events */
|
||||
private boolean modified;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Construct a bundle object with the given table row
|
||||
@@ -94,7 +101,7 @@ public class Bundle extends DSpaceObject
|
||||
{
|
||||
ourContext = context;
|
||||
bundleRow = row;
|
||||
bitstreams = new ArrayList();
|
||||
bitstreams = new ArrayList<Bitstream>();
|
||||
|
||||
// Get bitstreams
|
||||
TableRowIterator tri = DatabaseManager.queryTable(
|
||||
@@ -126,6 +133,8 @@ public class Bundle extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("bundle_id"));
|
||||
|
||||
modified = modifiedMetadata = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,6 +201,8 @@ public class Bundle extends DSpaceObject
|
||||
log.info(LogManager.getHeader(context, "create_bundle", "bundle_id="
|
||||
+ row.getIntColumn("bundle_id")));
|
||||
|
||||
context.addEvent(new Event(Event.CREATE, Constants.BUNDLE, row.getIntColumn("bundle_id"), null));
|
||||
|
||||
return new Bundle(context, row);
|
||||
}
|
||||
|
||||
@@ -225,6 +236,7 @@ public class Bundle extends DSpaceObject
|
||||
public void setName(String name)
|
||||
{
|
||||
bundleRow.setColumn("name", name);
|
||||
modifiedMetadata = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,6 +258,7 @@ public class Bundle extends DSpaceObject
|
||||
public void setPrimaryBitstreamID(int bitstreamID)
|
||||
{
|
||||
bundleRow.setColumn("primary_bitstream_id", bitstreamID);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +322,7 @@ public class Bundle extends DSpaceObject
|
||||
*/
|
||||
public Item[] getItems() throws SQLException
|
||||
{
|
||||
List items = new ArrayList();
|
||||
List<Item> items = new ArrayList<Item>();
|
||||
|
||||
// Get items
|
||||
TableRowIterator tri = DatabaseManager.queryTable(
|
||||
@@ -421,6 +434,8 @@ public class Bundle extends DSpaceObject
|
||||
// Add the bitstream object
|
||||
bitstreams.add(b);
|
||||
|
||||
ourContext.addEvent(new Event(Event.ADD, Constants.BUNDLE, getID(), Constants.BITSTREAM, b.getID(), String.valueOf(b.getSequenceID())));
|
||||
|
||||
// copy authorization policies from bundle to bitstream
|
||||
// FIXME: multiple inclusion is affected by this...
|
||||
AuthorizeManager.inheritPolicies(ourContext, this, b);
|
||||
@@ -475,6 +490,8 @@ public class Bundle extends DSpaceObject
|
||||
}
|
||||
}
|
||||
|
||||
ourContext.addEvent(new Event(Event.REMOVE, Constants.BUNDLE, getID(), Constants.BITSTREAM, b.getID(), String.valueOf(b.getSequenceID())));
|
||||
|
||||
// Delete the mapping row
|
||||
DatabaseManager.updateQuery(ourContext,
|
||||
"DELETE FROM bundle2bitstream WHERE bundle_id= ? "+
|
||||
@@ -505,6 +522,17 @@ public class Bundle extends DSpaceObject
|
||||
log.info(LogManager.getHeader(ourContext, "update_bundle", "bundle_id="
|
||||
+ getID()));
|
||||
|
||||
if (modified)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.BUNDLE, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.BUNDLE, getID(), null));
|
||||
modifiedMetadata = false;
|
||||
}
|
||||
|
||||
DatabaseManager.update(ourContext, bundleRow);
|
||||
}
|
||||
|
||||
@@ -518,6 +546,8 @@ public class Bundle extends DSpaceObject
|
||||
log.info(LogManager.getHeader(ourContext, "delete_bundle", "bundle_id="
|
||||
+ getID()));
|
||||
|
||||
ourContext.addEvent(new Event(Event.DELETE, Constants.BUNDLE, getID(), getName()));
|
||||
|
||||
// Remove from cache
|
||||
ourContext.removeCached(this, getID());
|
||||
|
||||
|
@@ -41,7 +41,9 @@ package org.dspace.content;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.*;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
@@ -57,9 +59,8 @@ import org.dspace.core.Context;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.search.DSIndexer;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -99,6 +100,12 @@ public class Collection extends DSpaceObject
|
||||
/** Our Handle */
|
||||
private String handle;
|
||||
|
||||
/** Flag set when data is modified, for events */
|
||||
private boolean modified;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Groups corresponding to workflow steps - NOTE these start from one, so
|
||||
* workflowGroups[0] corresponds to workflow_step_1.
|
||||
@@ -162,6 +169,9 @@ public class Collection extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("collection_id"));
|
||||
|
||||
modified = modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,8 +260,7 @@ public class Collection extends DSpaceObject
|
||||
myPolicy.setGroup(anonymousGroup);
|
||||
myPolicy.update();
|
||||
|
||||
HistoryManager.saveHistory(context, c, HistoryManager.CREATE, context
|
||||
.getCurrentUser(), context.getExtraLogInfo());
|
||||
context.addEvent(new Event(Event.CREATE, Constants.COLLECTION, c.getID(), c.handle));
|
||||
|
||||
log.info(LogManager.getHeader(context, "create_collection",
|
||||
"collection_id=" + row.getIntColumn("collection_id"))
|
||||
@@ -275,7 +284,7 @@ public class Collection extends DSpaceObject
|
||||
TableRowIterator tri = DatabaseManager.queryTable(context, "collection",
|
||||
"SELECT * FROM collection ORDER BY name");
|
||||
|
||||
List collections = new ArrayList();
|
||||
List<Collection> collections = new ArrayList<Collection>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -350,8 +359,19 @@ public class Collection extends DSpaceObject
|
||||
return collectionRow.getIntColumn("collection_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.dspace.content.DSpaceObject#getHandle()
|
||||
*/
|
||||
public String getHandle()
|
||||
{
|
||||
if(handle == null) {
|
||||
try {
|
||||
handle = HandleManager.findHandle(this.ourContext, this);
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -397,6 +417,13 @@ public class Collection extends DSpaceObject
|
||||
}
|
||||
}
|
||||
collectionRow.setColumn(field, value);
|
||||
modifiedMetadata = true;
|
||||
addDetails(field);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return getMetadata("name");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,6 +496,7 @@ public class Collection extends DSpaceObject
|
||||
+ newLogo.getID()));
|
||||
}
|
||||
|
||||
modified = true;
|
||||
return logo;
|
||||
}
|
||||
|
||||
@@ -527,6 +555,7 @@ public class Collection extends DSpaceObject
|
||||
{
|
||||
collectionRow.setColumn("workflow_step_" + step, g.getID());
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -571,6 +600,7 @@ public class Collection extends DSpaceObject
|
||||
|
||||
AuthorizeManager.addPolicy(ourContext, this, Constants.ADD, submitters);
|
||||
|
||||
modified = true;
|
||||
return submitters;
|
||||
}
|
||||
|
||||
@@ -624,6 +654,7 @@ public class Collection extends DSpaceObject
|
||||
admins);
|
||||
}
|
||||
|
||||
modified = true;
|
||||
return admins;
|
||||
}
|
||||
|
||||
@@ -704,6 +735,7 @@ public class Collection extends DSpaceObject
|
||||
{
|
||||
collectionRow.setColumn("license", license);
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -742,6 +774,7 @@ public class Collection extends DSpaceObject
|
||||
"collection_id=" + getID() + ",template_item_id="
|
||||
+ template.getID()));
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,6 +806,7 @@ public class Collection extends DSpaceObject
|
||||
template.delete();
|
||||
template = null;
|
||||
}
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), "remove_template_item"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -801,6 +835,8 @@ public class Collection extends DSpaceObject
|
||||
row.setColumn("item_id", item.getID());
|
||||
|
||||
DatabaseManager.update(ourContext, row);
|
||||
|
||||
ourContext.addEvent(new Event(Event.ADD, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -826,6 +862,8 @@ public class Collection extends DSpaceObject
|
||||
"AND item_id= ? ",
|
||||
getID(), item.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.REMOVE, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle()));
|
||||
|
||||
// Is the item an orphan?
|
||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||
"SELECT * FROM collection2item WHERE item_id= ? ",
|
||||
@@ -864,17 +902,22 @@ public class Collection extends DSpaceObject
|
||||
// Check authorisation
|
||||
canEdit();
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "update_collection",
|
||||
"collection_id=" + getID()));
|
||||
|
||||
DatabaseManager.update(ourContext, collectionRow);
|
||||
|
||||
// reindex this collection (could be smarter, to only do when name
|
||||
// changes)
|
||||
DSIndexer.reIndexContent(ourContext, this);
|
||||
if (modified)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.COLLECTION, getID(), getDetails()));
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canEditBoolean() throws java.sql.SQLException
|
||||
@@ -928,15 +971,11 @@ public class Collection extends DSpaceObject
|
||||
log.info(LogManager.getHeader(ourContext, "delete_collection",
|
||||
"collection_id=" + getID()));
|
||||
|
||||
// remove from index
|
||||
DSIndexer.unIndexContent(ourContext, this);
|
||||
ourContext.addEvent(new Event(Event.DELETE, Constants.COLLECTION, getID(), getHandle()));
|
||||
|
||||
// Remove from cache
|
||||
ourContext.removeCached(this, getID());
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
// remove subscriptions - hmm, should this be in Subscription.java?
|
||||
DatabaseManager.updateQuery(ourContext,
|
||||
"DELETE FROM subscription WHERE collection_id= ? ",
|
||||
@@ -1062,7 +1101,7 @@ public class Collection extends DSpaceObject
|
||||
getID());
|
||||
|
||||
// Build a list of Community objects
|
||||
List communities = new ArrayList();
|
||||
List<Community> communities = new ArrayList<Community>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -1162,7 +1201,7 @@ public class Collection extends DSpaceObject
|
||||
public static Collection[] findAuthorized(Context context, Community comm,
|
||||
int actionID) throws java.sql.SQLException
|
||||
{
|
||||
List myResults = new ArrayList();
|
||||
List<Collection> myResults = new ArrayList<Collection>();
|
||||
|
||||
Collection[] myCollections = null;
|
||||
|
||||
|
@@ -55,9 +55,8 @@ import org.dspace.core.Context;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.search.DSIndexer;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -89,6 +88,12 @@ public class Community extends DSpaceObject
|
||||
/** Handle, if any */
|
||||
private String handle;
|
||||
|
||||
/** Flag set when data is modified, for events */
|
||||
private boolean modified;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Construct a community object from a database row.
|
||||
*
|
||||
@@ -118,6 +123,9 @@ public class Community extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("community_id"));
|
||||
|
||||
modified = modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,8 +206,11 @@ public class Community extends DSpaceObject
|
||||
myPolicy.setGroup(anonymousGroup);
|
||||
myPolicy.update();
|
||||
|
||||
HistoryManager.saveHistory(context, c, HistoryManager.CREATE, context
|
||||
.getCurrentUser(), context.getExtraLogInfo());
|
||||
context.addEvent(new Event(Event.CREATE, Constants.COMMUNITY, c.getID(), c.handle));
|
||||
|
||||
// if creating a top-level Community, simulate an ADD event at the Site.
|
||||
if (parent == null)
|
||||
context.addEvent(new Event(Event.ADD, Constants.SITE, Site.SITE_ID, Constants.COMMUNITY, c.getID(), c.handle));
|
||||
|
||||
log.info(LogManager.getHeader(context, "create_community",
|
||||
"community_id=" + row.getIntColumn("community_id"))
|
||||
@@ -222,7 +233,7 @@ public class Community extends DSpaceObject
|
||||
TableRowIterator tri = DatabaseManager.queryTable(context, "community",
|
||||
"SELECT * FROM community ORDER BY name");
|
||||
|
||||
List communities = new ArrayList();
|
||||
List<Community> communities = new ArrayList<Community>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -268,7 +279,7 @@ public class Community extends DSpaceObject
|
||||
+ "(SELECT child_comm_id FROM community2community) "
|
||||
+ "ORDER BY name");
|
||||
|
||||
List topCommunities = new ArrayList();
|
||||
List<Community> topCommunities = new ArrayList<Community>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -306,8 +317,19 @@ public class Community extends DSpaceObject
|
||||
return communityRow.getIntColumn("community_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.dspace.content.DSpaceObject#getHandle()
|
||||
*/
|
||||
public String getHandle()
|
||||
{
|
||||
if(handle == null) {
|
||||
try {
|
||||
handle = HandleManager.findHandle(this.ourContext, this);
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -353,6 +375,13 @@ public class Community extends DSpaceObject
|
||||
}
|
||||
}
|
||||
communityRow.setColumn(field, value);
|
||||
modifiedMetadata = true;
|
||||
addDetails(field);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return getMetadata("name");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,6 +447,7 @@ public class Community extends DSpaceObject
|
||||
+ newLogo.getID()));
|
||||
}
|
||||
|
||||
modified = true;
|
||||
return logo;
|
||||
}
|
||||
|
||||
@@ -429,16 +459,22 @@ public class Community extends DSpaceObject
|
||||
// Check authorisation
|
||||
canEdit();
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "update_community",
|
||||
"community_id=" + getID()));
|
||||
|
||||
DatabaseManager.update(ourContext, communityRow);
|
||||
|
||||
// now re-index this Community
|
||||
DSIndexer.reIndexContent(ourContext, this);
|
||||
if (modified)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.COMMUNITY, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.COMMUNITY, getID(), getDetails()));
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,7 +485,7 @@ public class Community extends DSpaceObject
|
||||
*/
|
||||
public Collection[] getCollections() throws SQLException
|
||||
{
|
||||
List collections = new ArrayList();
|
||||
List<Collection> collections = new ArrayList<Collection>();
|
||||
|
||||
// Get the table rows
|
||||
TableRowIterator tri = DatabaseManager.queryTable(
|
||||
@@ -496,7 +532,7 @@ public class Community extends DSpaceObject
|
||||
*/
|
||||
public Community[] getSubcommunities() throws SQLException
|
||||
{
|
||||
List subcommunities = new ArrayList();
|
||||
List<Community> subcommunities = new ArrayList<Community>();
|
||||
|
||||
// Get the table rows
|
||||
TableRowIterator tri = DatabaseManager.queryTable(
|
||||
@@ -585,7 +621,7 @@ public class Community extends DSpaceObject
|
||||
*/
|
||||
public Community[] getAllParents() throws SQLException
|
||||
{
|
||||
List parentList = new ArrayList();
|
||||
List<Community> parentList = new ArrayList<Community>();
|
||||
Community parent = getParentCommunity();
|
||||
|
||||
while (parent != null)
|
||||
@@ -649,6 +685,8 @@ public class Community extends DSpaceObject
|
||||
mappingRow.setColumn("community_id", getID());
|
||||
mappingRow.setColumn("collection_id", c.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.ADD, Constants.COMMUNITY, getID(), Constants.COLLECTION, c.getID(), c.getHandle()));
|
||||
|
||||
DatabaseManager.update(ourContext, mappingRow);
|
||||
}
|
||||
// close the TableRowIterator to free up resources
|
||||
@@ -702,6 +740,8 @@ public class Community extends DSpaceObject
|
||||
mappingRow.setColumn("parent_comm_id", getID());
|
||||
mappingRow.setColumn("child_comm_id", c.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.ADD, Constants.COMMUNITY, getID(), Constants.COMMUNITY, c.getID(), c.getHandle()));
|
||||
|
||||
DatabaseManager.update(ourContext, mappingRow);
|
||||
}
|
||||
// close the TableRowIterator to free up resources
|
||||
@@ -728,6 +768,8 @@ public class Community extends DSpaceObject
|
||||
"DELETE FROM community2collection WHERE community_id= ? "+
|
||||
"AND collection_id= ? ", getID(), c.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.REMOVE, Constants.COMMUNITY, getID(), Constants.COLLECTION, c.getID(), c.getHandle()));
|
||||
|
||||
// Is the community an orphan?
|
||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||
"SELECT * FROM community2collection WHERE collection_id= ? ",
|
||||
@@ -774,6 +816,8 @@ public class Community extends DSpaceObject
|
||||
"DELETE FROM community2community WHERE parent_comm_id= ? " +
|
||||
" AND child_comm_id= ? ", getID(),c.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.REMOVE, Constants.COMMUNITY, getID(), Constants.COMMUNITY, c.getID(), c.getHandle()));
|
||||
|
||||
// Is the subcommunity an orphan?
|
||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||
"SELECT * FROM community2community WHERE child_comm_id= ? ",
|
||||
@@ -834,11 +878,7 @@ public class Community extends DSpaceObject
|
||||
log.info(LogManager.getHeader(ourContext, "delete_community",
|
||||
"community_id=" + getID()));
|
||||
|
||||
// remove from the search index
|
||||
DSIndexer.unIndexContent(ourContext, this);
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
ourContext.addEvent(new Event(Event.DELETE, Constants.COMMUNITY, getID(), getHandle()));
|
||||
|
||||
// Remove from cache
|
||||
ourContext.removeCached(this, getID());
|
||||
|
@@ -39,11 +39,53 @@
|
||||
*/
|
||||
package org.dspace.content;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
|
||||
/**
|
||||
* Abstract base class for DSpace objects
|
||||
*/
|
||||
public abstract class DSpaceObject
|
||||
{
|
||||
// accumulate information to add to "detail" element of content Event,
|
||||
// e.g. to document metadata fields touched, etc.
|
||||
private StringBuffer eventDetails = null;
|
||||
|
||||
/**
|
||||
* Reset the cache of event details.
|
||||
*/
|
||||
protected void clearDetails()
|
||||
{
|
||||
eventDetails = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a string to the cache of event details. Automatically
|
||||
* separates entries with a comma.
|
||||
* Subclass can just start calling addDetails, since it creates
|
||||
* the cache if it needs to.
|
||||
* @param detail detail string to add.
|
||||
*/
|
||||
protected void addDetails(String d)
|
||||
{
|
||||
if (eventDetails == null)
|
||||
eventDetails = new StringBuffer(d);
|
||||
else
|
||||
eventDetails.append(", ").append(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns summary of event details, or null if there are none.
|
||||
*/
|
||||
protected String getDetails()
|
||||
{
|
||||
return (eventDetails == null ? null : eventDetails.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this object, found in Constants
|
||||
*
|
||||
@@ -65,4 +107,40 @@ public abstract class DSpaceObject
|
||||
* one
|
||||
*/
|
||||
public abstract String getHandle();
|
||||
|
||||
/**
|
||||
* Get a proper name for the object. This may return <code>null</code>.
|
||||
* Name should be suitable for display in a user interface.
|
||||
*
|
||||
* @return Name for the object, or <code>null</code> if it doesn't have
|
||||
* one
|
||||
*/
|
||||
abstract public String getName();
|
||||
|
||||
/**
|
||||
* Generic find for when the precise type of a DSO is not known, just the
|
||||
* a pair of type number and database ID.
|
||||
*
|
||||
* @param context - the context
|
||||
* @param type - type number
|
||||
* @param id - id within table of type'd objects
|
||||
* @return the object found, or null if it does not exist.
|
||||
* @throws SQLException only upon failure accessing the database.
|
||||
*/
|
||||
public static DSpaceObject find(Context context, int type, int id)
|
||||
throws SQLException
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Constants.BITSTREAM : return Bitstream.find(context, id);
|
||||
case Constants.BUNDLE : return Bundle.find(context, id);
|
||||
case Constants.ITEM : return Item.find(context, id);
|
||||
case Constants.COLLECTION: return Collection.find(context, id);
|
||||
case Constants.COMMUNITY : return Community.find(context, id);
|
||||
case Constants.GROUP : return Group.find(context, id);
|
||||
case Constants.EPERSON : return EPerson.find(context, id);
|
||||
case Constants.SITE : return Site.find(context, id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -46,7 +46,6 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.search.DSIndexer;
|
||||
|
||||
/**
|
||||
* Support to install item in the archive
|
||||
@@ -145,9 +144,6 @@ public class InstallItem
|
||||
// save changes ;-)
|
||||
item.update();
|
||||
|
||||
// add item to search and browse indices
|
||||
DSIndexer.indexContent(c, item);
|
||||
|
||||
// remove in-progress submission
|
||||
is.deleteWrapper();
|
||||
|
||||
|
@@ -61,11 +61,10 @@ import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.search.DSIndexer;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -104,10 +103,10 @@ public class Item extends DSpaceObject
|
||||
private EPerson submitter;
|
||||
|
||||
/** The bundles in this item - kept in sync with DB */
|
||||
private List bundles;
|
||||
private List<Bundle> bundles;
|
||||
|
||||
/** The Dublin Core metadata - a list of DCValue objects. */
|
||||
private List dublinCore;
|
||||
private List<DCValue> dublinCore;
|
||||
|
||||
/** Handle, if any */
|
||||
private String handle;
|
||||
@@ -118,6 +117,12 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
private boolean dublinCoreChanged;
|
||||
|
||||
/**
|
||||
* True if anything else was changed since last update()
|
||||
* (to drive event mechanism)
|
||||
*/
|
||||
private boolean modified;
|
||||
|
||||
/**
|
||||
* Construct an item with the given table row
|
||||
*
|
||||
@@ -132,7 +137,9 @@ public class Item extends DSpaceObject
|
||||
ourContext = context;
|
||||
itemRow = row;
|
||||
dublinCoreChanged = false;
|
||||
dublinCore = new ArrayList();
|
||||
modified = false;
|
||||
dublinCore = new ArrayList<DCValue>();
|
||||
clearDetails();
|
||||
|
||||
// Get Dublin Core metadata
|
||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "MetadataValue",
|
||||
@@ -247,8 +254,7 @@ public class Item extends DSpaceObject
|
||||
i.update();
|
||||
context.setIgnoreAuthorization(false);
|
||||
|
||||
HistoryManager.saveHistory(context, i, HistoryManager.CREATE, context
|
||||
.getCurrentUser(), context.getExtraLogInfo());
|
||||
context.addEvent(new Event(Event.CREATE, Constants.ITEM, i.getID(), null));
|
||||
|
||||
log.info(LogManager.getHeader(context, "create_item", "item_id="
|
||||
+ row.getIntColumn("item_id")));
|
||||
@@ -312,6 +318,14 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
public String getHandle()
|
||||
{
|
||||
if(handle == null) {
|
||||
try {
|
||||
handle = HandleManager.findHandle(this.ourContext, this);
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -364,6 +378,7 @@ public class Item extends DSpaceObject
|
||||
public void setArchived(boolean isArchived)
|
||||
{
|
||||
itemRow.setColumn("in_archive", isArchived);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,6 +390,7 @@ public class Item extends DSpaceObject
|
||||
public void setOwningCollection(Collection c)
|
||||
{
|
||||
itemRow.setColumn("owning_collection", c.getID());
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -493,13 +509,9 @@ public class Item extends DSpaceObject
|
||||
String lang)
|
||||
{
|
||||
// Build up list of matching values
|
||||
List values = new ArrayList();
|
||||
Iterator i = dublinCore.iterator();
|
||||
|
||||
while (i.hasNext())
|
||||
List<DCValue> values = new ArrayList<DCValue>();
|
||||
for (DCValue dcv : dublinCore)
|
||||
{
|
||||
DCValue dcv = (DCValue) i.next();
|
||||
|
||||
if (match(schema, element, qualifier, lang, dcv))
|
||||
{
|
||||
// We will return a copy of the object in case it is altered
|
||||
@@ -661,6 +673,8 @@ public class Item extends DSpaceObject
|
||||
dcv.value = null;
|
||||
}
|
||||
dublinCore.add(dcv);
|
||||
addDetails(schema+"."+element+((qualifier==null)? "": "."+qualifier));
|
||||
|
||||
}
|
||||
|
||||
if (values.length > 0)
|
||||
@@ -752,13 +766,9 @@ public class Item extends DSpaceObject
|
||||
String lang)
|
||||
{
|
||||
// We will build a list of values NOT matching the values to clear
|
||||
List values = new ArrayList();
|
||||
Iterator i = dublinCore.iterator();
|
||||
|
||||
while (i.hasNext())
|
||||
List<DCValue> values = new ArrayList<DCValue>();
|
||||
for (DCValue dcv : dublinCore)
|
||||
{
|
||||
DCValue dcv = (DCValue) i.next();
|
||||
|
||||
if (!match(schema, element, qualifier, lang, dcv))
|
||||
{
|
||||
values.add(dcv);
|
||||
@@ -885,6 +895,7 @@ public class Item extends DSpaceObject
|
||||
{
|
||||
itemRow.setColumnNull("submitter_id");
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -895,7 +906,7 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
public Collection[] getCollections() throws SQLException
|
||||
{
|
||||
List collections = new ArrayList();
|
||||
List<Collection> collections = new ArrayList<Collection>();
|
||||
|
||||
// Get collection table rows
|
||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"collection",
|
||||
@@ -940,7 +951,7 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
public Community[] getCommunities() throws SQLException
|
||||
{
|
||||
List communities = new ArrayList();
|
||||
List<Community> communities = new ArrayList<Community>();
|
||||
|
||||
// Get community table rows
|
||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"community",
|
||||
@@ -990,7 +1001,7 @@ public class Item extends DSpaceObject
|
||||
{
|
||||
if (bundles == null)
|
||||
{
|
||||
bundles = new ArrayList();
|
||||
bundles = new ArrayList<Bundle>();
|
||||
// Get bundles
|
||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "bundle",
|
||||
"SELECT bundle.* FROM bundle, item2bundle WHERE " +
|
||||
@@ -1035,7 +1046,7 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
public Bundle[] getBundles(String name) throws SQLException
|
||||
{
|
||||
List matchingBundles = new ArrayList();
|
||||
List<Bundle> matchingBundles = new ArrayList<Bundle>();
|
||||
|
||||
// now only keep bundles with matching names
|
||||
Bundle[] bunds = getBundles();
|
||||
@@ -1121,6 +1132,8 @@ public class Item extends DSpaceObject
|
||||
mappingRow.setColumn("item_id", getID());
|
||||
mappingRow.setColumn("bundle_id", b.getID());
|
||||
DatabaseManager.update(ourContext, mappingRow);
|
||||
|
||||
ourContext.addEvent(new Event(Event.ADD, Constants.ITEM, getID(), Constants.BUNDLE, b.getID(), b.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1161,6 +1174,8 @@ public class Item extends DSpaceObject
|
||||
"AND bundle_id= ? ",
|
||||
getID(), b.getID());
|
||||
|
||||
ourContext.addEvent(new Event(Event.REMOVE, Constants.ITEM, getID(), Constants.BUNDLE, b.getID(), b.getName()));
|
||||
|
||||
// If the bundle is orphaned, it's removed
|
||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||
"SELECT * FROM item2bundle WHERE bundle_id= ? ",
|
||||
@@ -1238,7 +1253,7 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
public Bitstream[] getNonInternalBitstreams() throws SQLException
|
||||
{
|
||||
List bitstreamList = new ArrayList();
|
||||
List<Bitstream> bitstreamList = new ArrayList<Bitstream>();
|
||||
|
||||
// Go through the bundles and bitstreams picking out ones which aren't
|
||||
// of internal formats
|
||||
@@ -1359,9 +1374,6 @@ public class Item extends DSpaceObject
|
||||
AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
|
||||
}
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "update_item", "item_id="
|
||||
+ getID()));
|
||||
|
||||
@@ -1419,7 +1431,7 @@ public class Item extends DSpaceObject
|
||||
// Keys are Strings: "element" or "element.qualifier"
|
||||
// Values are Integers indicating number of values written for a
|
||||
// element/qualifier
|
||||
Map elementCount = new HashMap();
|
||||
Map<String,Integer> elementCount = new HashMap<String,Integer>();
|
||||
|
||||
DatabaseManager.update(ourContext, itemRow);
|
||||
|
||||
@@ -1430,12 +1442,8 @@ public class Item extends DSpaceObject
|
||||
removeMetadataFromDatabase();
|
||||
|
||||
// Add in-memory DC
|
||||
Iterator i = dublinCore.iterator();
|
||||
|
||||
while (i.hasNext())
|
||||
for (DCValue dcv : dublinCore)
|
||||
{
|
||||
DCValue dcv = (DCValue) i.next();
|
||||
|
||||
// Get the DC Type
|
||||
int schemaID;
|
||||
MetadataSchema schema = MetadataSchema.find(ourContext,dcv.schema);
|
||||
@@ -1497,11 +1505,16 @@ public class Item extends DSpaceObject
|
||||
metadata.create(ourContext);
|
||||
}
|
||||
|
||||
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.ITEM, getID(), getDetails()));
|
||||
dublinCoreChanged = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
// Update browse indices
|
||||
Browse.itemChanged(ourContext, this);
|
||||
if (modified)
|
||||
{
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1560,13 +1573,7 @@ public class Item extends DSpaceObject
|
||||
// Update item in DB
|
||||
update();
|
||||
|
||||
// Invoke History system
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY, e,
|
||||
ourContext.getExtraLogInfo());
|
||||
|
||||
// Remove from indicies
|
||||
Browse.itemRemoved(ourContext, getID());
|
||||
DSIndexer.unIndexContent(ourContext, this);
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), "WITHDRAW"));
|
||||
|
||||
// and all of our authorization policies
|
||||
// FIXME: not very "multiple-inclusion" friendly
|
||||
@@ -1621,14 +1628,7 @@ public class Item extends DSpaceObject
|
||||
// Update item in DB
|
||||
update();
|
||||
|
||||
// Invoke History system
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY, e,
|
||||
ourContext.getExtraLogInfo());
|
||||
|
||||
// Add to indicies
|
||||
// Remove - update() already performs this
|
||||
// Browse.itemAdded(ourContext, this);
|
||||
DSIndexer.indexContent(ourContext, this);
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), "REINSTATE"));
|
||||
|
||||
// authorization policies
|
||||
if (colls.length > 0)
|
||||
@@ -1656,8 +1656,7 @@ public class Item extends DSpaceObject
|
||||
*/
|
||||
void delete() throws SQLException, AuthorizeException, IOException
|
||||
{
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
ourContext.addEvent(new Event(Event.DELETE, Constants.ITEM, getID(), getHandle()));
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "delete_item", "item_id="
|
||||
+ getID()));
|
||||
@@ -1665,12 +1664,19 @@ public class Item extends DSpaceObject
|
||||
// Remove from cache
|
||||
ourContext.removeCached(this, getID());
|
||||
|
||||
// Remove from indices, if appropriate
|
||||
// Remove from browse indices, if appropriate
|
||||
/** XXX FIXME
|
||||
** Although all other Browse index updates are managed through
|
||||
** Event consumers, removing an Item *must* be done *here* (inline)
|
||||
** because otherwise, tables are left in an inconsistent state
|
||||
** and the DB transaction will fail.
|
||||
** Any fix would involve too much work on Browse code that
|
||||
** is likely to be replaced soon anyway. --lcs, Aug 2006
|
||||
**/
|
||||
if (isArchived())
|
||||
{
|
||||
// Remove from Browse indices
|
||||
Browse.itemRemoved(ourContext, getID());
|
||||
DSIndexer.unIndexContent(ourContext, this);
|
||||
}
|
||||
|
||||
// Delete the Dublin Core
|
||||
@@ -1687,15 +1693,6 @@ public class Item extends DSpaceObject
|
||||
// remove all of our authorization policies
|
||||
AuthorizeManager.removeAllPolicies(ourContext, this);
|
||||
|
||||
// Remove any Handle
|
||||
// FIXME: This is sort of a "tentacle" - HandleManager should provide
|
||||
// a way of doing this. Plus, deleting a Handle may have ramifications
|
||||
// that need considering.
|
||||
DatabaseManager.updateQuery(ourContext,
|
||||
"DELETE FROM handle WHERE resource_type_id= ? " +
|
||||
"AND resource_id= ? ",
|
||||
Constants.ITEM,getID());
|
||||
|
||||
// Finally remove item row
|
||||
DatabaseManager.delete(ourContext, itemRow);
|
||||
}
|
||||
@@ -1982,4 +1979,9 @@ public class Item extends DSpaceObject
|
||||
|
||||
return false;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
DCValue t[] = getMetadata("dc", "title", null, Item.ANY);
|
||||
return (t.length >= 1) ? t[0].value : null;
|
||||
}
|
||||
}
|
||||
|
141
dspace-api/src/main/java/org/dspace/content/Site.java
Normal file
141
dspace-api/src/main/java/org/dspace/content/Site.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Site.java
|
||||
*
|
||||
* Version: $Revision: 1.8 $
|
||||
*
|
||||
* Date: $Date: 2005/04/20 14:22:34 $
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.net.URI;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
|
||||
/**
|
||||
* Represents the root of the DSpace Archive.
|
||||
* By default, the handle suffix "0" represents the Site, e.g. "1721.1/0"
|
||||
*/
|
||||
public class Site extends DSpaceObject
|
||||
{
|
||||
/** "database" identifier of the site */
|
||||
public static final int SITE_ID = 0;
|
||||
|
||||
// cache for Handle that is persistent ID for entire site.
|
||||
private static String handle = null;
|
||||
|
||||
private static Site theSite = null;
|
||||
|
||||
/**
|
||||
* Get the type of this object, found in Constants
|
||||
*
|
||||
* @return type of the object
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return Constants.SITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal ID (database primary key) of this object
|
||||
*
|
||||
* @return internal ID of object
|
||||
*/
|
||||
public int getID()
|
||||
{
|
||||
return SITE_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Handle of the object. This may return <code>null</code>
|
||||
*
|
||||
* @return Handle of the object, or <code>null</code> if it doesn't have
|
||||
* one
|
||||
*/
|
||||
public String getHandle()
|
||||
{
|
||||
return getSiteHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to return site Handle without creating a Site.
|
||||
* @returns handle of the Site.
|
||||
*/
|
||||
public static String getSiteHandle()
|
||||
{
|
||||
if (handle == null)
|
||||
handle = ConfigurationManager.getProperty("handle.prefix")+"/"+
|
||||
String.valueOf(SITE_ID);
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Site object corresponding to db id (which is ignroed).
|
||||
* @param context the context.
|
||||
* @param id integer database id, ignored.
|
||||
* @returns Site object.
|
||||
*/
|
||||
public static DSpaceObject find(Context context, int id)
|
||||
throws SQLException
|
||||
{
|
||||
if (theSite == null)
|
||||
theSite = new Site();
|
||||
return theSite;
|
||||
}
|
||||
|
||||
void delete()
|
||||
throws SQLException, AuthorizeException, IOException
|
||||
{
|
||||
}
|
||||
|
||||
public void update()
|
||||
throws SQLException, AuthorizeException, IOException
|
||||
{
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return ConfigurationManager.getProperty("dspace.name");
|
||||
}
|
||||
}
|
@@ -52,7 +52,6 @@ import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -286,9 +285,6 @@ public class WorkspaceItem implements InProgressSubmission
|
||||
|
||||
WorkspaceItem wi = new WorkspaceItem(c, row);
|
||||
|
||||
HistoryManager.saveHistory(c, wi, HistoryManager.CREATE, c
|
||||
.getCurrentUser(), c.getExtraLogInfo());
|
||||
|
||||
return wi;
|
||||
}
|
||||
|
||||
@@ -463,8 +459,6 @@ public class WorkspaceItem implements InProgressSubmission
|
||||
public void update() throws SQLException, AuthorizeException, IOException
|
||||
{
|
||||
// Authorisation is checked by the item.update() method below
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "update_workspace_item",
|
||||
"workspace_item_id=" + getID()));
|
||||
@@ -499,9 +493,6 @@ public class WorkspaceItem implements InProgressSubmission
|
||||
+ "original submitter to delete a workspace item");
|
||||
}
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
|
||||
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
||||
+ "collection_id=" + collection.getID()));
|
||||
@@ -536,9 +527,6 @@ public class WorkspaceItem implements InProgressSubmission
|
||||
// Check authorisation. We check permissions on the enclosed item.
|
||||
AuthorizeManager.authorizeAction(ourContext, item, Constants.WRITE);
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
|
||||
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
||||
+ "collection_id=" + collection.getID()));
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* StreamDisseminationCrosswalk
|
||||
*
|
||||
* Version: $Revision: 1.4 $
|
||||
*
|
||||
* Date: $Date: 2006/04/10 04:11:09 $
|
||||
*
|
||||
* 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.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.crosswalk.CrosswalkException;
|
||||
|
||||
|
||||
/**
|
||||
* A class implementing this interface crosswalk metadata directly
|
||||
* from a DSpace Object to an output stream, in a specific format.
|
||||
* <p>
|
||||
* Stream-oriented crosswalks are intended to be used for metadata
|
||||
* formats which are either (a) not XML-based, or (b) too bulky for the
|
||||
* DOM-ish in-memory model developed for the METS and IMSCP packagers.
|
||||
* The METS packagers (all subclasses of AbstractMETSDisseminator / AbstractMETSIngester
|
||||
* are equipped to call these crosswalks as well as the XML-based ones,
|
||||
* just refer to the desired crosswalk by its plugin name.
|
||||
*
|
||||
* @author Larry Stone
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
public interface StreamDisseminationCrosswalk
|
||||
{
|
||||
/**
|
||||
* Predicate: Can this disseminator crosswalk the given object.
|
||||
*
|
||||
* @param dso dspace object, e.g. an <code>Item</code>.
|
||||
* @return true when disseminator is capable of producing metadata.
|
||||
*/
|
||||
public boolean canDisseminate(Context context, DSpaceObject dso);
|
||||
|
||||
/**
|
||||
* Execute crosswalk on the given object, sending output to the stream.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param dso the DSpace Object whose metadata to export.
|
||||
* @param out output stream to write to
|
||||
*
|
||||
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
|
||||
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
|
||||
* @throws IOException I/O failure in services this calls
|
||||
* @throws SQLException Database failure in services this calls
|
||||
* @throws AuthorizeException current user not authorized for this operation.
|
||||
*/
|
||||
public void disseminate(Context context, DSpaceObject dso, OutputStream out)
|
||||
throws CrosswalkException, IOException, SQLException, AuthorizeException;
|
||||
|
||||
public String getMIMEType();
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* StreamIngestionCrosswalk
|
||||
*
|
||||
* Version: $Revision: 1.4 $
|
||||
*
|
||||
* Date: $Date: 2006/04/10 04:11:09 $
|
||||
*
|
||||
* 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.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.crosswalk.CrosswalkException;
|
||||
|
||||
|
||||
/**
|
||||
* A class implementing this interface can crosswalk metadata directly
|
||||
* from a stream (assumed to be in a specific format) to the object.
|
||||
* <p>
|
||||
* Stream-oriented crosswalks are intended to be used for metadata
|
||||
* formats which are either (a) not XML-based, or (b) too bulky for the
|
||||
* DOM-ish in-memory model developed for the METS and IMSCP packagers.
|
||||
* The METS packagers (all subclasses of AbstractMETSDisseminator / AbstractMETSIngester
|
||||
* are equipped to call these crosswalks as well as the XML-based ones,
|
||||
* just refer to the desired crosswalk by its plugin name.
|
||||
*
|
||||
* @author Larry Stone
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
public interface StreamIngestionCrosswalk
|
||||
{
|
||||
/**
|
||||
* Execute crosswalk on the given object, taking input from the stream.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param dso the DSpace Object whose metadata is being ingested.
|
||||
* @param out input stream containing the metadata.
|
||||
*
|
||||
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
|
||||
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
|
||||
* @throws IOException I/O failure in services this calls
|
||||
* @throws SQLException Database failure in services this calls
|
||||
* @throws AuthorizeException current user not authorized for this operation.
|
||||
*/
|
||||
public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType)
|
||||
throws CrosswalkException, IOException, SQLException, AuthorizeException;
|
||||
}
|
@@ -51,6 +51,9 @@ import java.util.Map;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.event.EventManager;
|
||||
import org.dspace.event.Dispatcher;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
|
||||
/**
|
||||
@@ -68,7 +71,6 @@ import org.dspace.storage.rdbms.DatabaseManager;
|
||||
* The context object is also used as a cache for CM API objects.
|
||||
*
|
||||
*
|
||||
* @author Robert Tansley
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class Context
|
||||
@@ -96,6 +98,12 @@ public class Context
|
||||
/** Group IDs of special groups user is a member of */
|
||||
private List specialGroups;
|
||||
|
||||
/** Content events */
|
||||
private List<Event> events = null;
|
||||
|
||||
/** Event dispatcher name */
|
||||
private String dispName = null;
|
||||
|
||||
/**
|
||||
* Construct a new context object. A database connection is opened. No user
|
||||
* is authenticated.
|
||||
@@ -241,7 +249,7 @@ public class Context
|
||||
try
|
||||
{
|
||||
// Commit any changes made as part of the transaction
|
||||
connection.commit();
|
||||
commit();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -259,12 +267,79 @@ public class Context
|
||||
* if there was an error completing the database transaction
|
||||
* or closing the connection
|
||||
*/
|
||||
public void commit() throws SQLException
|
||||
{
|
||||
public void commit() throws SQLException {
|
||||
// Commit any changes made as part of the transaction
|
||||
Dispatcher dispatcher = null;
|
||||
|
||||
try {
|
||||
if (events != null) {
|
||||
|
||||
if (dispName == null) {
|
||||
dispName = EventManager.DEFAULT_DISPATCHER;
|
||||
}
|
||||
|
||||
dispatcher = EventManager.getDispatcher(dispName);
|
||||
|
||||
connection.commit();
|
||||
dispatcher.dispatch(this);
|
||||
} else {
|
||||
connection.commit();
|
||||
}
|
||||
|
||||
} finally {
|
||||
events = null;
|
||||
if(dispatcher != null)
|
||||
{
|
||||
/*
|
||||
* TODO return dispatcher via internal method dispatcher.close();
|
||||
* and remove the returnDispatcher method from EventManager.
|
||||
*/
|
||||
EventManager.returnDispatcher(dispName, dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an event dispatcher, <code>null</code> selects the default
|
||||
*
|
||||
*/
|
||||
public void setDispatcher(String dispatcher)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug(this.toString() + ": setDispatcher(\"" + dispatcher + "\")");
|
||||
}
|
||||
dispName = dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event to be dispatched when this context is committed.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void addEvent(Event event)
|
||||
{
|
||||
if (events == null)
|
||||
{
|
||||
events = new ArrayList<Event>();
|
||||
}
|
||||
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current event list. If there is a separate list of events from
|
||||
* already-committed operations combine that with current list.
|
||||
*
|
||||
* @return List of all available events.
|
||||
*/
|
||||
public List<Event> getEvents()
|
||||
{
|
||||
return events;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the context, without committing any of the changes performed using
|
||||
* this context. The database connection is freed. No exception is thrown if
|
||||
@@ -287,10 +362,12 @@ public class Context
|
||||
{
|
||||
DatabaseManager.freeConnection(connection);
|
||||
connection = null;
|
||||
events = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Find out if this context is valid. Returns <code>false</code> if this
|
||||
* context has been aborted or completed.
|
||||
*
|
||||
|
@@ -52,6 +52,13 @@ import java.text.ParseException;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Date;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Utility functions for DSpace.
|
||||
@@ -61,6 +68,9 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class Utils
|
||||
{
|
||||
/** log4j logger */
|
||||
private static Logger log = Logger.getLogger(Utils.class);
|
||||
|
||||
private static final Pattern DURATION_PATTERN = Pattern
|
||||
.compile("(\\d+)([smhdwy])");
|
||||
|
||||
@@ -82,6 +92,31 @@ public class Utils
|
||||
|
||||
private static VMID vmid = new VMID();
|
||||
|
||||
// for parseISO8601Date
|
||||
private static SimpleDateFormat parseFmt[] =
|
||||
{
|
||||
// first try at parsing, has milliseconds (note General time zone)
|
||||
new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSz"),
|
||||
|
||||
// second try at parsing, no milliseconds (note General time zone)
|
||||
new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ssz"),
|
||||
|
||||
|
||||
// finally, try without any timezone (defaults to current TZ)
|
||||
new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSS"),
|
||||
|
||||
new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss")
|
||||
};
|
||||
|
||||
// for formatISO8601Date
|
||||
// output canonical format (note RFC22 time zone, easier to hack)
|
||||
private static SimpleDateFormat outFmtSecond = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ssZ");
|
||||
|
||||
// output format with millsecond precision
|
||||
private static SimpleDateFormat outFmtMillisec = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZ");
|
||||
|
||||
private static Calendar outCal = GregorianCalendar.getInstance();
|
||||
|
||||
/** Private Constructor */
|
||||
private Utils()
|
||||
{
|
||||
@@ -350,4 +385,64 @@ public class Utils
|
||||
|
||||
return qint * multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates timestamp from an ISO 8601-standard format, which
|
||||
* is commonly used in XML and RDF documents.
|
||||
* This method is synchronized because it depends on a non-reentrant
|
||||
* static DateFormat (more efficient than creating a new one each call).
|
||||
*
|
||||
* @param s the input string
|
||||
* @return Date object, or null if there is a problem translating.
|
||||
*/
|
||||
public static synchronized Date parseISO8601Date(String s)
|
||||
{
|
||||
// attempt to normalize the timezone to something we can parse;
|
||||
// SimpleDateFormat can't handle "Z"
|
||||
char tzSign = s.charAt(s.length()-6);
|
||||
if (s.endsWith("Z"))
|
||||
s = s.substring(0, s.length()-1) + "GMT+00:00";
|
||||
|
||||
// check for trailing timezone
|
||||
else if (tzSign == '-' || tzSign == '+')
|
||||
s = s.substring(0, s.length()-6) + "GMT" + s.substring(s.length()-6);
|
||||
|
||||
// try to parse without millseconds
|
||||
ParseException lastError = null;
|
||||
for (int i = 0; i < parseFmt.length; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
return parseFmt[i].parse(s);
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
if (lastError != null)
|
||||
log.error("Error parsing date:", lastError);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Date to String in the ISO 8601 standard format.
|
||||
* The RFC822 timezone is almost right, still need to insert ":".
|
||||
* This method is synchronized because it depends on a non-reentrant
|
||||
* static DateFormat (more efficient than creating a new one each call).
|
||||
*
|
||||
* @param d the input Date
|
||||
* @return String containing formatted date.
|
||||
*/
|
||||
public static synchronized String formatISO8601Date(Date d)
|
||||
{
|
||||
String result;
|
||||
outCal.setTime(d);
|
||||
if (outCal.get(Calendar.MILLISECOND) == 0)
|
||||
result = outFmtSecond.format(d);
|
||||
else
|
||||
result = outFmtMillisec.format(d);
|
||||
int rl = result.length();
|
||||
return result.substring(0, rl-2) + ":" + result.substring(rl-2);
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.core.Utils;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -89,6 +89,12 @@ public class EPerson extends DSpaceObject
|
||||
/** The row in the table representing this eperson */
|
||||
private TableRow myRow;
|
||||
|
||||
/** Flag set when data is modified, for events */
|
||||
private boolean modified;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Construct an EPerson
|
||||
*
|
||||
@@ -104,6 +110,8 @@ public class EPerson extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("eperson_id"));
|
||||
modified = modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,8 +434,7 @@ public class EPerson extends DSpaceObject
|
||||
log.info(LogManager.getHeader(context, "create_eperson", "eperson_id="
|
||||
+ e.getID()));
|
||||
|
||||
HistoryManager.saveHistory(context, e, HistoryManager.REMOVE, context
|
||||
.getCurrentUser(), context.getExtraLogInfo());
|
||||
context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(), null));
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -446,9 +453,6 @@ public class EPerson extends DSpaceObject
|
||||
"You must be an admin to delete an EPerson");
|
||||
}
|
||||
|
||||
HistoryManager.saveHistory(myContext, this, HistoryManager.REMOVE,
|
||||
myContext.getCurrentUser(), myContext.getExtraLogInfo());
|
||||
|
||||
// check for presence of eperson in tables that
|
||||
// have constraints on eperson_id
|
||||
Vector constraintList = getDeleteConstraints();
|
||||
@@ -460,9 +464,14 @@ public class EPerson extends DSpaceObject
|
||||
throw new EPersonDeletionException(constraintList);
|
||||
}
|
||||
|
||||
myContext.addEvent(new Event(Event.DELETE, Constants.EPERSON, getID(), getEmail()));
|
||||
|
||||
// Remove from cache
|
||||
myContext.removeCached(this, getID());
|
||||
|
||||
// XXX FIXME: This sidesteps the object model code so it won't
|
||||
// generate REMOVE events on the affected Groups.
|
||||
|
||||
// Remove any group memberships first
|
||||
DatabaseManager.updateQuery(myContext,
|
||||
"DELETE FROM EPersonGroup2EPerson WHERE eperson_id= ? ",
|
||||
@@ -549,6 +558,7 @@ public class EPerson extends DSpaceObject
|
||||
}
|
||||
|
||||
myRow.setColumn("email", s);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -575,6 +585,7 @@ public class EPerson extends DSpaceObject
|
||||
}
|
||||
|
||||
myRow.setColumn("netid", s);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,6 +632,7 @@ public class EPerson extends DSpaceObject
|
||||
public void setFirstName(String firstname)
|
||||
{
|
||||
myRow.setColumn("firstname", firstname);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -642,6 +654,7 @@ public class EPerson extends DSpaceObject
|
||||
public void setLastName(String lastname)
|
||||
{
|
||||
myRow.setColumn("lastname", lastname);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,6 +666,7 @@ public class EPerson extends DSpaceObject
|
||||
public void setCanLogIn(boolean login)
|
||||
{
|
||||
myRow.setColumn("can_log_in", login);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -674,6 +688,7 @@ public class EPerson extends DSpaceObject
|
||||
public void setRequireCertificate(boolean isrequired)
|
||||
{
|
||||
myRow.setColumn("require_certificate", isrequired);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -695,6 +710,7 @@ public class EPerson extends DSpaceObject
|
||||
public void setSelfRegistered(boolean sr)
|
||||
{
|
||||
myRow.setColumn("self_registered", sr);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -737,6 +753,8 @@ public class EPerson extends DSpaceObject
|
||||
public void setMetadata(String field, String value)
|
||||
{
|
||||
myRow.setColumn(field, value);
|
||||
modifiedMetadata = true;
|
||||
addDetails(field);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,6 +769,7 @@ public class EPerson extends DSpaceObject
|
||||
String encoded = Utils.getMD5(s);
|
||||
|
||||
myRow.setColumn("password", encoded);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -786,8 +805,17 @@ public class EPerson extends DSpaceObject
|
||||
log.info(LogManager.getHeader(myContext, "update_eperson",
|
||||
"eperson_id=" + getID()));
|
||||
|
||||
HistoryManager.saveHistory(myContext, this, HistoryManager.MODIFY,
|
||||
myContext.getCurrentUser(), myContext.getExtraLogInfo());
|
||||
if (modified)
|
||||
{
|
||||
myContext.addEvent(new Event(Event.MODIFY, Constants.EPERSON, getID(), null));
|
||||
modified = false;
|
||||
}
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
myContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.EPERSON, getID(), getDetails()));
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -830,7 +858,7 @@ public class EPerson extends DSpaceObject
|
||||
*/
|
||||
public Vector getDeleteConstraints() throws SQLException
|
||||
{
|
||||
Vector tableList = new Vector();
|
||||
Vector<String> tableList = new Vector<String>();
|
||||
|
||||
// check for eperson in item table
|
||||
TableRowIterator tri = DatabaseManager.query(myContext,
|
||||
@@ -872,4 +900,10 @@ public class EPerson extends DSpaceObject
|
||||
// explaining to the user why the eperson cannot be deleted.
|
||||
return tableList;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return getEmail();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
@@ -56,6 +57,7 @@ import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -83,9 +85,9 @@ public class Group extends DSpaceObject
|
||||
private TableRow myRow;
|
||||
|
||||
/** lists of epeople and groups in the group */
|
||||
private List epeople = new ArrayList();
|
||||
private List<EPerson> epeople = new ArrayList<EPerson>();
|
||||
|
||||
private List groups = new ArrayList();
|
||||
private List<Group> groups = new ArrayList<Group>();
|
||||
|
||||
/** lists that need to be written out again */
|
||||
private boolean epeopleChanged = false;
|
||||
@@ -95,6 +97,9 @@ public class Group extends DSpaceObject
|
||||
/** is this just a stub, or is all data loaded? */
|
||||
private boolean isDataLoaded = false;
|
||||
|
||||
/** Flag set when metadata is modified, for events */
|
||||
private boolean modifiedMetadata;
|
||||
|
||||
/**
|
||||
* Construct a Group from a given context and tablerow
|
||||
*
|
||||
@@ -108,6 +113,9 @@ public class Group extends DSpaceObject
|
||||
|
||||
// Cache ourselves
|
||||
context.cache(this, row.getIntColumn("eperson_group_id"));
|
||||
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,6 +221,8 @@ public class Group extends DSpaceObject
|
||||
log.info(LogManager.getHeader(context, "create_group", "group_id="
|
||||
+ g.getID()));
|
||||
|
||||
context.addEvent(new Event(Event.CREATE, Constants.GROUP, g.getID(), null));
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
@@ -245,6 +255,8 @@ public class Group extends DSpaceObject
|
||||
public void setName(String name)
|
||||
{
|
||||
myRow.setColumn("name", name);
|
||||
modifiedMetadata = true;
|
||||
addDetails("name");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +276,8 @@ public class Group extends DSpaceObject
|
||||
|
||||
epeople.add(e);
|
||||
epeopleChanged = true;
|
||||
|
||||
myContext.addEvent(new Event(Event.ADD, Constants.GROUP, getID(), Constants.EPERSON, e.getID(), e.getEmail()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,6 +297,8 @@ public class Group extends DSpaceObject
|
||||
|
||||
groups.add(g);
|
||||
groupsChanged = true;
|
||||
|
||||
myContext.addEvent(new Event(Event.ADD, Constants.GROUP, getID(), Constants.GROUP, g.getID(), g.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,6 +314,7 @@ public class Group extends DSpaceObject
|
||||
if (epeople.remove(e))
|
||||
{
|
||||
epeopleChanged = true;
|
||||
myContext.addEvent(new Event(Event.REMOVE, Constants.GROUP, getID(), Constants.EPERSON, e.getID(), e.getEmail()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +330,7 @@ public class Group extends DSpaceObject
|
||||
if (groups.remove(g))
|
||||
{
|
||||
groupsChanged = true;
|
||||
myContext.addEvent(new Event(Event.REMOVE, Constants.GROUP, getID(), Constants.GROUP, g.getID(), g.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,9 +415,9 @@ public class Group extends DSpaceObject
|
||||
public static Group[] allMemberGroups(Context c, EPerson e)
|
||||
throws SQLException
|
||||
{
|
||||
List groupList = new ArrayList();
|
||||
List<Group> groupList = new ArrayList<Group>();
|
||||
|
||||
Set myGroups = allMemberGroupIDs(c, e);
|
||||
Set<Integer> myGroups = allMemberGroupIDs(c, e);
|
||||
// now convert those Integers to Groups
|
||||
Iterator i = myGroups.iterator();
|
||||
|
||||
@@ -419,7 +437,7 @@ public class Group extends DSpaceObject
|
||||
* @return Set of Integer groupIDs
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static Set allMemberGroupIDs(Context c, EPerson e)
|
||||
public static Set<Integer> allMemberGroupIDs(Context c, EPerson e)
|
||||
throws SQLException
|
||||
{
|
||||
// two queries - first to get groups eperson is a member of
|
||||
@@ -429,7 +447,7 @@ public class Group extends DSpaceObject
|
||||
"SELECT * FROM epersongroup2eperson WHERE eperson_id= ?",
|
||||
e.getID());
|
||||
|
||||
Set groupIDs = new HashSet();
|
||||
Set<Integer> groupIDs = new HashSet<Integer>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -513,9 +531,9 @@ public class Group extends DSpaceObject
|
||||
public static EPerson[] allMembers(Context c, Group g)
|
||||
throws SQLException
|
||||
{
|
||||
List epersonList = new ArrayList();
|
||||
List<EPerson> epersonList = new ArrayList<EPerson>();
|
||||
|
||||
Set myEpeople = allMemberIDs(c, g);
|
||||
Set<Integer> myEpeople = allMemberIDs(c, g);
|
||||
// now convert those Integers to EPerson objects
|
||||
Iterator i = myEpeople.iterator();
|
||||
|
||||
@@ -538,19 +556,19 @@ public class Group extends DSpaceObject
|
||||
* @return Set of Integer epersonIDs
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static Set allMemberIDs(Context c, Group g)
|
||||
public static Set<Integer> allMemberIDs(Context c, Group g)
|
||||
throws SQLException
|
||||
{
|
||||
// two queries - first to get all groups which are a member of this group
|
||||
// second query gets all members of each group in the first query
|
||||
Set epeopleIDs = new HashSet();
|
||||
Set<Integer> epeopleIDs = new HashSet<Integer>();
|
||||
|
||||
// Get all groups which are a member of this group
|
||||
TableRowIterator tri = DatabaseManager.queryTable(c, "group2groupcache",
|
||||
"SELECT * FROM group2groupcache WHERE parent_id= ? ",
|
||||
g.getID());
|
||||
|
||||
Set groupIDs = new HashSet();
|
||||
Set<Integer> groupIDs = new HashSet<Integer>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -611,7 +629,7 @@ public class Group extends DSpaceObject
|
||||
private static boolean epersonInGroup(Context c, int groupID, EPerson e)
|
||||
throws SQLException
|
||||
{
|
||||
Set groupIDs = Group.allMemberGroupIDs(c, e);
|
||||
Set<Integer> groupIDs = Group.allMemberGroupIDs(c, e);
|
||||
|
||||
return groupIDs.contains(new Integer(groupID));
|
||||
}
|
||||
@@ -868,6 +886,9 @@ public class Group extends DSpaceObject
|
||||
public void delete() throws SQLException
|
||||
{
|
||||
// FIXME: authorizations
|
||||
|
||||
myContext.addEvent(new Event(Event.DELETE, Constants.GROUP, getID(), getName()));
|
||||
|
||||
// Remove from cache
|
||||
myContext.removeCached(this, getID());
|
||||
|
||||
@@ -964,6 +985,13 @@ public class Group extends DSpaceObject
|
||||
// FIXME: Check authorisation
|
||||
DatabaseManager.update(myContext, myRow);
|
||||
|
||||
if (modifiedMetadata)
|
||||
{
|
||||
myContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.GROUP, getID(), getDetails()));
|
||||
modifiedMetadata = false;
|
||||
clearDetails();
|
||||
}
|
||||
|
||||
// Redo eperson mappings if they've changed
|
||||
if (epeopleChanged)
|
||||
{
|
||||
@@ -1062,7 +1090,7 @@ public class Group extends DSpaceObject
|
||||
TableRowIterator tri = DatabaseManager.queryTable(myContext, "group2group",
|
||||
"SELECT * FROM group2group");
|
||||
|
||||
Map parents = new HashMap();
|
||||
Map<Integer,Set<Integer>> parents = new HashMap<Integer,Set<Integer>>();
|
||||
|
||||
while (tri.hasNext())
|
||||
{
|
||||
@@ -1074,7 +1102,7 @@ public class Group extends DSpaceObject
|
||||
// if parent doesn't have an entry, create one
|
||||
if (!parents.containsKey(parentID))
|
||||
{
|
||||
Set children = new HashSet();
|
||||
Set<Integer> children = new HashSet<Integer>();
|
||||
|
||||
// add child id to the list
|
||||
children.add(childID);
|
||||
@@ -1084,7 +1112,7 @@ public class Group extends DSpaceObject
|
||||
{
|
||||
// parent has an entry, now add the child to the parent's record
|
||||
// of children
|
||||
Set children = (Set) parents.get(parentID);
|
||||
Set<Integer> children = parents.get(parentID);
|
||||
children.add(childID);
|
||||
}
|
||||
}
|
||||
@@ -1103,7 +1131,7 @@ public class Group extends DSpaceObject
|
||||
{
|
||||
Integer parentID = (Integer) i.next();
|
||||
|
||||
Set myChildren = getChildren(parents, parentID);
|
||||
Set<Integer> myChildren = getChildren(parents, parentID);
|
||||
|
||||
Iterator j = myChildren.iterator();
|
||||
|
||||
@@ -1112,7 +1140,7 @@ public class Group extends DSpaceObject
|
||||
// child of a parent
|
||||
Integer childID = (Integer) j.next();
|
||||
|
||||
((Set) parents.get(parentID)).add(childID);
|
||||
((Set<Integer>) parents.get(parentID)).add(childID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,7 +1155,7 @@ public class Group extends DSpaceObject
|
||||
{
|
||||
Integer parent = (Integer) pi.next();
|
||||
|
||||
Set children = (Set) parents.get(parent);
|
||||
Set<Integer> children = parents.get(parent);
|
||||
Iterator ci = children.iterator(); // child iterator
|
||||
|
||||
while (ci.hasNext())
|
||||
@@ -1158,16 +1186,16 @@ public class Group extends DSpaceObject
|
||||
* the parent you're interested in
|
||||
* @return Map whose keys are all of the children of a parent
|
||||
*/
|
||||
private Set getChildren(Map parents, Integer parent)
|
||||
private Set<Integer> getChildren(Map<Integer,Set<Integer>> parents, Integer parent)
|
||||
{
|
||||
Set myChildren = new HashSet();
|
||||
Set<Integer> myChildren = new HashSet<Integer>();
|
||||
|
||||
// degenerate case, this parent has no children
|
||||
if (!parents.containsKey(parent))
|
||||
return myChildren;
|
||||
|
||||
// got this far, so we must have children
|
||||
Set children = (Set) parents.get(parent);
|
||||
Set<Integer> children = parents.get(parent);
|
||||
|
||||
// now iterate over all of the children
|
||||
Iterator i = children.iterator();
|
||||
|
183
dspace-api/src/main/java/org/dspace/event/BasicDispatcher.java
Normal file
183
dspace-api/src/main/java/org/dspace/event/BasicDispatcher.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* BasicDispatcher.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.Utils;
|
||||
|
||||
/**
|
||||
* BasicDispatcher implements the primary task of a Dispatcher: it delivers a
|
||||
* filtered list of events, synchronously, to a configured list of consumers. It
|
||||
* may be extended for more elaborate behavior.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class BasicDispatcher extends Dispatcher
|
||||
{
|
||||
|
||||
public BasicDispatcher(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(BasicDispatcher.class);
|
||||
|
||||
public void addConsumerProfile(ConsumerProfile cp)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if (consumers.containsKey(cp.getName()))
|
||||
throw new IllegalArgumentException(
|
||||
"This dispatcher already has a consumer named \""
|
||||
+ cp.getName() + "\"");
|
||||
|
||||
consumers.put(cp.getName(), cp);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
int n = 0;
|
||||
for (Iterator i = cp.getFilters().iterator(); i.hasNext(); ++n)
|
||||
{
|
||||
int f[] = (int[]) i.next();
|
||||
log.debug("Adding Consumer=\"" + cp.getName() + "\", instance="
|
||||
+ cp.getConsumer().toString() + ", filter["
|
||||
+ String.valueOf(n) + "]=(ObjMask="
|
||||
+ String.valueOf(f[Event.SUBJECT_MASK])
|
||||
+ ", EventMask=" + String.valueOf(f[Event.EVENT_MASK])
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch all events added to this Context according to configured
|
||||
* consumers.
|
||||
*
|
||||
* @param ctx
|
||||
* the execution context
|
||||
*/
|
||||
public void dispatch(Context ctx)
|
||||
{
|
||||
if (!consumers.isEmpty())
|
||||
{
|
||||
List events = ctx.getEvents();
|
||||
|
||||
if (events == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Processing queue of "
|
||||
+ String.valueOf(events.size()) + " events.");
|
||||
|
||||
// transaction identifier applies to all events created in
|
||||
// this context for the current transaction. Prefix it with
|
||||
// some letters so RDF readers don't mistake it for an integer.
|
||||
String tid = "TX" + Utils.generateKey();
|
||||
|
||||
for (Iterator ei = events.iterator(); ei.hasNext();)
|
||||
{
|
||||
Event event = (Event) ei.next();
|
||||
event.setDispatcher(getIdentifier());
|
||||
event.setTransactionID(tid);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Iterating over "
|
||||
+ String.valueOf(consumers.values().size())
|
||||
+ " consumers...");
|
||||
|
||||
for (Iterator ci = consumers.values().iterator(); ci.hasNext();)
|
||||
{
|
||||
ConsumerProfile cp = (ConsumerProfile) ci.next();
|
||||
|
||||
if (event.pass(cp.getFilters()))
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Sending event to \"" + cp.getName()
|
||||
+ "\": " + event.toString());
|
||||
|
||||
try
|
||||
{
|
||||
cp.getConsumer().consume(ctx, event);
|
||||
|
||||
// Record that the event has been consumed by this
|
||||
// consumer
|
||||
event.setBitSet(cp.getName());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Consumer(\"" + cp.getName()
|
||||
+ "\").consume threw: " + e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Call end on the consumers that got synchronous events.
|
||||
for (Iterator ci = consumers.values().iterator(); ci.hasNext();)
|
||||
{
|
||||
ConsumerProfile cp = (ConsumerProfile) ci.next();
|
||||
if (cp != null)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Calling end for consumer \"" + cp.getName()
|
||||
+ "\"");
|
||||
|
||||
try
|
||||
{
|
||||
cp.getConsumer().end(ctx);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Error in Consumer(\"" + cp.getName()
|
||||
+ "\").end: " + e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
91
dspace-api/src/main/java/org/dspace/event/Consumer.java
Normal file
91
dspace-api/src/main/java/org/dspace/event/Consumer.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Consumer.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Interface for content event consumers. Note that the consumer cannot tell if
|
||||
* it is invoked synchronously or asynchronously; the consumer interface and
|
||||
* sequence of calls is the same for both. Asynchronous consumers may see more
|
||||
* consume() calls between the start and end of the event stream, if they are
|
||||
* invoked asynchronously, once in a long time period, rather than synchronously
|
||||
* after every Context.commit().
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public interface Consumer
|
||||
{
|
||||
/**
|
||||
* Initialize - allocate any resources required to operate. This may include
|
||||
* initializing any pooled JMS resources. Called ONCE when created by the
|
||||
* dispatcher pool. This should be used to set up expensive resources that
|
||||
* will remain for the lifetime of the consumer.
|
||||
*/
|
||||
public void initialize() throws Exception;
|
||||
|
||||
/**
|
||||
* Consume an event; events may get filtered at the dispatcher level, hiding
|
||||
* it from the consumer. This behavior is based on the dispatcher/consumer
|
||||
* configuration. Should include logic to initialize any resources required
|
||||
* for a batch of events.
|
||||
*
|
||||
* @param ctx
|
||||
* the execution context object
|
||||
*
|
||||
* @param event
|
||||
* the content event
|
||||
*/
|
||||
public void consume(Context ctx, Event event) throws Exception;
|
||||
|
||||
/**
|
||||
* Signal that there are no more events queued in this event stream and
|
||||
* event processing for the preceding consume calls should be finished up.
|
||||
*/
|
||||
public void end(Context ctx) throws Exception;
|
||||
|
||||
/**
|
||||
* Finish - free any allocated resources. Called when consumer (via it's
|
||||
* parent dispatcher) is going to be destroyed by the dispatcher pool.
|
||||
*/
|
||||
public void finish(Context ctx) throws Exception;
|
||||
|
||||
}
|
179
dspace-api/src/main/java/org/dspace/event/ConsumerProfile.java
Normal file
179
dspace-api/src/main/java/org/dspace/event/ConsumerProfile.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* ConsumerProfile.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
|
||||
/**
|
||||
* An instance of this class contains the configuration profile of a specific,
|
||||
* named Consumer, <em>in the context of a specific
|
||||
* Dispatcher</em>. This
|
||||
* includes the name, the class to instantiate and event filters. Note that all
|
||||
* characteristics are "global" and the same for all dispatchers.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class ConsumerProfile
|
||||
{
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(EventManager.class);
|
||||
|
||||
/** Name matching the key in DSpace Configuration */
|
||||
private String name;
|
||||
|
||||
/** Instance of configured consumer class */
|
||||
private Consumer consumer;
|
||||
|
||||
/** Filters - each is an array of 2 bitmasks, action mask and subject mask */
|
||||
private List<int[]> filters;
|
||||
|
||||
// Prefix of keys in DSpace Configuration.
|
||||
private final String CONSUMER_PREFIX = "event.consumer.";
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private ConsumerProfile(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method, create new profile from configuration.
|
||||
*
|
||||
* @param name
|
||||
* configuration name of the consumer profile
|
||||
* @returns a new ConsumerProfile; never null.
|
||||
*/
|
||||
public static ConsumerProfile makeConsumerProfile(String name)
|
||||
throws IllegalArgumentException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException
|
||||
{
|
||||
ConsumerProfile result = new ConsumerProfile(name);
|
||||
result.readConfiguration();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get class and filters from DSpace Configuration.
|
||||
private void readConfiguration() throws IllegalArgumentException,
|
||||
ClassNotFoundException, InstantiationException,
|
||||
IllegalAccessException
|
||||
{
|
||||
String className = ConfigurationManager.getProperty(CONSUMER_PREFIX
|
||||
+ name + ".class");
|
||||
String filterString = ConfigurationManager.getProperty(CONSUMER_PREFIX
|
||||
+ name + ".filters");
|
||||
|
||||
if (className == null)
|
||||
throw new IllegalArgumentException(
|
||||
"No class configured for consumer named: " + name);
|
||||
if (filterString == null)
|
||||
throw new IllegalArgumentException(
|
||||
"No filters configured for consumer named: " + name);
|
||||
|
||||
consumer = (Consumer) Class.forName(className.trim()).newInstance();
|
||||
|
||||
// Each "filter" is <objectTypes> + <eventTypes> : ...
|
||||
filters = new ArrayList<int[]>();
|
||||
String part[] = filterString.trim().split(":");
|
||||
for (int j = 0; j < part.length; ++j)
|
||||
{
|
||||
String fpart[] = part[j].split("\\+");
|
||||
if (fpart.length != 2)
|
||||
log
|
||||
.error("Bad Filter clause in consumer stanza in Configuration entry for "
|
||||
+ CONSUMER_PREFIX
|
||||
+ name
|
||||
+ ".consumers: "
|
||||
+ part[j]);
|
||||
else
|
||||
{
|
||||
int filter[] = new int[2];
|
||||
filter[0] = filter[1] = 0;
|
||||
String objectNames[] = fpart[0].split("\\|");
|
||||
for (int k = 0; k < objectNames.length; ++k)
|
||||
{
|
||||
int ot = Event.parseObjectType(objectNames[k]);
|
||||
if (ot == 0)
|
||||
log
|
||||
.error("Bad ObjectType in Consumer Stanza in Configuration entry for "
|
||||
+ CONSUMER_PREFIX
|
||||
+ name
|
||||
+ ".consumers: " + objectNames[k]);
|
||||
else
|
||||
filter[Event.SUBJECT_MASK] |= ot;
|
||||
}
|
||||
String eventNames[] = fpart[1].split("\\|");
|
||||
for (int k = 0; k < eventNames.length; ++k)
|
||||
{
|
||||
int et = Event.parseEventType(eventNames[k]);
|
||||
if (et == 0)
|
||||
log
|
||||
.error("Bad EventType in Consumer Stanza in Configuration entry for "
|
||||
+ CONSUMER_PREFIX
|
||||
+ name
|
||||
+ ".consumers: " + eventNames[k]);
|
||||
else
|
||||
filter[Event.EVENT_MASK] |= et;
|
||||
}
|
||||
filters.add(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Consumer getConsumer()
|
||||
{
|
||||
return consumer;
|
||||
}
|
||||
|
||||
public List<int[]> getFilters()
|
||||
{
|
||||
return filters;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
110
dspace-api/src/main/java/org/dspace/event/Dispatcher.java
Normal file
110
dspace-api/src/main/java/org/dspace/event/Dispatcher.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Dispatcher.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Interface for event dispatchers. The primary role of a dispatcher is to
|
||||
* deliver a set of events to a configured list of consumers. It may also
|
||||
* transform, consolidate, and otherwise optimize the event stream prior to
|
||||
* delivering events to its consumers.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public abstract class Dispatcher
|
||||
{
|
||||
protected String name;
|
||||
|
||||
/** unique identifer of this dispatcher - cached hash of its text Name */
|
||||
protected int identifier;
|
||||
|
||||
/**
|
||||
* Map of consumers by their configured name.
|
||||
*/
|
||||
protected Map<String, ConsumerProfile> consumers = new HashMap<String, ConsumerProfile>();
|
||||
|
||||
protected Dispatcher(String name)
|
||||
{
|
||||
super();
|
||||
this.name = name;
|
||||
this.identifier = name.hashCode();
|
||||
}
|
||||
|
||||
public Collection getConsumers()
|
||||
{
|
||||
return consumers.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns unique integer that identifies this Dispatcher configuration.
|
||||
*/
|
||||
public int getIdentifier()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a consumer to the end of the list.
|
||||
*
|
||||
* @param consumer
|
||||
* the event consumer to add
|
||||
* @param filter
|
||||
* the event filter to apply
|
||||
*/
|
||||
public abstract void addConsumerProfile(ConsumerProfile cp)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Dispatch all events added to this Context according to configured
|
||||
* consumers.
|
||||
*
|
||||
* @param ctx
|
||||
* the execution context object
|
||||
*/
|
||||
public abstract void dispatch(Context ctx);
|
||||
|
||||
}
|
614
dspace-api/src/main/java/org/dspace/event/Event.java
Normal file
614
dspace-api/src/main/java/org/dspace/event/Event.java
Normal file
@@ -0,0 +1,614 @@
|
||||
/*
|
||||
* Event.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* An Event object represents a single action that changed one object in the
|
||||
* DSpace data model. An "atomic" action at the application or business-logic
|
||||
* API level may spawn many of these events.
|
||||
* <p>
|
||||
* This class includes tools to help set and use the contents of the event. Note
|
||||
* that it describes DSpace data object types in two ways: by the type
|
||||
* identifiers in the Constants class, and also by an Event-specific bitmask
|
||||
* (used by its internal filters). All public API calls use the Constants
|
||||
* version of the data model types.
|
||||
* <p>
|
||||
* Note that the type of the event itself is actually descriptive of the
|
||||
* <em>action</em> it performs: ADD, MODIFY, etc. The most significant
|
||||
* elements of the event are:
|
||||
* <p>
|
||||
* <br> - (Action) Type <br> - Subject -- DSpace object to which the action
|
||||
* applies, e.g. the Collection to which an ADD adds a member. <br> - Object --
|
||||
* optional, when present it is the other object effected by an action, e.g. the
|
||||
* Item ADDed to a Collection by an ADD. <br> - detail -- a textual summary of
|
||||
* what changed, content and its significance varies by the combination of
|
||||
* action and subject type. <br> - timestamp -- exact millisecond timestamp at
|
||||
* which event was logged.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class Event implements Serializable
|
||||
{
|
||||
/** ---------- Constants ------------- * */
|
||||
|
||||
/** Event (Action) types */
|
||||
public static final int CREATE = 1 << 0; // create new object
|
||||
|
||||
public static final int MODIFY = 1 << 1; // modify object
|
||||
|
||||
public static final int MODIFY_METADATA = 1 << 2; // modify object
|
||||
|
||||
public static final int ADD = 1 << 3; // add content to container
|
||||
|
||||
public static final int REMOVE = 1 << 4; // remove content from container
|
||||
|
||||
public static final int DELETE = 1 << 5; // destroy object
|
||||
|
||||
/** Index of filter parts in their array: */
|
||||
public static final int SUBJECT_MASK = 0; // mask of subject types
|
||||
|
||||
public static final int EVENT_MASK = 1; // mask of event type
|
||||
|
||||
// XXX NOTE: keep this up to date with any changes to event (action) types.
|
||||
private static final String eventTypeText[] = { "CREATE", "MODIFY",
|
||||
"MODIFY_METADATA", "ADD", "REMOVE", "DELETE" };
|
||||
|
||||
/** XXX NOTE: These constants must be kept synchronized * */
|
||||
/** XXX NOTE: with ALL_OBJECTS_MASK *AND* objTypeToMask hash * */
|
||||
private static final int NONE = 0;
|
||||
|
||||
private static final int BITSTREAM = 1 << Constants.BITSTREAM; // 0
|
||||
|
||||
private static final int BUNDLE = 1 << Constants.BUNDLE; // 1
|
||||
|
||||
private static final int ITEM = 1 << Constants.ITEM; // 2
|
||||
|
||||
private static final int COLLECTION = 1 << Constants.COLLECTION; // 3
|
||||
|
||||
private static final int COMMUNITY = 1 << Constants.COMMUNITY; // 4
|
||||
|
||||
private static final int SITE = 1 << Constants.SITE; // 5
|
||||
|
||||
private static final int GROUP = 1 << Constants.GROUP; // 6
|
||||
|
||||
private static final int EPERSON = 1 << Constants.EPERSON; // 7
|
||||
|
||||
private static final int ALL_OBJECTS_MASK = BITSTREAM | BUNDLE | ITEM
|
||||
| COLLECTION | COMMUNITY | SITE | GROUP | EPERSON;
|
||||
|
||||
private static Map<Integer, Integer> objTypeToMask = new HashMap<Integer, Integer>();
|
||||
|
||||
private static Map<Integer, Integer> objMaskToType = new HashMap<Integer, Integer>();
|
||||
static
|
||||
{
|
||||
objTypeToMask.put(new Integer(Constants.BITSTREAM), new Integer(
|
||||
BITSTREAM));
|
||||
objMaskToType.put(new Integer(BITSTREAM), new Integer(
|
||||
Constants.BITSTREAM));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.BUNDLE), new Integer(BUNDLE));
|
||||
objMaskToType.put(new Integer(BUNDLE), new Integer(Constants.BUNDLE));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.ITEM), new Integer(ITEM));
|
||||
objMaskToType.put(new Integer(ITEM), new Integer(Constants.ITEM));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.COLLECTION), new Integer(
|
||||
COLLECTION));
|
||||
objMaskToType.put(new Integer(COLLECTION), new Integer(
|
||||
Constants.COLLECTION));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.COMMUNITY), new Integer(
|
||||
COMMUNITY));
|
||||
objMaskToType.put(new Integer(COMMUNITY), new Integer(
|
||||
Constants.COMMUNITY));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.SITE), new Integer(SITE));
|
||||
objMaskToType.put(new Integer(SITE), new Integer(Constants.SITE));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.GROUP), new Integer(GROUP));
|
||||
objMaskToType.put(new Integer(GROUP), new Integer(Constants.GROUP));
|
||||
|
||||
objTypeToMask.put(new Integer(Constants.EPERSON), new Integer(EPERSON));
|
||||
objMaskToType.put(new Integer(EPERSON), new Integer(Constants.EPERSON));
|
||||
}
|
||||
|
||||
/** ---------- Event Fields ------------- * */
|
||||
|
||||
/** identifier of Dispatcher that created this event (hash of its name) */
|
||||
private int dispatcher;
|
||||
|
||||
/** event (action) type - above enumeration */
|
||||
private int eventType;
|
||||
|
||||
/** object-type of SUBJECT - see above enumeration */
|
||||
private int subjectType;
|
||||
|
||||
/** content model identifier */
|
||||
private int subjectID;
|
||||
|
||||
/** object-type of SUBJECT - see above enumeration */
|
||||
private int objectType = NONE;
|
||||
|
||||
/** content model identifier */
|
||||
private int objectID = -1;
|
||||
|
||||
/** timestamp */
|
||||
private long timeStamp;
|
||||
|
||||
/** "detail" - arbitrary field for relevant detail, */
|
||||
/** e.g. former handle for DELETE event since obj is no longer available. */
|
||||
/**
|
||||
* FIXME This field is not a complete view of the DSpaceObject that was
|
||||
* modified. Providing these objects to the consumer (e.g. by storing
|
||||
* lifecycle versions of the changed objects in the context) would provide
|
||||
* for more complex consumer abilities that are beyond our purview.
|
||||
*/
|
||||
private String detail;
|
||||
|
||||
/** unique key to bind together events from one context's transaction */
|
||||
private String transactionID;
|
||||
|
||||
/** identity of authenticated user, i.e. context.getCurrentUser() */
|
||||
/** only needed in the event for marshalling for asynch event messages */
|
||||
private int currentUser = -1;
|
||||
|
||||
/** copy of context's "extraLogInfo" filed, used only for */
|
||||
/** marshalling for asynch event messages */
|
||||
private String extraLogInfo = null;
|
||||
|
||||
private BitSet consumedBy = new BitSet();
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(Event.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param eventType
|
||||
* action type, e.g. Event.ADD
|
||||
* @param subjectType
|
||||
* DSpace Object Type of subject e.g. Constants.ITEM.
|
||||
* @param subjectID
|
||||
* database ID of subject instance.
|
||||
* @param detail
|
||||
* detail information that depends on context.
|
||||
*/
|
||||
public Event(int eventType, int subjectType, int subjectID, String detail)
|
||||
{
|
||||
this.eventType = eventType;
|
||||
this.subjectType = coreTypeToMask(subjectType);
|
||||
this.subjectID = subjectID;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param eventType
|
||||
* action type, e.g. Event.ADD
|
||||
* @param subjectType
|
||||
* DSpace Object Type of subject e.g. Constants.ITEM.
|
||||
* @param subjectID
|
||||
* database ID of subject instance.
|
||||
* @param objectType
|
||||
* DSpace Object Type of object e.g. Constants.BUNDLE.
|
||||
* @param objectID
|
||||
* database ID of object instance.
|
||||
* @param detail
|
||||
* detail information that depends on context.
|
||||
* @param
|
||||
*/
|
||||
public Event(int eventType, int subjectType, int subjectID, int objectType,
|
||||
int objectID, String detail)
|
||||
{
|
||||
this.eventType = eventType;
|
||||
this.subjectType = coreTypeToMask(subjectType);
|
||||
this.subjectID = subjectID;
|
||||
this.objectType = coreTypeToMask(objectType);
|
||||
this.objectID = objectID;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two events. Ignore any difference in the timestamps. Also ignore
|
||||
* transactionID since that is not always set initially.
|
||||
*
|
||||
* @param other
|
||||
* the event to compare this one to
|
||||
* @returns true if events are "equal", false otherwise.
|
||||
*/
|
||||
public boolean equals(Event other)
|
||||
{
|
||||
return (this.detail == null ? other.detail == null : this.detail
|
||||
.equals(other.detail))
|
||||
&& this.eventType == other.eventType
|
||||
&& this.subjectType == other.subjectType
|
||||
&& this.subjectID == other.subjectID
|
||||
&& this.objectType == other.objectType
|
||||
&& this.objectID == other.objectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the identifier of the dispatcher that first processed this event.
|
||||
*
|
||||
* @param id
|
||||
* the unique (hash code) value characteristic of the dispatcher.
|
||||
*/
|
||||
public void setDispatcher(int id)
|
||||
{
|
||||
dispatcher = id;
|
||||
}
|
||||
|
||||
// translate a "core.Constants" object type value to local bitmask value.
|
||||
private static int coreTypeToMask(int core)
|
||||
{
|
||||
Integer mask = (Integer) objTypeToMask.get(new Integer(core));
|
||||
if (mask == null)
|
||||
return -1;
|
||||
else
|
||||
return mask.intValue();
|
||||
}
|
||||
|
||||
// translate bitmask object-type to "core.Constants" object type.
|
||||
private static int maskTypeToCore(int mask)
|
||||
{
|
||||
Integer core = (Integer) objMaskToType.get(new Integer(mask));
|
||||
if (core == null)
|
||||
return -1;
|
||||
else
|
||||
return core.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSpace object which is the "object" of an event.
|
||||
*
|
||||
* @returns DSpaceObject or null if none can be found or no object was set.
|
||||
*/
|
||||
public DSpaceObject getObject(Context context) throws SQLException
|
||||
{
|
||||
int type = getObjectType();
|
||||
int id = getObjectID();
|
||||
if (type < 0 || id < 0)
|
||||
return null;
|
||||
else
|
||||
return DSpaceObject.find(context, type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntactic sugar to get the DSpace object which is the "subject" of an
|
||||
* event.
|
||||
*
|
||||
* @returns DSpaceObject or null if none can be found.
|
||||
*/
|
||||
public DSpaceObject getSubject(Context context) throws SQLException
|
||||
{
|
||||
return DSpaceObject.find(context, getSubjectType(), getSubjectID());
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns database ID of subject of this event.
|
||||
*/
|
||||
public int getSubjectID()
|
||||
{
|
||||
return subjectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns database ID of object of this event, or -1 if none was set.
|
||||
*/
|
||||
public int getObjectID()
|
||||
{
|
||||
return objectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns type number (e.g. Constants.ITEM) of subject of this event.
|
||||
*/
|
||||
public int getSubjectType()
|
||||
{
|
||||
return maskTypeToCore(subjectType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns type number (e.g. Constants.ITEM) of object of this event, or -1
|
||||
* if none was set.
|
||||
*/
|
||||
public int getObjectType()
|
||||
{
|
||||
return maskTypeToCore(objectType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns type of subject of this event as a String, e.g. for logging.
|
||||
*/
|
||||
public String getSubjectTypeAsString()
|
||||
{
|
||||
int i = log2(subjectType);
|
||||
if (i >= 0 && i < Constants.typeText.length)
|
||||
return Constants.typeText[i];
|
||||
else
|
||||
return "(Unknown)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns type of object of this event as a String, e.g. for logging.
|
||||
*/
|
||||
public String getObjectTypeAsString()
|
||||
{
|
||||
int i = log2(objectType);
|
||||
if (i >= 0 && i < Constants.typeText.length)
|
||||
return Constants.typeText[i];
|
||||
else
|
||||
return "(Unknown)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a textual DSpace Object type name into an event subject-type
|
||||
* mask. NOTE: This returns a BIT-MASK, not a numeric type value; the mask
|
||||
* is only used within the event system.
|
||||
*
|
||||
* @param s
|
||||
* text name of object type.
|
||||
* @returns numeric value of object type or 0 for error.
|
||||
*/
|
||||
public static int parseObjectType(String s)
|
||||
{
|
||||
if (s.equals("*") | s.equalsIgnoreCase("all"))
|
||||
return ALL_OBJECTS_MASK;
|
||||
else
|
||||
{
|
||||
int id = Constants.getTypeID(s.toUpperCase());
|
||||
if (id >= 0)
|
||||
return 1 << id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns event-type (i.e. action) this event, one of the masks like
|
||||
* Event.ADD defined above.
|
||||
*/
|
||||
public int getEventType()
|
||||
{
|
||||
return eventType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text name of event (action) type.
|
||||
*
|
||||
* @returns event-type (i.e. action) this event as a String, e.g. for
|
||||
* logging.
|
||||
*/
|
||||
public String getEventTypeAsString()
|
||||
{
|
||||
int i = log2(eventType);
|
||||
if (i >= 0 && i < eventTypeText.length)
|
||||
return eventTypeText[i];
|
||||
else
|
||||
return "(Unknown)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret named event type.
|
||||
*
|
||||
* @param text
|
||||
* name of event type.
|
||||
* @returns numeric value of event type or 0 for error.
|
||||
*/
|
||||
public static int parseEventType(String s)
|
||||
{
|
||||
if (s.equals("*") | s.equalsIgnoreCase("all"))
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < eventTypeText.length; ++i)
|
||||
result |= (1 << i);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < eventTypeText.length; ++i)
|
||||
if (eventTypeText[i].equalsIgnoreCase(s))
|
||||
return 1 << i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns timestamp at which event occurred, as a count of milliseconds
|
||||
* since the epoch (standard Java format).
|
||||
*/
|
||||
public long getTimeStamp()
|
||||
{
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns hashcode identifier of name of Dispatcher which first dispatched
|
||||
* this event. (Needed by asynch dispatch code.)
|
||||
*/
|
||||
public int getDispatcher()
|
||||
{
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns value of detail element of the event.
|
||||
*/
|
||||
public String getDetail()
|
||||
{
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns value of transactionID element of the event.
|
||||
*/
|
||||
public String getTransactionID()
|
||||
{
|
||||
return transactionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value of transactionID element of the event.
|
||||
*
|
||||
* @param tid
|
||||
* new value of transactionID.
|
||||
*/
|
||||
public void setTransactionID(String tid)
|
||||
{
|
||||
transactionID = tid;
|
||||
}
|
||||
|
||||
public void setCurrentUser(int uid)
|
||||
{
|
||||
currentUser = uid;
|
||||
}
|
||||
|
||||
public int getCurrentUser()
|
||||
{
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public void setExtraLogInfo(String info)
|
||||
{
|
||||
extraLogInfo = info;
|
||||
}
|
||||
|
||||
public String getExtraLogInfo()
|
||||
{
|
||||
return extraLogInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param filters
|
||||
* list of filter masks; each one is an Array of two ints.
|
||||
* @returns true if this event would be passed through the given filter
|
||||
* list.
|
||||
*/
|
||||
public boolean pass(List filters)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
for (Iterator fi = filters.iterator(); fi.hasNext();)
|
||||
{
|
||||
int filter[] = (int[]) fi.next();
|
||||
if ((subjectType & filter[SUBJECT_MASK]) != 0
|
||||
&& (eventType & filter[EVENT_MASK]) != 0)
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Filtering event: " + "eventType="
|
||||
+ String.valueOf(eventType) + ", subjectType="
|
||||
+ String.valueOf(subjectType) + ", result="
|
||||
+ String.valueOf(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// dumb integer "log base 2", returns -1 if there are no 1's in number.
|
||||
private static int log2(int n)
|
||||
{
|
||||
for (int i = 0; i < 32; ++i)
|
||||
if (n == 1)
|
||||
return i;
|
||||
else
|
||||
n = n >> 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of which consumers the event has been consumed by. Should be
|
||||
* called by a dispatcher when calling consume(Context ctx, String name,
|
||||
* Event event) on an event.
|
||||
*
|
||||
* @param consumerName
|
||||
*/
|
||||
public void setBitSet(String consumerName)
|
||||
{
|
||||
consumedBy.set(EventManager.getConsumerIndex(consumerName));
|
||||
|
||||
}
|
||||
|
||||
public BitSet getBitSet()
|
||||
{
|
||||
return consumedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Detailed string representation of contents of this event, to
|
||||
* help in logging and debugging.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return "org.dspace.event.Event(eventType="
|
||||
+ this.getEventTypeAsString()
|
||||
+ ", SubjectType="
|
||||
+ this.getSubjectTypeAsString()
|
||||
+ ", SubjectID="
|
||||
+ String.valueOf(subjectID)
|
||||
+ ", ObjectType="
|
||||
+ this.getObjectTypeAsString()
|
||||
+ ", ObjectID="
|
||||
+ String.valueOf(objectID)
|
||||
+ ", TimeStamp="
|
||||
+ String.valueOf(timeStamp)
|
||||
+ ", dispatcher="
|
||||
+ String.valueOf(dispatcher)
|
||||
+ ", detail="
|
||||
+ (detail == null ? "[null]" : "\"" + detail + "\"")
|
||||
+ ", transactionID="
|
||||
+ (transactionID == null ? "[null]" : "\"" + transactionID
|
||||
+ "\"") + ")";
|
||||
}
|
||||
}
|
389
dspace-api/src/main/java/org/dspace/event/EventManager.java
Normal file
389
dspace-api/src/main/java/org/dspace/event/EventManager.java
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* EventManager.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.pool.KeyedObjectPool;
|
||||
import org.apache.commons.pool.KeyedPoolableObjectFactory;
|
||||
import org.apache.commons.pool.PoolUtils;
|
||||
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Class for managing the content event environment. The EventManager mainly
|
||||
* acts as a factory for Dispatchers, which are used by the Context to send
|
||||
* events to consumers. It also contains generally useful utility methods.
|
||||
*
|
||||
* Version: $Revision$
|
||||
*/
|
||||
public class EventManager
|
||||
{
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(EventManager.class);
|
||||
|
||||
// The name of the default dispatcher assigned to every new context unless
|
||||
// overridden
|
||||
public static final String DEFAULT_DISPATCHER = "default";
|
||||
|
||||
private static DispatcherPoolFactory dispatcherFactory = null;
|
||||
|
||||
private static GenericKeyedObjectPool.Config poolConfig = null;
|
||||
|
||||
// Keyed FIFO Pool of event dispatchers
|
||||
private static KeyedObjectPool dispatcherPool = null;
|
||||
|
||||
private static HashMap<String, Integer> consumerIndicies = null;
|
||||
|
||||
private static final String CONSUMER_PFX = "event.consumer.";
|
||||
|
||||
public EventManager()
|
||||
{
|
||||
initPool();
|
||||
log.info("Event Dispatcher Pool Initialized");
|
||||
}
|
||||
|
||||
private static void initPool()
|
||||
{
|
||||
|
||||
if (dispatcherPool == null)
|
||||
{
|
||||
|
||||
// TODO EVENT Some of these pool configuration
|
||||
// parameters can live in dspace.cfg or a
|
||||
// separate configuration file
|
||||
|
||||
// TODO EVENT Eviction parameters should be set
|
||||
|
||||
poolConfig = new GenericKeyedObjectPool.Config();
|
||||
poolConfig.maxActive = 100;
|
||||
poolConfig.maxIdle = 5;
|
||||
poolConfig.maxTotal = 100;
|
||||
|
||||
try
|
||||
{
|
||||
dispatcherFactory = new DispatcherPoolFactory();
|
||||
dispatcherPool = PoolUtils
|
||||
.synchronizedPool(new GenericKeyedObjectPool(
|
||||
dispatcherFactory, poolConfig));
|
||||
|
||||
enumerateConsumers();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dispatcher for configuration named by "name". Returns cached instance
|
||||
* if one exists.
|
||||
*/
|
||||
public static Dispatcher getDispatcher(String name)
|
||||
{
|
||||
if (dispatcherPool == null)
|
||||
{
|
||||
initPool();
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
name = DEFAULT_DISPATCHER;
|
||||
|
||||
try
|
||||
{
|
||||
return (Dispatcher) dispatcherPool.borrowObject(name);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Unable to aquire dispatcher named "
|
||||
+ name, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void returnDispatcher(String key, Dispatcher disp)
|
||||
{
|
||||
try
|
||||
{
|
||||
dispatcherPool.returnObject(key, disp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static int getConsumerIndex(String consumerClass)
|
||||
{
|
||||
Integer index = (Integer) consumerIndicies.get(consumerClass);
|
||||
return index != null ? index.intValue() : -1;
|
||||
|
||||
}
|
||||
|
||||
private static void enumerateConsumers()
|
||||
{
|
||||
Enumeration propertyNames = ConfigurationManager.propertyNames();
|
||||
int bitSetIndex = 0;
|
||||
|
||||
if (consumerIndicies == null)
|
||||
{
|
||||
consumerIndicies = new HashMap<String, Integer>();
|
||||
}
|
||||
|
||||
while (propertyNames.hasMoreElements())
|
||||
{
|
||||
String ckey = ((String) propertyNames.nextElement()).trim();
|
||||
|
||||
if (ckey.startsWith(CONSUMER_PFX) && ckey.endsWith(".class"))
|
||||
{
|
||||
String consumerName = ckey.substring(CONSUMER_PFX.length(),
|
||||
ckey.length() - 6);
|
||||
|
||||
consumerIndicies.put(consumerName, (Integer) bitSetIndex);
|
||||
bitSetIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class DispatcherPoolFactory implements KeyedPoolableObjectFactory
|
||||
{
|
||||
|
||||
// Prefix of keys in DSpace Configuration
|
||||
private static final String PROP_PFX = "event.dispatcher.";
|
||||
|
||||
// Cache of event dispatchers, keyed by name, for re-use.
|
||||
private static Map<String, String> dispatchers = new HashMap<String, String>();
|
||||
|
||||
public DispatcherPoolFactory()
|
||||
{
|
||||
parseEventConfig();
|
||||
log.info("");
|
||||
}
|
||||
|
||||
public Object makeObject(Object dispatcherName) throws Exception
|
||||
{
|
||||
|
||||
Dispatcher dispatcher = null;
|
||||
String dispClass = dispatchers.get(dispatcherName);
|
||||
|
||||
if (dispClass != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// all this to call a constructor with an argument
|
||||
final Class argTypes[] = { String.class };
|
||||
Constructor dc = Class.forName(dispClass).getConstructor(
|
||||
argTypes);
|
||||
Object args[] = new Object[1];
|
||||
args[0] = dispatcherName;
|
||||
dispatcher = (Dispatcher) dc.newInstance(args);
|
||||
|
||||
// OK, now get its list of consumers/filters
|
||||
String consumerKey = PROP_PFX + dispatcherName
|
||||
+ ".consumers";
|
||||
String consumerList = ConfigurationManager
|
||||
.getProperty(consumerKey);
|
||||
if (consumerList == null)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"No Configuration entry found for consumer list of event Dispatcher: \""
|
||||
+ consumerKey + "\"");
|
||||
}
|
||||
|
||||
// Consumer list format:
|
||||
// <consumer-name>:<mode>, ...
|
||||
String[] consumerStanza = consumerList.trim().split(
|
||||
"\\s*,\\s*");
|
||||
|
||||
// I think this should be a fatal error.. --lcs
|
||||
if (consumerStanza.length < 1)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Cannot initialize Dispatcher, malformed Configuration value for "
|
||||
+ consumerKey);
|
||||
}
|
||||
|
||||
ConsumerProfile consumerProfile = null;
|
||||
|
||||
// parts: 0 is name, part 1 is mode.
|
||||
for (int i = 0; i < consumerStanza.length; i++)
|
||||
{
|
||||
consumerProfile = ConsumerProfile
|
||||
.makeConsumerProfile(consumerStanza[i]);
|
||||
consumerProfile.getConsumer().initialize();
|
||||
|
||||
dispatcher.addConsumerProfile(consumerProfile);
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Constructor not found for event dispatcher="
|
||||
+ dispatcherName, e);
|
||||
}
|
||||
catch (InvocationTargetException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Error creating event dispatcher=" + dispatcherName,
|
||||
e);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Dispatcher/Consumer class not found for event dispatcher="
|
||||
+ dispatcherName, e);
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Dispatcher/Consumer instantiation failure for event dispatcher="
|
||||
+ dispatcherName, e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Dispatcher/Consumer access failure for event dispatcher="
|
||||
+ dispatcherName, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Requested Dispatcher Does Not Exist In DSpace Configuration!");
|
||||
}
|
||||
|
||||
return dispatcher;
|
||||
|
||||
}
|
||||
|
||||
public void activateObject(Object arg0, Object arg1) throws Exception
|
||||
{
|
||||
// No-op
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public void destroyObject(Object key, Object dispatcher)
|
||||
throws Exception
|
||||
{
|
||||
Context ctx = new Context();
|
||||
|
||||
for (Iterator ci = ((Dispatcher) dispatcher).getConsumers()
|
||||
.iterator(); ci.hasNext();)
|
||||
{
|
||||
ConsumerProfile cp = (ConsumerProfile) ci.next();
|
||||
if (cp != null)
|
||||
cp.getConsumer().finish(ctx);
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public void passivateObject(Object arg0, Object arg1) throws Exception
|
||||
{
|
||||
// No-op
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public boolean validateObject(Object arg0, Object arg1)
|
||||
{
|
||||
// No-op
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks through the configuration for dispatcher configurations and
|
||||
* loads one of each into a HashMap. This Map will be used to clone new
|
||||
* objects when the pool needs them.
|
||||
*
|
||||
* Looks for configuration properties like:
|
||||
*
|
||||
* <pre>
|
||||
* # class of dispatcher "default"
|
||||
* event.dispatcher.default = org.dspace.event.BasicDispatcher
|
||||
* # list of consumers followed by filters for each, format is
|
||||
* # <consumerClass>:<filter>[:<anotherFilter>..] , ...
|
||||
* # and each filter is expressed as:
|
||||
* # <objectType>[|<objectType> ...] + <eventType>[|<eventType> ..]
|
||||
* org.dspace.event.TestConsumer:all+all, \
|
||||
* org.dspace.eperson.SubscribeConsumer:Item+CREATE|DELETE:Collection+ADD, ...
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
private void parseEventConfig()
|
||||
{
|
||||
Enumeration propertyNames = ConfigurationManager.propertyNames();
|
||||
while (propertyNames.hasMoreElements())
|
||||
{
|
||||
String ckey = ((String) propertyNames.nextElement()).trim();
|
||||
|
||||
if (ckey.startsWith(PROP_PFX) && ckey.endsWith(".class"))
|
||||
{
|
||||
String name = ckey.substring(PROP_PFX.length(), ckey
|
||||
.length() - 6);
|
||||
String dispatcherClass = ConfigurationManager
|
||||
.getProperty(ckey);
|
||||
|
||||
// Can we grab all of the consumers configured for this
|
||||
// dispatcher
|
||||
// and store them also? Then there is no
|
||||
// ConfigurationManager call
|
||||
// upon other makeObject(key) requests resulting in a faster
|
||||
// pool
|
||||
// get.
|
||||
|
||||
dispatchers.put(name, dispatcherClass);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
141
dspace-api/src/main/java/org/dspace/event/TestConsumer.java
Normal file
141
dspace-api/src/main/java/org/dspace/event/TestConsumer.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* TestConsumer.java
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.event;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
|
||||
/**
|
||||
* Demonstration and test consumer for the event system. This consumer only
|
||||
* makes an entry in the log, and on an output stream, for each event it
|
||||
* receives. It also logs when consume() and end() get called. It is intended
|
||||
* for testing, exploring, and debugging the event system.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class TestConsumer implements Consumer
|
||||
{
|
||||
// Log4j logger
|
||||
private static Logger log = Logger.getLogger(TestConsumer.class);
|
||||
|
||||
// Send diagnostic output here - set to null to turn it off.
|
||||
private static PrintStream out = ConfigurationManager
|
||||
.getBooleanProperty("testConsumer.verbose") ? System.out : null;
|
||||
|
||||
static final DateFormat df = new SimpleDateFormat(
|
||||
"dd-MMM-yyyy HH:mm:ss.SSS Z");
|
||||
|
||||
public void initialize() throws Exception
|
||||
{
|
||||
log.info("EVENT: called TestConsumer.initialize();");
|
||||
if (out != null)
|
||||
out.println("TestConsumer.initialize();");
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a content event - display it in detail.
|
||||
*
|
||||
* @param ctx
|
||||
* DSpace context
|
||||
* @param event
|
||||
* Content event
|
||||
*/
|
||||
public void consume(Context ctx, Event event) throws Exception
|
||||
{
|
||||
EPerson ep = ctx.getCurrentUser();
|
||||
String user = (ep == null) ? "(none)" : ep.getEmail();
|
||||
String detail = event.getDetail();
|
||||
|
||||
String msg = "EVENT: called TestConsumer.consume(): EventType="
|
||||
+ event.getEventTypeAsString()
|
||||
+ ", SubjectType="
|
||||
+ event.getSubjectTypeAsString()
|
||||
+ ", SubjectID="
|
||||
+ String.valueOf(event.getSubjectID())
|
||||
+ ", ObjectType="
|
||||
+ event.getObjectTypeAsString()
|
||||
+ ", ObjectID="
|
||||
+ String.valueOf(event.getObjectID())
|
||||
+ ", TimeStamp="
|
||||
+ df.format(new Date(event.getTimeStamp()))
|
||||
+ ", user=\""
|
||||
+ user
|
||||
+ "\""
|
||||
+ ", extraLog=\""
|
||||
+ ctx.getExtraLogInfo()
|
||||
+ "\""
|
||||
+ ", dispatcher="
|
||||
+ String.valueOf(event.getDispatcher())
|
||||
+ ", detail="
|
||||
+ (detail == null ? "[null]" : "\"" + detail + "\"")
|
||||
+ ", transactionID="
|
||||
+ (event.getTransactionID() == null ? "[null]" : "\""
|
||||
+ event.getTransactionID() + "\"") + ", context="
|
||||
+ ctx.toString();
|
||||
log.info(msg);
|
||||
if (out != null)
|
||||
out.println("TestConsumer.consume(): " + msg);
|
||||
}
|
||||
|
||||
public void end(Context ctx) throws Exception
|
||||
{
|
||||
log.info("EVENT: called TestConsumer.end();");
|
||||
if (out != null)
|
||||
out.println("TestConsumer.end();");
|
||||
|
||||
}
|
||||
|
||||
public void finish(Context ctx) throws Exception
|
||||
{
|
||||
log.info("EVENT: called TestConsumer.finish();");
|
||||
if (out != null)
|
||||
out.println("TestConsumer.finish();");
|
||||
|
||||
}
|
||||
|
||||
}
|
282
dspace-api/src/main/java/org/dspace/search/SearchConsumer.java
Normal file
282
dspace-api/src/main/java/org/dspace/search/SearchConsumer.java
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* SearchConsumer.java
|
||||
*
|
||||
* Location: $URL$
|
||||
*
|
||||
* Version: $Revision$
|
||||
*
|
||||
* Date: $Date$
|
||||
*
|
||||
* 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.search;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.event.Consumer;
|
||||
import org.dspace.event.Event;
|
||||
|
||||
/**
|
||||
* Class for updating search indices from content events.
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class SearchConsumer implements Consumer
|
||||
{
|
||||
/** log4j logger */
|
||||
private static Logger log = Logger.getLogger(SearchConsumer.class);
|
||||
|
||||
// collect Items, Collections, Communities newly created.
|
||||
private Set objectsCreated = null;
|
||||
|
||||
// collect Items, Collections, Communities that need reindexing
|
||||
private Set objectsToUpdate = null;
|
||||
|
||||
// handles to delete since IDs are not useful by now.
|
||||
private Set handlesToDelete = null;
|
||||
|
||||
public void initialize() throws Exception
|
||||
{
|
||||
// No-op
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a content event -- just build the sets of objects to add (new) to
|
||||
* the index, update, and delete.
|
||||
*
|
||||
* @param ctx
|
||||
* DSpace context
|
||||
* @param event
|
||||
* Content event
|
||||
*/
|
||||
public void consume(Context ctx, Event event) throws Exception
|
||||
{
|
||||
|
||||
if (objectsCreated == null)
|
||||
{
|
||||
objectsCreated = new HashSet();
|
||||
objectsToUpdate = new HashSet();
|
||||
handlesToDelete = new HashSet();
|
||||
}
|
||||
|
||||
int st = event.getSubjectType();
|
||||
if (!(st == Constants.ITEM || st == Constants.BUNDLE
|
||||
|| st == Constants.COLLECTION || st == Constants.COMMUNITY))
|
||||
{
|
||||
log
|
||||
.warn("SearchConsumer should not have been given this kind of Subject in an event, skipping: "
|
||||
+ event.toString());
|
||||
return;
|
||||
}
|
||||
DSpaceObject dso = null;
|
||||
// EVENT FIXME This call to getSubjectOfEvent is catching a SQLException
|
||||
// but other Consumers don't
|
||||
try
|
||||
{
|
||||
dso = event.getSubject(ctx);
|
||||
}
|
||||
catch (SQLException se)
|
||||
{
|
||||
}
|
||||
|
||||
// If event subject is a Bundle and event was Add or Remove,
|
||||
// transform the event to be a Modify on the owning Item.
|
||||
// It could be a new bitstream in the TEXT bundle which
|
||||
// would change the index.
|
||||
int et = event.getEventType();
|
||||
if (st == Constants.BUNDLE)
|
||||
{
|
||||
if ((et == Event.ADD || et == Event.REMOVE) && dso != null
|
||||
&& ((Bundle) dso).getName().equals("TEXT"))
|
||||
{
|
||||
st = Constants.ITEM;
|
||||
et = Event.MODIFY;
|
||||
dso = ((Bundle) dso).getItems()[0];
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Transforming Bundle event into MODIFY of Item "
|
||||
+ dso.getHandle());
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
switch (et)
|
||||
{
|
||||
case Event.CREATE:
|
||||
if (dso == null)
|
||||
log.warn("CREATE event, could not get object for "
|
||||
+ event.getSubjectTypeAsString() + " id="
|
||||
+ String.valueOf(event.getSubjectID())
|
||||
+ ", perhaps it has been deleted.");
|
||||
else
|
||||
objectsCreated.add(dso);
|
||||
break;
|
||||
case Event.MODIFY:
|
||||
case Event.MODIFY_METADATA:
|
||||
if (dso == null)
|
||||
log.warn("MODIFY event, could not get object for "
|
||||
+ event.getSubjectTypeAsString() + " id="
|
||||
+ String.valueOf(event.getSubjectID())
|
||||
+ ", perhaps it has been deleted.");
|
||||
else
|
||||
objectsToUpdate.add(dso);
|
||||
break;
|
||||
case Event.DELETE:
|
||||
String detail = event.getDetail();
|
||||
if (detail == null)
|
||||
log.warn("got null detail on DELETE event, skipping it.");
|
||||
else
|
||||
handlesToDelete.add(detail);
|
||||
break;
|
||||
default:
|
||||
log
|
||||
.warn("SearchConsumer should not have been given a event of type="
|
||||
+ event.getEventTypeAsString()
|
||||
+ " on subject="
|
||||
+ event.getSubjectTypeAsString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process sets of objects to add, update, and delete in index. Correct for
|
||||
* interactions between the sets -- e.g. objects which were deleted do not
|
||||
* need to be added or updated, new objects don't also need an update, etc.
|
||||
*/
|
||||
public void end(Context ctx) throws Exception
|
||||
{
|
||||
// add new created items to index, unless they were deleted.
|
||||
for (Iterator ii = objectsCreated.iterator(); ii.hasNext();)
|
||||
{
|
||||
DSpaceObject ic = (DSpaceObject) ii.next();
|
||||
if (ic.getType() != Constants.ITEM || ((Item) ic).isArchived())
|
||||
{
|
||||
// if handle is NOT in list of deleted objects, index it:
|
||||
String hdl = ic.getHandle();
|
||||
if (hdl != null && !handlesToDelete.contains(hdl))
|
||||
{
|
||||
try
|
||||
{
|
||||
DSIndexer.indexContent(ctx, ic);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Indexed NEW "
|
||||
+ Constants.typeText[ic.getType()]
|
||||
+ ", id=" + String.valueOf(ic.getID())
|
||||
+ ", handle=" + hdl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Failed while indexing new object: ", e);
|
||||
objectsCreated = null;
|
||||
objectsToUpdate = null;
|
||||
handlesToDelete = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove it from modified list since we just indexed it.
|
||||
objectsToUpdate.remove(ic);
|
||||
}
|
||||
|
||||
// update the changed Items not deleted because they were on create list
|
||||
for (Iterator ii = objectsToUpdate.iterator(); ii.hasNext();)
|
||||
{
|
||||
DSpaceObject iu = (DSpaceObject) ii.next();
|
||||
if (iu.getType() != Constants.ITEM || ((Item) iu).isArchived())
|
||||
{
|
||||
// if handle is NOT in list of deleted objects, index it:
|
||||
String hdl = iu.getHandle();
|
||||
if (hdl != null && !handlesToDelete.contains(hdl))
|
||||
{
|
||||
try
|
||||
{
|
||||
DSIndexer.reIndexContent(ctx, iu);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("RE-Indexed "
|
||||
+ Constants.typeText[iu.getType()]
|
||||
+ ", id=" + String.valueOf(iu.getID())
|
||||
+ ", handle=" + hdl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Failed while RE-indexing object: ", e);
|
||||
objectsCreated = null;
|
||||
objectsToUpdate = null;
|
||||
handlesToDelete = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator ii = handlesToDelete.iterator(); ii.hasNext();)
|
||||
{
|
||||
String hdl = (String) ii.next();
|
||||
try
|
||||
{
|
||||
DSIndexer.unIndexContent(ctx, hdl);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("UN-Indexed Item, handle=" + hdl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Failed while UN-indexing object: " + hdl, e);
|
||||
objectsCreated = new HashSet();
|
||||
objectsToUpdate = new HashSet();
|
||||
handlesToDelete = new HashSet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// "free" the resources
|
||||
objectsCreated = null;
|
||||
objectsToUpdate = null;
|
||||
handlesToDelete = null;
|
||||
}
|
||||
|
||||
public void finish(Context ctx) throws Exception
|
||||
{
|
||||
// No-op
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -52,7 +52,6 @@ import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -356,9 +355,6 @@ public class WorkflowItem implements InProgressSubmission
|
||||
|
||||
// Update ourselves
|
||||
DatabaseManager.update(ourContext, wfRow);
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,9 +366,6 @@ public class WorkflowItem implements InProgressSubmission
|
||||
// Remove from cache
|
||||
ourContext.removeCached(this, getID());
|
||||
|
||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
||||
|
||||
// delete any pending tasks
|
||||
WorkflowManager.deleteTasks(ourContext, this);
|
||||
|
||||
|
@@ -68,7 +68,6 @@ import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.history.HistoryManager;
|
||||
import org.dspace.storage.rdbms.DatabaseManager;
|
||||
import org.dspace.storage.rdbms.TableRow;
|
||||
import org.dspace.storage.rdbms.TableRowIterator;
|
||||
@@ -195,10 +194,6 @@ public class WorkflowManager
|
||||
wfi.setMultipleTitles(wsi.hasMultipleTitles());
|
||||
wfi.setPublishedBefore(wsi.isPublishedBefore());
|
||||
|
||||
// Write history creation event
|
||||
HistoryManager.saveHistory(c, wfi, HistoryManager.CREATE, c
|
||||
.getCurrentUser(), c.getExtraLogInfo());
|
||||
|
||||
// remove the WorkspaceItem
|
||||
wsi.deleteWrapper();
|
||||
|
||||
|
Reference in New Issue
Block a user