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.setDispatcher(dispatcher);
|
||||||
checker.setCollector(logger);
|
checker.setCollector(logger);
|
||||||
checker.process();
|
checker.process();
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -170,6 +170,7 @@ public class ItemImport
|
|||||||
String mapfile = null;
|
String mapfile = null;
|
||||||
String eperson = null; // db ID or email
|
String eperson = null; // db ID or email
|
||||||
String[] collections = null; // db ID or handles
|
String[] collections = null; // db ID or handles
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
if (line.hasOption('h'))
|
if (line.hasOption('h'))
|
||||||
{
|
{
|
||||||
@@ -439,6 +440,7 @@ public class ItemImport
|
|||||||
c.abort();
|
c.abort();
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.out.println(e);
|
System.out.println(e);
|
||||||
|
status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapOut != null)
|
if (mapOut != null)
|
||||||
@@ -450,6 +452,7 @@ public class ItemImport
|
|||||||
{
|
{
|
||||||
System.out.println("***End of Test Run***");
|
System.out.println("***End of Test Run***");
|
||||||
}
|
}
|
||||||
|
System.exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addItems(Context c, Collection[] mycollections,
|
private void addItems(Context c, Collection[] mycollections,
|
||||||
|
@@ -101,6 +101,8 @@ public class MediaFilterManager
|
|||||||
// create an options object and populate it
|
// create an options object and populate it
|
||||||
CommandLineParser parser = new PosixParser();
|
CommandLineParser parser = new PosixParser();
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
Options options = new Options();
|
Options options = new Options();
|
||||||
|
|
||||||
options.addOption("v", "verbose", false,
|
options.addOption("v", "verbose", false,
|
||||||
@@ -217,6 +219,10 @@ public class MediaFilterManager
|
|||||||
c.complete();
|
c.complete();
|
||||||
c = null;
|
c = null;
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (c != null)
|
if (c != null)
|
||||||
@@ -224,6 +230,7 @@ public class MediaFilterManager
|
|||||||
c.abort();
|
c.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void applyFiltersAllItems(Context c) throws Exception
|
public static void applyFiltersAllItems(Context c) throws Exception
|
||||||
|
@@ -215,6 +215,7 @@ public class METSExport
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.abort();
|
context.abort();
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -138,6 +138,7 @@ public class FixDefaultPolicies
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.complete();
|
c.complete();
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -99,6 +99,7 @@ public class PolicySet
|
|||||||
groupID, isReplace, false);
|
groupID, isReplace, false);
|
||||||
|
|
||||||
c.complete();
|
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)
|
public static void main(String[] argv)
|
||||||
{
|
{
|
||||||
Context context = null;
|
Context context = null;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -78,6 +79,7 @@ public class InitializeBrowse
|
|||||||
}
|
}
|
||||||
catch (SQLException sqle)
|
catch (SQLException sqle)
|
||||||
{
|
{
|
||||||
|
status = 1;
|
||||||
if (context != null)
|
if (context != null)
|
||||||
{
|
{
|
||||||
context.abort();
|
context.abort();
|
||||||
@@ -86,5 +88,9 @@ public class InitializeBrowse
|
|||||||
System.err.println("Error: Browse index NOT created");
|
System.err.println("Error: Browse index NOT created");
|
||||||
sqle.printStackTrace();
|
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.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.storage.bitstore.BitstreamStorageManager;
|
import org.dspace.storage.bitstore.BitstreamStorageManager;
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
@@ -81,6 +82,12 @@ public class Bitstream extends DSpaceObject
|
|||||||
/** The bitstream format corresponding to this bitstream */
|
/** The bitstream format corresponding to this bitstream */
|
||||||
private BitstreamFormat bitstreamFormat;
|
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
|
* Private constructor for creating a Bitstream object based on the contents
|
||||||
* of a DB table row.
|
* of a DB table row.
|
||||||
@@ -114,6 +121,9 @@ public class Bitstream extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("bitstream_id"));
|
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 bitstream = find(context, bitstreamID);
|
||||||
bitstream.setFormat(null);
|
bitstream.setFormat(null);
|
||||||
|
|
||||||
|
context.addEvent(new Event(Event.CREATE, Constants.BITSTREAM, bitstreamID, null));
|
||||||
|
|
||||||
return bitstream;
|
return bitstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +235,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
Bitstream bitstream = find(context, bitstreamID);
|
Bitstream bitstream = find(context, bitstreamID);
|
||||||
bitstream.setFormat(null);
|
bitstream.setFormat(null);
|
||||||
|
|
||||||
|
context.addEvent(new Event(Event.CREATE, Constants.BITSTREAM, bitstreamID, "REGISTER"));
|
||||||
|
|
||||||
return bitstream;
|
return bitstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +275,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
public void setSequenceID(int sid)
|
public void setSequenceID(int sid)
|
||||||
{
|
{
|
||||||
bRow.setColumn("sequence_id", sid);
|
bRow.setColumn("sequence_id", sid);
|
||||||
|
modifiedMetadata = true;
|
||||||
|
addDetails("SequenceID");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,6 +299,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
public void setName(String n)
|
public void setName(String n)
|
||||||
{
|
{
|
||||||
bRow.setColumn("name", n);
|
bRow.setColumn("name", n);
|
||||||
|
modifiedMetadata = true;
|
||||||
|
addDetails("Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,6 +324,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
public void setSource(String n)
|
public void setSource(String n)
|
||||||
{
|
{
|
||||||
bRow.setColumn("source", n);
|
bRow.setColumn("source", n);
|
||||||
|
modifiedMetadata = true;
|
||||||
|
addDetails("Source");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -328,6 +348,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
public void setDescription(String n)
|
public void setDescription(String n)
|
||||||
{
|
{
|
||||||
bRow.setColumn("description", 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!
|
// but we need to find the unknown format!
|
||||||
setFormat(null);
|
setFormat(null);
|
||||||
bRow.setColumn("user_format_description", desc);
|
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
|
// Update the ID in the table row
|
||||||
bRow.setColumn("bitstream_format_id", bitstreamFormat.getID());
|
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",
|
log.info(LogManager.getHeader(bContext, "update_bitstream",
|
||||||
"bitstream_id=" + getID()));
|
"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);
|
DatabaseManager.update(bContext, bRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,6 +527,8 @@ public class Bitstream extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(bContext, "delete_bitstream",
|
log.info(LogManager.getHeader(bContext, "delete_bitstream",
|
||||||
"bitstream_id=" + getID()));
|
"bitstream_id=" + getID()));
|
||||||
|
|
||||||
|
bContext.addEvent(new Event(Event.DELETE, Constants.BITSTREAM, getID(), String.valueOf(getSequenceID())));
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
bContext.removeCached(this, getID());
|
bContext.removeCached(this, getID());
|
||||||
|
|
||||||
@@ -541,7 +580,7 @@ public class Bitstream extends DSpaceObject
|
|||||||
bRow.getIntColumn("bitstream_id"));
|
bRow.getIntColumn("bitstream_id"));
|
||||||
|
|
||||||
// Build a list of Bundle objects
|
// Build a list of Bundle objects
|
||||||
List bundles = new ArrayList();
|
List<Bundle> bundles = new ArrayList<Bundle>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
|
@@ -53,6 +53,7 @@ import org.dspace.authorize.AuthorizeManager;
|
|||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -80,7 +81,13 @@ public class Bundle extends DSpaceObject
|
|||||||
private TableRow bundleRow;
|
private TableRow bundleRow;
|
||||||
|
|
||||||
/** The bitstreams in this bundle */
|
/** 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
|
* Construct a bundle object with the given table row
|
||||||
@@ -94,7 +101,7 @@ public class Bundle extends DSpaceObject
|
|||||||
{
|
{
|
||||||
ourContext = context;
|
ourContext = context;
|
||||||
bundleRow = row;
|
bundleRow = row;
|
||||||
bitstreams = new ArrayList();
|
bitstreams = new ArrayList<Bitstream>();
|
||||||
|
|
||||||
// Get bitstreams
|
// Get bitstreams
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(
|
TableRowIterator tri = DatabaseManager.queryTable(
|
||||||
@@ -126,6 +133,8 @@ public class Bundle extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("bundle_id"));
|
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="
|
log.info(LogManager.getHeader(context, "create_bundle", "bundle_id="
|
||||||
+ row.getIntColumn("bundle_id")));
|
+ row.getIntColumn("bundle_id")));
|
||||||
|
|
||||||
|
context.addEvent(new Event(Event.CREATE, Constants.BUNDLE, row.getIntColumn("bundle_id"), null));
|
||||||
|
|
||||||
return new Bundle(context, row);
|
return new Bundle(context, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +236,7 @@ public class Bundle extends DSpaceObject
|
|||||||
public void setName(String name)
|
public void setName(String name)
|
||||||
{
|
{
|
||||||
bundleRow.setColumn("name", name);
|
bundleRow.setColumn("name", name);
|
||||||
|
modifiedMetadata = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,6 +258,7 @@ public class Bundle extends DSpaceObject
|
|||||||
public void setPrimaryBitstreamID(int bitstreamID)
|
public void setPrimaryBitstreamID(int bitstreamID)
|
||||||
{
|
{
|
||||||
bundleRow.setColumn("primary_bitstream_id", bitstreamID);
|
bundleRow.setColumn("primary_bitstream_id", bitstreamID);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,7 +322,7 @@ public class Bundle extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Item[] getItems() throws SQLException
|
public Item[] getItems() throws SQLException
|
||||||
{
|
{
|
||||||
List items = new ArrayList();
|
List<Item> items = new ArrayList<Item>();
|
||||||
|
|
||||||
// Get items
|
// Get items
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(
|
TableRowIterator tri = DatabaseManager.queryTable(
|
||||||
@@ -421,6 +434,8 @@ public class Bundle extends DSpaceObject
|
|||||||
// Add the bitstream object
|
// Add the bitstream object
|
||||||
bitstreams.add(b);
|
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
|
// copy authorization policies from bundle to bitstream
|
||||||
// FIXME: multiple inclusion is affected by this...
|
// FIXME: multiple inclusion is affected by this...
|
||||||
AuthorizeManager.inheritPolicies(ourContext, this, b);
|
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
|
// Delete the mapping row
|
||||||
DatabaseManager.updateQuery(ourContext,
|
DatabaseManager.updateQuery(ourContext,
|
||||||
"DELETE FROM bundle2bitstream WHERE bundle_id= ? "+
|
"DELETE FROM bundle2bitstream WHERE bundle_id= ? "+
|
||||||
@@ -505,6 +522,17 @@ public class Bundle extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(ourContext, "update_bundle", "bundle_id="
|
log.info(LogManager.getHeader(ourContext, "update_bundle", "bundle_id="
|
||||||
+ getID()));
|
+ 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);
|
DatabaseManager.update(ourContext, bundleRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +546,8 @@ public class Bundle extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(ourContext, "delete_bundle", "bundle_id="
|
log.info(LogManager.getHeader(ourContext, "delete_bundle", "bundle_id="
|
||||||
+ getID()));
|
+ getID()));
|
||||||
|
|
||||||
|
ourContext.addEvent(new Event(Event.DELETE, Constants.BUNDLE, getID(), getName()));
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
ourContext.removeCached(this, getID());
|
ourContext.removeCached(this, getID());
|
||||||
|
|
||||||
|
@@ -41,7 +41,9 @@ package org.dspace.content;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
@@ -57,9 +59,8 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.I18nUtil;
|
import org.dspace.core.I18nUtil;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.handle.HandleManager;
|
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.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -99,6 +100,12 @@ public class Collection extends DSpaceObject
|
|||||||
/** Our Handle */
|
/** Our Handle */
|
||||||
private String 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
|
* Groups corresponding to workflow steps - NOTE these start from one, so
|
||||||
* workflowGroups[0] corresponds to workflow_step_1.
|
* workflowGroups[0] corresponds to workflow_step_1.
|
||||||
@@ -162,6 +169,9 @@ public class Collection extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("collection_id"));
|
context.cache(this, row.getIntColumn("collection_id"));
|
||||||
|
|
||||||
|
modified = modifiedMetadata = false;
|
||||||
|
clearDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,8 +260,7 @@ public class Collection extends DSpaceObject
|
|||||||
myPolicy.setGroup(anonymousGroup);
|
myPolicy.setGroup(anonymousGroup);
|
||||||
myPolicy.update();
|
myPolicy.update();
|
||||||
|
|
||||||
HistoryManager.saveHistory(context, c, HistoryManager.CREATE, context
|
context.addEvent(new Event(Event.CREATE, Constants.COLLECTION, c.getID(), c.handle));
|
||||||
.getCurrentUser(), context.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(context, "create_collection",
|
log.info(LogManager.getHeader(context, "create_collection",
|
||||||
"collection_id=" + row.getIntColumn("collection_id"))
|
"collection_id=" + row.getIntColumn("collection_id"))
|
||||||
@@ -275,7 +284,7 @@ public class Collection extends DSpaceObject
|
|||||||
TableRowIterator tri = DatabaseManager.queryTable(context, "collection",
|
TableRowIterator tri = DatabaseManager.queryTable(context, "collection",
|
||||||
"SELECT * FROM collection ORDER BY name");
|
"SELECT * FROM collection ORDER BY name");
|
||||||
|
|
||||||
List collections = new ArrayList();
|
List<Collection> collections = new ArrayList<Collection>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -350,8 +359,19 @@ public class Collection extends DSpaceObject
|
|||||||
return collectionRow.getIntColumn("collection_id");
|
return collectionRow.getIntColumn("collection_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.dspace.content.DSpaceObject#getHandle()
|
||||||
|
*/
|
||||||
public String 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;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,6 +417,13 @@ public class Collection extends DSpaceObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
collectionRow.setColumn(field, value);
|
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()));
|
+ newLogo.getID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modified = true;
|
||||||
return logo;
|
return logo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +555,7 @@ public class Collection extends DSpaceObject
|
|||||||
{
|
{
|
||||||
collectionRow.setColumn("workflow_step_" + step, g.getID());
|
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);
|
AuthorizeManager.addPolicy(ourContext, this, Constants.ADD, submitters);
|
||||||
|
|
||||||
|
modified = true;
|
||||||
return submitters;
|
return submitters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,6 +654,7 @@ public class Collection extends DSpaceObject
|
|||||||
admins);
|
admins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modified = true;
|
||||||
return admins;
|
return admins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,6 +735,7 @@ public class Collection extends DSpaceObject
|
|||||||
{
|
{
|
||||||
collectionRow.setColumn("license", license);
|
collectionRow.setColumn("license", license);
|
||||||
}
|
}
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -742,6 +774,7 @@ public class Collection extends DSpaceObject
|
|||||||
"collection_id=" + getID() + ",template_item_id="
|
"collection_id=" + getID() + ",template_item_id="
|
||||||
+ template.getID()));
|
+ template.getID()));
|
||||||
}
|
}
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -773,6 +806,7 @@ public class Collection extends DSpaceObject
|
|||||||
template.delete();
|
template.delete();
|
||||||
template = null;
|
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());
|
row.setColumn("item_id", item.getID());
|
||||||
|
|
||||||
DatabaseManager.update(ourContext, row);
|
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= ? ",
|
"AND item_id= ? ",
|
||||||
getID(), item.getID());
|
getID(), item.getID());
|
||||||
|
|
||||||
|
ourContext.addEvent(new Event(Event.REMOVE, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle()));
|
||||||
|
|
||||||
// Is the item an orphan?
|
// Is the item an orphan?
|
||||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||||
"SELECT * FROM collection2item WHERE item_id= ? ",
|
"SELECT * FROM collection2item WHERE item_id= ? ",
|
||||||
@@ -864,17 +902,22 @@ public class Collection extends DSpaceObject
|
|||||||
// Check authorisation
|
// Check authorisation
|
||||||
canEdit();
|
canEdit();
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(ourContext, "update_collection",
|
log.info(LogManager.getHeader(ourContext, "update_collection",
|
||||||
"collection_id=" + getID()));
|
"collection_id=" + getID()));
|
||||||
|
|
||||||
DatabaseManager.update(ourContext, collectionRow);
|
DatabaseManager.update(ourContext, collectionRow);
|
||||||
|
|
||||||
// reindex this collection (could be smarter, to only do when name
|
if (modified)
|
||||||
// changes)
|
{
|
||||||
DSIndexer.reIndexContent(ourContext, this);
|
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
|
public boolean canEditBoolean() throws java.sql.SQLException
|
||||||
@@ -928,15 +971,11 @@ public class Collection extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(ourContext, "delete_collection",
|
log.info(LogManager.getHeader(ourContext, "delete_collection",
|
||||||
"collection_id=" + getID()));
|
"collection_id=" + getID()));
|
||||||
|
|
||||||
// remove from index
|
ourContext.addEvent(new Event(Event.DELETE, Constants.COLLECTION, getID(), getHandle()));
|
||||||
DSIndexer.unIndexContent(ourContext, this);
|
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
ourContext.removeCached(this, getID());
|
ourContext.removeCached(this, getID());
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
// remove subscriptions - hmm, should this be in Subscription.java?
|
// remove subscriptions - hmm, should this be in Subscription.java?
|
||||||
DatabaseManager.updateQuery(ourContext,
|
DatabaseManager.updateQuery(ourContext,
|
||||||
"DELETE FROM subscription WHERE collection_id= ? ",
|
"DELETE FROM subscription WHERE collection_id= ? ",
|
||||||
@@ -1062,7 +1101,7 @@ public class Collection extends DSpaceObject
|
|||||||
getID());
|
getID());
|
||||||
|
|
||||||
// Build a list of Community objects
|
// Build a list of Community objects
|
||||||
List communities = new ArrayList();
|
List<Community> communities = new ArrayList<Community>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -1162,7 +1201,7 @@ public class Collection extends DSpaceObject
|
|||||||
public static Collection[] findAuthorized(Context context, Community comm,
|
public static Collection[] findAuthorized(Context context, Community comm,
|
||||||
int actionID) throws java.sql.SQLException
|
int actionID) throws java.sql.SQLException
|
||||||
{
|
{
|
||||||
List myResults = new ArrayList();
|
List<Collection> myResults = new ArrayList<Collection>();
|
||||||
|
|
||||||
Collection[] myCollections = null;
|
Collection[] myCollections = null;
|
||||||
|
|
||||||
|
@@ -55,9 +55,8 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.I18nUtil;
|
import org.dspace.core.I18nUtil;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.handle.HandleManager;
|
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.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -89,6 +88,12 @@ public class Community extends DSpaceObject
|
|||||||
/** Handle, if any */
|
/** Handle, if any */
|
||||||
private String 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a community object from a database row.
|
* Construct a community object from a database row.
|
||||||
*
|
*
|
||||||
@@ -118,6 +123,9 @@ public class Community extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("community_id"));
|
context.cache(this, row.getIntColumn("community_id"));
|
||||||
|
|
||||||
|
modified = modifiedMetadata = false;
|
||||||
|
clearDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,8 +206,11 @@ public class Community extends DSpaceObject
|
|||||||
myPolicy.setGroup(anonymousGroup);
|
myPolicy.setGroup(anonymousGroup);
|
||||||
myPolicy.update();
|
myPolicy.update();
|
||||||
|
|
||||||
HistoryManager.saveHistory(context, c, HistoryManager.CREATE, context
|
context.addEvent(new Event(Event.CREATE, Constants.COMMUNITY, c.getID(), c.handle));
|
||||||
.getCurrentUser(), context.getExtraLogInfo());
|
|
||||||
|
// 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",
|
log.info(LogManager.getHeader(context, "create_community",
|
||||||
"community_id=" + row.getIntColumn("community_id"))
|
"community_id=" + row.getIntColumn("community_id"))
|
||||||
@@ -222,7 +233,7 @@ public class Community extends DSpaceObject
|
|||||||
TableRowIterator tri = DatabaseManager.queryTable(context, "community",
|
TableRowIterator tri = DatabaseManager.queryTable(context, "community",
|
||||||
"SELECT * FROM community ORDER BY name");
|
"SELECT * FROM community ORDER BY name");
|
||||||
|
|
||||||
List communities = new ArrayList();
|
List<Community> communities = new ArrayList<Community>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -268,7 +279,7 @@ public class Community extends DSpaceObject
|
|||||||
+ "(SELECT child_comm_id FROM community2community) "
|
+ "(SELECT child_comm_id FROM community2community) "
|
||||||
+ "ORDER BY name");
|
+ "ORDER BY name");
|
||||||
|
|
||||||
List topCommunities = new ArrayList();
|
List<Community> topCommunities = new ArrayList<Community>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -306,8 +317,19 @@ public class Community extends DSpaceObject
|
|||||||
return communityRow.getIntColumn("community_id");
|
return communityRow.getIntColumn("community_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.dspace.content.DSpaceObject#getHandle()
|
||||||
|
*/
|
||||||
public String 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;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +375,13 @@ public class Community extends DSpaceObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
communityRow.setColumn(field, value);
|
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()));
|
+ newLogo.getID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modified = true;
|
||||||
return logo;
|
return logo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,16 +459,22 @@ public class Community extends DSpaceObject
|
|||||||
// Check authorisation
|
// Check authorisation
|
||||||
canEdit();
|
canEdit();
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(ourContext, "update_community",
|
log.info(LogManager.getHeader(ourContext, "update_community",
|
||||||
"community_id=" + getID()));
|
"community_id=" + getID()));
|
||||||
|
|
||||||
DatabaseManager.update(ourContext, communityRow);
|
DatabaseManager.update(ourContext, communityRow);
|
||||||
|
|
||||||
// now re-index this Community
|
if (modified)
|
||||||
DSIndexer.reIndexContent(ourContext, this);
|
{
|
||||||
|
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
|
public Collection[] getCollections() throws SQLException
|
||||||
{
|
{
|
||||||
List collections = new ArrayList();
|
List<Collection> collections = new ArrayList<Collection>();
|
||||||
|
|
||||||
// Get the table rows
|
// Get the table rows
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(
|
TableRowIterator tri = DatabaseManager.queryTable(
|
||||||
@@ -496,7 +532,7 @@ public class Community extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Community[] getSubcommunities() throws SQLException
|
public Community[] getSubcommunities() throws SQLException
|
||||||
{
|
{
|
||||||
List subcommunities = new ArrayList();
|
List<Community> subcommunities = new ArrayList<Community>();
|
||||||
|
|
||||||
// Get the table rows
|
// Get the table rows
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(
|
TableRowIterator tri = DatabaseManager.queryTable(
|
||||||
@@ -585,7 +621,7 @@ public class Community extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Community[] getAllParents() throws SQLException
|
public Community[] getAllParents() throws SQLException
|
||||||
{
|
{
|
||||||
List parentList = new ArrayList();
|
List<Community> parentList = new ArrayList<Community>();
|
||||||
Community parent = getParentCommunity();
|
Community parent = getParentCommunity();
|
||||||
|
|
||||||
while (parent != null)
|
while (parent != null)
|
||||||
@@ -649,6 +685,8 @@ public class Community extends DSpaceObject
|
|||||||
mappingRow.setColumn("community_id", getID());
|
mappingRow.setColumn("community_id", getID());
|
||||||
mappingRow.setColumn("collection_id", c.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);
|
DatabaseManager.update(ourContext, mappingRow);
|
||||||
}
|
}
|
||||||
// close the TableRowIterator to free up resources
|
// close the TableRowIterator to free up resources
|
||||||
@@ -702,6 +740,8 @@ public class Community extends DSpaceObject
|
|||||||
mappingRow.setColumn("parent_comm_id", getID());
|
mappingRow.setColumn("parent_comm_id", getID());
|
||||||
mappingRow.setColumn("child_comm_id", c.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);
|
DatabaseManager.update(ourContext, mappingRow);
|
||||||
}
|
}
|
||||||
// close the TableRowIterator to free up resources
|
// close the TableRowIterator to free up resources
|
||||||
@@ -728,6 +768,8 @@ public class Community extends DSpaceObject
|
|||||||
"DELETE FROM community2collection WHERE community_id= ? "+
|
"DELETE FROM community2collection WHERE community_id= ? "+
|
||||||
"AND collection_id= ? ", getID(), c.getID());
|
"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?
|
// Is the community an orphan?
|
||||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||||
"SELECT * FROM community2collection WHERE collection_id= ? ",
|
"SELECT * FROM community2collection WHERE collection_id= ? ",
|
||||||
@@ -774,6 +816,8 @@ public class Community extends DSpaceObject
|
|||||||
"DELETE FROM community2community WHERE parent_comm_id= ? " +
|
"DELETE FROM community2community WHERE parent_comm_id= ? " +
|
||||||
" AND child_comm_id= ? ", getID(),c.getID());
|
" 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?
|
// Is the subcommunity an orphan?
|
||||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||||
"SELECT * FROM community2community WHERE child_comm_id= ? ",
|
"SELECT * FROM community2community WHERE child_comm_id= ? ",
|
||||||
@@ -834,11 +878,7 @@ public class Community extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(ourContext, "delete_community",
|
log.info(LogManager.getHeader(ourContext, "delete_community",
|
||||||
"community_id=" + getID()));
|
"community_id=" + getID()));
|
||||||
|
|
||||||
// remove from the search index
|
ourContext.addEvent(new Event(Event.DELETE, Constants.COMMUNITY, getID(), getHandle()));
|
||||||
DSIndexer.unIndexContent(ourContext, this);
|
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
ourContext.removeCached(this, getID());
|
ourContext.removeCached(this, getID());
|
||||||
|
@@ -39,11 +39,53 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.content;
|
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
|
* Abstract base class for DSpace objects
|
||||||
*/
|
*/
|
||||||
public abstract class DSpaceObject
|
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
|
* Get the type of this object, found in Constants
|
||||||
*
|
*
|
||||||
@@ -65,4 +107,40 @@ public abstract class DSpaceObject
|
|||||||
* one
|
* one
|
||||||
*/
|
*/
|
||||||
public abstract String getHandle();
|
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.ConfigurationManager;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.handle.HandleManager;
|
import org.dspace.handle.HandleManager;
|
||||||
import org.dspace.search.DSIndexer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support to install item in the archive
|
* Support to install item in the archive
|
||||||
@@ -145,9 +144,6 @@ public class InstallItem
|
|||||||
// save changes ;-)
|
// save changes ;-)
|
||||||
item.update();
|
item.update();
|
||||||
|
|
||||||
// add item to search and browse indices
|
|
||||||
DSIndexer.indexContent(c, item);
|
|
||||||
|
|
||||||
// remove in-progress submission
|
// remove in-progress submission
|
||||||
is.deleteWrapper();
|
is.deleteWrapper();
|
||||||
|
|
||||||
|
@@ -61,11 +61,10 @@ import org.dspace.core.ConfigurationManager;
|
|||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.handle.HandleManager;
|
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.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -104,10 +103,10 @@ public class Item extends DSpaceObject
|
|||||||
private EPerson submitter;
|
private EPerson submitter;
|
||||||
|
|
||||||
/** The bundles in this item - kept in sync with DB */
|
/** 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. */
|
/** The Dublin Core metadata - a list of DCValue objects. */
|
||||||
private List dublinCore;
|
private List<DCValue> dublinCore;
|
||||||
|
|
||||||
/** Handle, if any */
|
/** Handle, if any */
|
||||||
private String handle;
|
private String handle;
|
||||||
@@ -118,6 +117,12 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
private boolean dublinCoreChanged;
|
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
|
* Construct an item with the given table row
|
||||||
*
|
*
|
||||||
@@ -132,7 +137,9 @@ public class Item extends DSpaceObject
|
|||||||
ourContext = context;
|
ourContext = context;
|
||||||
itemRow = row;
|
itemRow = row;
|
||||||
dublinCoreChanged = false;
|
dublinCoreChanged = false;
|
||||||
dublinCore = new ArrayList();
|
modified = false;
|
||||||
|
dublinCore = new ArrayList<DCValue>();
|
||||||
|
clearDetails();
|
||||||
|
|
||||||
// Get Dublin Core metadata
|
// Get Dublin Core metadata
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "MetadataValue",
|
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "MetadataValue",
|
||||||
@@ -247,8 +254,7 @@ public class Item extends DSpaceObject
|
|||||||
i.update();
|
i.update();
|
||||||
context.setIgnoreAuthorization(false);
|
context.setIgnoreAuthorization(false);
|
||||||
|
|
||||||
HistoryManager.saveHistory(context, i, HistoryManager.CREATE, context
|
context.addEvent(new Event(Event.CREATE, Constants.ITEM, i.getID(), null));
|
||||||
.getCurrentUser(), context.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(context, "create_item", "item_id="
|
log.info(LogManager.getHeader(context, "create_item", "item_id="
|
||||||
+ row.getIntColumn("item_id")));
|
+ row.getIntColumn("item_id")));
|
||||||
@@ -312,6 +318,14 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public String 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;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,6 +378,7 @@ public class Item extends DSpaceObject
|
|||||||
public void setArchived(boolean isArchived)
|
public void setArchived(boolean isArchived)
|
||||||
{
|
{
|
||||||
itemRow.setColumn("in_archive", isArchived);
|
itemRow.setColumn("in_archive", isArchived);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -375,6 +390,7 @@ public class Item extends DSpaceObject
|
|||||||
public void setOwningCollection(Collection c)
|
public void setOwningCollection(Collection c)
|
||||||
{
|
{
|
||||||
itemRow.setColumn("owning_collection", c.getID());
|
itemRow.setColumn("owning_collection", c.getID());
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -493,13 +509,9 @@ public class Item extends DSpaceObject
|
|||||||
String lang)
|
String lang)
|
||||||
{
|
{
|
||||||
// Build up list of matching values
|
// Build up list of matching values
|
||||||
List values = new ArrayList();
|
List<DCValue> values = new ArrayList<DCValue>();
|
||||||
Iterator i = dublinCore.iterator();
|
for (DCValue dcv : dublinCore)
|
||||||
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
{
|
||||||
DCValue dcv = (DCValue) i.next();
|
|
||||||
|
|
||||||
if (match(schema, element, qualifier, lang, dcv))
|
if (match(schema, element, qualifier, lang, dcv))
|
||||||
{
|
{
|
||||||
// We will return a copy of the object in case it is altered
|
// 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;
|
dcv.value = null;
|
||||||
}
|
}
|
||||||
dublinCore.add(dcv);
|
dublinCore.add(dcv);
|
||||||
|
addDetails(schema+"."+element+((qualifier==null)? "": "."+qualifier));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.length > 0)
|
if (values.length > 0)
|
||||||
@@ -752,13 +766,9 @@ public class Item extends DSpaceObject
|
|||||||
String lang)
|
String lang)
|
||||||
{
|
{
|
||||||
// We will build a list of values NOT matching the values to clear
|
// We will build a list of values NOT matching the values to clear
|
||||||
List values = new ArrayList();
|
List<DCValue> values = new ArrayList<DCValue>();
|
||||||
Iterator i = dublinCore.iterator();
|
for (DCValue dcv : dublinCore)
|
||||||
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
{
|
||||||
DCValue dcv = (DCValue) i.next();
|
|
||||||
|
|
||||||
if (!match(schema, element, qualifier, lang, dcv))
|
if (!match(schema, element, qualifier, lang, dcv))
|
||||||
{
|
{
|
||||||
values.add(dcv);
|
values.add(dcv);
|
||||||
@@ -885,6 +895,7 @@ public class Item extends DSpaceObject
|
|||||||
{
|
{
|
||||||
itemRow.setColumnNull("submitter_id");
|
itemRow.setColumnNull("submitter_id");
|
||||||
}
|
}
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -895,7 +906,7 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Collection[] getCollections() throws SQLException
|
public Collection[] getCollections() throws SQLException
|
||||||
{
|
{
|
||||||
List collections = new ArrayList();
|
List<Collection> collections = new ArrayList<Collection>();
|
||||||
|
|
||||||
// Get collection table rows
|
// Get collection table rows
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"collection",
|
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"collection",
|
||||||
@@ -940,7 +951,7 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Community[] getCommunities() throws SQLException
|
public Community[] getCommunities() throws SQLException
|
||||||
{
|
{
|
||||||
List communities = new ArrayList();
|
List<Community> communities = new ArrayList<Community>();
|
||||||
|
|
||||||
// Get community table rows
|
// Get community table rows
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"community",
|
TableRowIterator tri = DatabaseManager.queryTable(ourContext,"community",
|
||||||
@@ -990,7 +1001,7 @@ public class Item extends DSpaceObject
|
|||||||
{
|
{
|
||||||
if (bundles == null)
|
if (bundles == null)
|
||||||
{
|
{
|
||||||
bundles = new ArrayList();
|
bundles = new ArrayList<Bundle>();
|
||||||
// Get bundles
|
// Get bundles
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "bundle",
|
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "bundle",
|
||||||
"SELECT bundle.* FROM bundle, item2bundle WHERE " +
|
"SELECT bundle.* FROM bundle, item2bundle WHERE " +
|
||||||
@@ -1035,7 +1046,7 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Bundle[] getBundles(String name) throws SQLException
|
public Bundle[] getBundles(String name) throws SQLException
|
||||||
{
|
{
|
||||||
List matchingBundles = new ArrayList();
|
List<Bundle> matchingBundles = new ArrayList<Bundle>();
|
||||||
|
|
||||||
// now only keep bundles with matching names
|
// now only keep bundles with matching names
|
||||||
Bundle[] bunds = getBundles();
|
Bundle[] bunds = getBundles();
|
||||||
@@ -1121,6 +1132,8 @@ public class Item extends DSpaceObject
|
|||||||
mappingRow.setColumn("item_id", getID());
|
mappingRow.setColumn("item_id", getID());
|
||||||
mappingRow.setColumn("bundle_id", b.getID());
|
mappingRow.setColumn("bundle_id", b.getID());
|
||||||
DatabaseManager.update(ourContext, mappingRow);
|
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= ? ",
|
"AND bundle_id= ? ",
|
||||||
getID(), b.getID());
|
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
|
// If the bundle is orphaned, it's removed
|
||||||
TableRowIterator tri = DatabaseManager.query(ourContext,
|
TableRowIterator tri = DatabaseManager.query(ourContext,
|
||||||
"SELECT * FROM item2bundle WHERE bundle_id= ? ",
|
"SELECT * FROM item2bundle WHERE bundle_id= ? ",
|
||||||
@@ -1238,7 +1253,7 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
public Bitstream[] getNonInternalBitstreams() throws SQLException
|
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
|
// Go through the bundles and bitstreams picking out ones which aren't
|
||||||
// of internal formats
|
// of internal formats
|
||||||
@@ -1359,9 +1374,6 @@ public class Item extends DSpaceObject
|
|||||||
AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
|
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="
|
log.info(LogManager.getHeader(ourContext, "update_item", "item_id="
|
||||||
+ getID()));
|
+ getID()));
|
||||||
|
|
||||||
@@ -1419,7 +1431,7 @@ public class Item extends DSpaceObject
|
|||||||
// Keys are Strings: "element" or "element.qualifier"
|
// Keys are Strings: "element" or "element.qualifier"
|
||||||
// Values are Integers indicating number of values written for a
|
// Values are Integers indicating number of values written for a
|
||||||
// element/qualifier
|
// element/qualifier
|
||||||
Map elementCount = new HashMap();
|
Map<String,Integer> elementCount = new HashMap<String,Integer>();
|
||||||
|
|
||||||
DatabaseManager.update(ourContext, itemRow);
|
DatabaseManager.update(ourContext, itemRow);
|
||||||
|
|
||||||
@@ -1430,12 +1442,8 @@ public class Item extends DSpaceObject
|
|||||||
removeMetadataFromDatabase();
|
removeMetadataFromDatabase();
|
||||||
|
|
||||||
// Add in-memory DC
|
// Add in-memory DC
|
||||||
Iterator i = dublinCore.iterator();
|
for (DCValue dcv : dublinCore)
|
||||||
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
{
|
||||||
DCValue dcv = (DCValue) i.next();
|
|
||||||
|
|
||||||
// Get the DC Type
|
// Get the DC Type
|
||||||
int schemaID;
|
int schemaID;
|
||||||
MetadataSchema schema = MetadataSchema.find(ourContext,dcv.schema);
|
MetadataSchema schema = MetadataSchema.find(ourContext,dcv.schema);
|
||||||
@@ -1497,11 +1505,16 @@ public class Item extends DSpaceObject
|
|||||||
metadata.create(ourContext);
|
metadata.create(ourContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.ITEM, getID(), getDetails()));
|
||||||
dublinCoreChanged = false;
|
dublinCoreChanged = false;
|
||||||
|
clearDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update browse indices
|
if (modified)
|
||||||
Browse.itemChanged(ourContext, this);
|
{
|
||||||
|
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 item in DB
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// Invoke History system
|
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), "WITHDRAW"));
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.MODIFY, e,
|
|
||||||
ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
// Remove from indicies
|
|
||||||
Browse.itemRemoved(ourContext, getID());
|
|
||||||
DSIndexer.unIndexContent(ourContext, this);
|
|
||||||
|
|
||||||
// and all of our authorization policies
|
// and all of our authorization policies
|
||||||
// FIXME: not very "multiple-inclusion" friendly
|
// FIXME: not very "multiple-inclusion" friendly
|
||||||
@@ -1621,14 +1628,7 @@ public class Item extends DSpaceObject
|
|||||||
// Update item in DB
|
// Update item in DB
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// Invoke History system
|
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), "REINSTATE"));
|
||||||
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);
|
|
||||||
|
|
||||||
// authorization policies
|
// authorization policies
|
||||||
if (colls.length > 0)
|
if (colls.length > 0)
|
||||||
@@ -1656,8 +1656,7 @@ public class Item extends DSpaceObject
|
|||||||
*/
|
*/
|
||||||
void delete() throws SQLException, AuthorizeException, IOException
|
void delete() throws SQLException, AuthorizeException, IOException
|
||||||
{
|
{
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
ourContext.addEvent(new Event(Event.DELETE, Constants.ITEM, getID(), getHandle()));
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(ourContext, "delete_item", "item_id="
|
log.info(LogManager.getHeader(ourContext, "delete_item", "item_id="
|
||||||
+ getID()));
|
+ getID()));
|
||||||
@@ -1665,12 +1664,19 @@ public class Item extends DSpaceObject
|
|||||||
// Remove from cache
|
// Remove from cache
|
||||||
ourContext.removeCached(this, getID());
|
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())
|
if (isArchived())
|
||||||
{
|
{
|
||||||
// Remove from Browse indices
|
// Remove from Browse indices
|
||||||
Browse.itemRemoved(ourContext, getID());
|
Browse.itemRemoved(ourContext, getID());
|
||||||
DSIndexer.unIndexContent(ourContext, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the Dublin Core
|
// Delete the Dublin Core
|
||||||
@@ -1687,15 +1693,6 @@ public class Item extends DSpaceObject
|
|||||||
// remove all of our authorization policies
|
// remove all of our authorization policies
|
||||||
AuthorizeManager.removeAllPolicies(ourContext, this);
|
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
|
// Finally remove item row
|
||||||
DatabaseManager.delete(ourContext, itemRow);
|
DatabaseManager.delete(ourContext, itemRow);
|
||||||
}
|
}
|
||||||
@@ -1982,4 +1979,9 @@ public class Item extends DSpaceObject
|
|||||||
|
|
||||||
return false;
|
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.core.LogManager;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.history.HistoryManager;
|
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -286,9 +285,6 @@ public class WorkspaceItem implements InProgressSubmission
|
|||||||
|
|
||||||
WorkspaceItem wi = new WorkspaceItem(c, row);
|
WorkspaceItem wi = new WorkspaceItem(c, row);
|
||||||
|
|
||||||
HistoryManager.saveHistory(c, wi, HistoryManager.CREATE, c
|
|
||||||
.getCurrentUser(), c.getExtraLogInfo());
|
|
||||||
|
|
||||||
return wi;
|
return wi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,8 +459,6 @@ public class WorkspaceItem implements InProgressSubmission
|
|||||||
public void update() throws SQLException, AuthorizeException, IOException
|
public void update() throws SQLException, AuthorizeException, IOException
|
||||||
{
|
{
|
||||||
// Authorisation is checked by the item.update() method below
|
// 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",
|
log.info(LogManager.getHeader(ourContext, "update_workspace_item",
|
||||||
"workspace_item_id=" + getID()));
|
"workspace_item_id=" + getID()));
|
||||||
@@ -499,9 +493,6 @@ public class WorkspaceItem implements InProgressSubmission
|
|||||||
+ "original submitter to delete a workspace item");
|
+ "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",
|
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
|
||||||
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
||||||
+ "collection_id=" + collection.getID()));
|
+ "collection_id=" + collection.getID()));
|
||||||
@@ -536,9 +527,6 @@ public class WorkspaceItem implements InProgressSubmission
|
|||||||
// Check authorisation. We check permissions on the enclosed item.
|
// Check authorisation. We check permissions on the enclosed item.
|
||||||
AuthorizeManager.authorizeAction(ourContext, item, Constants.WRITE);
|
AuthorizeManager.authorizeAction(ourContext, item, Constants.WRITE);
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
|
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
|
||||||
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
"workspace_item_id=" + getID() + "item_id=" + item.getID()
|
||||||
+ "collection_id=" + collection.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.apache.log4j.Logger;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
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;
|
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.
|
* The context object is also used as a cache for CM API objects.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @author Robert Tansley
|
|
||||||
* @version $Revision$
|
* @version $Revision$
|
||||||
*/
|
*/
|
||||||
public class Context
|
public class Context
|
||||||
@@ -96,6 +98,12 @@ public class Context
|
|||||||
/** Group IDs of special groups user is a member of */
|
/** Group IDs of special groups user is a member of */
|
||||||
private List specialGroups;
|
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
|
* Construct a new context object. A database connection is opened. No user
|
||||||
* is authenticated.
|
* is authenticated.
|
||||||
@@ -241,7 +249,7 @@ public class Context
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Commit any changes made as part of the transaction
|
// Commit any changes made as part of the transaction
|
||||||
connection.commit();
|
commit();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -259,12 +267,79 @@ public class Context
|
|||||||
* if there was an error completing the database transaction
|
* if there was an error completing the database transaction
|
||||||
* or closing the connection
|
* or closing the connection
|
||||||
*/
|
*/
|
||||||
public void commit() throws SQLException
|
public void commit() throws SQLException {
|
||||||
{
|
|
||||||
// Commit any changes made as part of the transaction
|
// 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();
|
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
|
* Close the context, without committing any of the changes performed using
|
||||||
* this context. The database connection is freed. No exception is thrown if
|
* this context. The database connection is freed. No exception is thrown if
|
||||||
@@ -287,10 +362,12 @@ public class Context
|
|||||||
{
|
{
|
||||||
DatabaseManager.freeConnection(connection);
|
DatabaseManager.freeConnection(connection);
|
||||||
connection = null;
|
connection = null;
|
||||||
|
events = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Find out if this context is valid. Returns <code>false</code> if this
|
* Find out if this context is valid. Returns <code>false</code> if this
|
||||||
* context has been aborted or completed.
|
* context has been aborted or completed.
|
||||||
*
|
*
|
||||||
|
@@ -52,6 +52,13 @@ import java.text.ParseException;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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.
|
* Utility functions for DSpace.
|
||||||
@@ -61,6 +68,9 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public class Utils
|
public class Utils
|
||||||
{
|
{
|
||||||
|
/** log4j logger */
|
||||||
|
private static Logger log = Logger.getLogger(Utils.class);
|
||||||
|
|
||||||
private static final Pattern DURATION_PATTERN = Pattern
|
private static final Pattern DURATION_PATTERN = Pattern
|
||||||
.compile("(\\d+)([smhdwy])");
|
.compile("(\\d+)([smhdwy])");
|
||||||
|
|
||||||
@@ -82,6 +92,31 @@ public class Utils
|
|||||||
|
|
||||||
private static VMID vmid = new VMID();
|
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 Constructor */
|
||||||
private Utils()
|
private Utils()
|
||||||
{
|
{
|
||||||
@@ -350,4 +385,64 @@ public class Utils
|
|||||||
|
|
||||||
return qint * multiplier;
|
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.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
import org.dspace.core.Utils;
|
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.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -89,6 +89,12 @@ public class EPerson extends DSpaceObject
|
|||||||
/** The row in the table representing this eperson */
|
/** The row in the table representing this eperson */
|
||||||
private TableRow myRow;
|
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
|
* Construct an EPerson
|
||||||
*
|
*
|
||||||
@@ -104,6 +110,8 @@ public class EPerson extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("eperson_id"));
|
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="
|
log.info(LogManager.getHeader(context, "create_eperson", "eperson_id="
|
||||||
+ e.getID()));
|
+ e.getID()));
|
||||||
|
|
||||||
HistoryManager.saveHistory(context, e, HistoryManager.REMOVE, context
|
context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(), null));
|
||||||
.getCurrentUser(), context.getExtraLogInfo());
|
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -446,9 +453,6 @@ public class EPerson extends DSpaceObject
|
|||||||
"You must be an admin to delete an EPerson");
|
"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
|
// check for presence of eperson in tables that
|
||||||
// have constraints on eperson_id
|
// have constraints on eperson_id
|
||||||
Vector constraintList = getDeleteConstraints();
|
Vector constraintList = getDeleteConstraints();
|
||||||
@@ -460,9 +464,14 @@ public class EPerson extends DSpaceObject
|
|||||||
throw new EPersonDeletionException(constraintList);
|
throw new EPersonDeletionException(constraintList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myContext.addEvent(new Event(Event.DELETE, Constants.EPERSON, getID(), getEmail()));
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
myContext.removeCached(this, getID());
|
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
|
// Remove any group memberships first
|
||||||
DatabaseManager.updateQuery(myContext,
|
DatabaseManager.updateQuery(myContext,
|
||||||
"DELETE FROM EPersonGroup2EPerson WHERE eperson_id= ? ",
|
"DELETE FROM EPersonGroup2EPerson WHERE eperson_id= ? ",
|
||||||
@@ -549,6 +558,7 @@ public class EPerson extends DSpaceObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
myRow.setColumn("email", s);
|
myRow.setColumn("email", s);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -575,6 +585,7 @@ public class EPerson extends DSpaceObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
myRow.setColumn("netid", s);
|
myRow.setColumn("netid", s);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -621,6 +632,7 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setFirstName(String firstname)
|
public void setFirstName(String firstname)
|
||||||
{
|
{
|
||||||
myRow.setColumn("firstname", firstname);
|
myRow.setColumn("firstname", firstname);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -642,6 +654,7 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setLastName(String lastname)
|
public void setLastName(String lastname)
|
||||||
{
|
{
|
||||||
myRow.setColumn("lastname", lastname);
|
myRow.setColumn("lastname", lastname);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -653,6 +666,7 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setCanLogIn(boolean login)
|
public void setCanLogIn(boolean login)
|
||||||
{
|
{
|
||||||
myRow.setColumn("can_log_in", login);
|
myRow.setColumn("can_log_in", login);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -674,6 +688,7 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setRequireCertificate(boolean isrequired)
|
public void setRequireCertificate(boolean isrequired)
|
||||||
{
|
{
|
||||||
myRow.setColumn("require_certificate", isrequired);
|
myRow.setColumn("require_certificate", isrequired);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -695,6 +710,7 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setSelfRegistered(boolean sr)
|
public void setSelfRegistered(boolean sr)
|
||||||
{
|
{
|
||||||
myRow.setColumn("self_registered", sr);
|
myRow.setColumn("self_registered", sr);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -737,6 +753,8 @@ public class EPerson extends DSpaceObject
|
|||||||
public void setMetadata(String field, String value)
|
public void setMetadata(String field, String value)
|
||||||
{
|
{
|
||||||
myRow.setColumn(field, value);
|
myRow.setColumn(field, value);
|
||||||
|
modifiedMetadata = true;
|
||||||
|
addDetails(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -751,6 +769,7 @@ public class EPerson extends DSpaceObject
|
|||||||
String encoded = Utils.getMD5(s);
|
String encoded = Utils.getMD5(s);
|
||||||
|
|
||||||
myRow.setColumn("password", encoded);
|
myRow.setColumn("password", encoded);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -786,8 +805,17 @@ public class EPerson extends DSpaceObject
|
|||||||
log.info(LogManager.getHeader(myContext, "update_eperson",
|
log.info(LogManager.getHeader(myContext, "update_eperson",
|
||||||
"eperson_id=" + getID()));
|
"eperson_id=" + getID()));
|
||||||
|
|
||||||
HistoryManager.saveHistory(myContext, this, HistoryManager.MODIFY,
|
if (modified)
|
||||||
myContext.getCurrentUser(), myContext.getExtraLogInfo());
|
{
|
||||||
|
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
|
public Vector getDeleteConstraints() throws SQLException
|
||||||
{
|
{
|
||||||
Vector tableList = new Vector();
|
Vector<String> tableList = new Vector<String>();
|
||||||
|
|
||||||
// check for eperson in item table
|
// check for eperson in item table
|
||||||
TableRowIterator tri = DatabaseManager.query(myContext,
|
TableRowIterator tri = DatabaseManager.query(myContext,
|
||||||
@@ -872,4 +900,10 @@ public class EPerson extends DSpaceObject
|
|||||||
// explaining to the user why the eperson cannot be deleted.
|
// explaining to the user why the eperson cannot be deleted.
|
||||||
return tableList;
|
return tableList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -56,6 +57,7 @@ import org.dspace.core.ConfigurationManager;
|
|||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
|
import org.dspace.event.Event;
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -83,9 +85,9 @@ public class Group extends DSpaceObject
|
|||||||
private TableRow myRow;
|
private TableRow myRow;
|
||||||
|
|
||||||
/** lists of epeople and groups in the group */
|
/** 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 */
|
/** lists that need to be written out again */
|
||||||
private boolean epeopleChanged = false;
|
private boolean epeopleChanged = false;
|
||||||
@@ -95,6 +97,9 @@ public class Group extends DSpaceObject
|
|||||||
/** is this just a stub, or is all data loaded? */
|
/** is this just a stub, or is all data loaded? */
|
||||||
private boolean isDataLoaded = false;
|
private boolean isDataLoaded = false;
|
||||||
|
|
||||||
|
/** Flag set when metadata is modified, for events */
|
||||||
|
private boolean modifiedMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Group from a given context and tablerow
|
* Construct a Group from a given context and tablerow
|
||||||
*
|
*
|
||||||
@@ -108,6 +113,9 @@ public class Group extends DSpaceObject
|
|||||||
|
|
||||||
// Cache ourselves
|
// Cache ourselves
|
||||||
context.cache(this, row.getIntColumn("eperson_group_id"));
|
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="
|
log.info(LogManager.getHeader(context, "create_group", "group_id="
|
||||||
+ g.getID()));
|
+ g.getID()));
|
||||||
|
|
||||||
|
context.addEvent(new Event(Event.CREATE, Constants.GROUP, g.getID(), null));
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +255,8 @@ public class Group extends DSpaceObject
|
|||||||
public void setName(String name)
|
public void setName(String name)
|
||||||
{
|
{
|
||||||
myRow.setColumn("name", name);
|
myRow.setColumn("name", name);
|
||||||
|
modifiedMetadata = true;
|
||||||
|
addDetails("name");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,6 +276,8 @@ public class Group extends DSpaceObject
|
|||||||
|
|
||||||
epeople.add(e);
|
epeople.add(e);
|
||||||
epeopleChanged = true;
|
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);
|
groups.add(g);
|
||||||
groupsChanged = true;
|
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))
|
if (epeople.remove(e))
|
||||||
{
|
{
|
||||||
epeopleChanged = true;
|
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))
|
if (groups.remove(g))
|
||||||
{
|
{
|
||||||
groupsChanged = true;
|
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)
|
public static Group[] allMemberGroups(Context c, EPerson e)
|
||||||
throws SQLException
|
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
|
// now convert those Integers to Groups
|
||||||
Iterator i = myGroups.iterator();
|
Iterator i = myGroups.iterator();
|
||||||
|
|
||||||
@@ -419,7 +437,7 @@ public class Group extends DSpaceObject
|
|||||||
* @return Set of Integer groupIDs
|
* @return Set of Integer groupIDs
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public static Set allMemberGroupIDs(Context c, EPerson e)
|
public static Set<Integer> allMemberGroupIDs(Context c, EPerson e)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
// two queries - first to get groups eperson is a member of
|
// 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= ?",
|
"SELECT * FROM epersongroup2eperson WHERE eperson_id= ?",
|
||||||
e.getID());
|
e.getID());
|
||||||
|
|
||||||
Set groupIDs = new HashSet();
|
Set<Integer> groupIDs = new HashSet<Integer>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -513,9 +531,9 @@ public class Group extends DSpaceObject
|
|||||||
public static EPerson[] allMembers(Context c, Group g)
|
public static EPerson[] allMembers(Context c, Group g)
|
||||||
throws SQLException
|
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
|
// now convert those Integers to EPerson objects
|
||||||
Iterator i = myEpeople.iterator();
|
Iterator i = myEpeople.iterator();
|
||||||
|
|
||||||
@@ -538,19 +556,19 @@ public class Group extends DSpaceObject
|
|||||||
* @return Set of Integer epersonIDs
|
* @return Set of Integer epersonIDs
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public static Set allMemberIDs(Context c, Group g)
|
public static Set<Integer> allMemberIDs(Context c, Group g)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
// two queries - first to get all groups which are a member of this group
|
// 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
|
// 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
|
// Get all groups which are a member of this group
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(c, "group2groupcache",
|
TableRowIterator tri = DatabaseManager.queryTable(c, "group2groupcache",
|
||||||
"SELECT * FROM group2groupcache WHERE parent_id= ? ",
|
"SELECT * FROM group2groupcache WHERE parent_id= ? ",
|
||||||
g.getID());
|
g.getID());
|
||||||
|
|
||||||
Set groupIDs = new HashSet();
|
Set<Integer> groupIDs = new HashSet<Integer>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -611,7 +629,7 @@ public class Group extends DSpaceObject
|
|||||||
private static boolean epersonInGroup(Context c, int groupID, EPerson e)
|
private static boolean epersonInGroup(Context c, int groupID, EPerson e)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
Set groupIDs = Group.allMemberGroupIDs(c, e);
|
Set<Integer> groupIDs = Group.allMemberGroupIDs(c, e);
|
||||||
|
|
||||||
return groupIDs.contains(new Integer(groupID));
|
return groupIDs.contains(new Integer(groupID));
|
||||||
}
|
}
|
||||||
@@ -868,6 +886,9 @@ public class Group extends DSpaceObject
|
|||||||
public void delete() throws SQLException
|
public void delete() throws SQLException
|
||||||
{
|
{
|
||||||
// FIXME: authorizations
|
// FIXME: authorizations
|
||||||
|
|
||||||
|
myContext.addEvent(new Event(Event.DELETE, Constants.GROUP, getID(), getName()));
|
||||||
|
|
||||||
// Remove from cache
|
// Remove from cache
|
||||||
myContext.removeCached(this, getID());
|
myContext.removeCached(this, getID());
|
||||||
|
|
||||||
@@ -964,6 +985,13 @@ public class Group extends DSpaceObject
|
|||||||
// FIXME: Check authorisation
|
// FIXME: Check authorisation
|
||||||
DatabaseManager.update(myContext, myRow);
|
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
|
// Redo eperson mappings if they've changed
|
||||||
if (epeopleChanged)
|
if (epeopleChanged)
|
||||||
{
|
{
|
||||||
@@ -1062,7 +1090,7 @@ public class Group extends DSpaceObject
|
|||||||
TableRowIterator tri = DatabaseManager.queryTable(myContext, "group2group",
|
TableRowIterator tri = DatabaseManager.queryTable(myContext, "group2group",
|
||||||
"SELECT * FROM group2group");
|
"SELECT * FROM group2group");
|
||||||
|
|
||||||
Map parents = new HashMap();
|
Map<Integer,Set<Integer>> parents = new HashMap<Integer,Set<Integer>>();
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -1074,7 +1102,7 @@ public class Group extends DSpaceObject
|
|||||||
// if parent doesn't have an entry, create one
|
// if parent doesn't have an entry, create one
|
||||||
if (!parents.containsKey(parentID))
|
if (!parents.containsKey(parentID))
|
||||||
{
|
{
|
||||||
Set children = new HashSet();
|
Set<Integer> children = new HashSet<Integer>();
|
||||||
|
|
||||||
// add child id to the list
|
// add child id to the list
|
||||||
children.add(childID);
|
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
|
// parent has an entry, now add the child to the parent's record
|
||||||
// of children
|
// of children
|
||||||
Set children = (Set) parents.get(parentID);
|
Set<Integer> children = parents.get(parentID);
|
||||||
children.add(childID);
|
children.add(childID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1103,7 +1131,7 @@ public class Group extends DSpaceObject
|
|||||||
{
|
{
|
||||||
Integer parentID = (Integer) i.next();
|
Integer parentID = (Integer) i.next();
|
||||||
|
|
||||||
Set myChildren = getChildren(parents, parentID);
|
Set<Integer> myChildren = getChildren(parents, parentID);
|
||||||
|
|
||||||
Iterator j = myChildren.iterator();
|
Iterator j = myChildren.iterator();
|
||||||
|
|
||||||
@@ -1112,7 +1140,7 @@ public class Group extends DSpaceObject
|
|||||||
// child of a parent
|
// child of a parent
|
||||||
Integer childID = (Integer) j.next();
|
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();
|
Integer parent = (Integer) pi.next();
|
||||||
|
|
||||||
Set children = (Set) parents.get(parent);
|
Set<Integer> children = parents.get(parent);
|
||||||
Iterator ci = children.iterator(); // child iterator
|
Iterator ci = children.iterator(); // child iterator
|
||||||
|
|
||||||
while (ci.hasNext())
|
while (ci.hasNext())
|
||||||
@@ -1158,16 +1186,16 @@ public class Group extends DSpaceObject
|
|||||||
* the parent you're interested in
|
* the parent you're interested in
|
||||||
* @return Map whose keys are all of the children of a parent
|
* @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
|
// degenerate case, this parent has no children
|
||||||
if (!parents.containsKey(parent))
|
if (!parents.containsKey(parent))
|
||||||
return myChildren;
|
return myChildren;
|
||||||
|
|
||||||
// got this far, so we must have children
|
// 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
|
// now iterate over all of the children
|
||||||
Iterator i = children.iterator();
|
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.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.history.HistoryManager;
|
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -356,9 +355,6 @@ public class WorkflowItem implements InProgressSubmission
|
|||||||
|
|
||||||
// Update ourselves
|
// Update ourselves
|
||||||
DatabaseManager.update(ourContext, wfRow);
|
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
|
// Remove from cache
|
||||||
ourContext.removeCached(this, getID());
|
ourContext.removeCached(this, getID());
|
||||||
|
|
||||||
HistoryManager.saveHistory(ourContext, this, HistoryManager.REMOVE,
|
|
||||||
ourContext.getCurrentUser(), ourContext.getExtraLogInfo());
|
|
||||||
|
|
||||||
// delete any pending tasks
|
// delete any pending tasks
|
||||||
WorkflowManager.deleteTasks(ourContext, this);
|
WorkflowManager.deleteTasks(ourContext, this);
|
||||||
|
|
||||||
|
@@ -68,7 +68,6 @@ import org.dspace.core.LogManager;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.handle.HandleManager;
|
import org.dspace.handle.HandleManager;
|
||||||
import org.dspace.history.HistoryManager;
|
|
||||||
import org.dspace.storage.rdbms.DatabaseManager;
|
import org.dspace.storage.rdbms.DatabaseManager;
|
||||||
import org.dspace.storage.rdbms.TableRow;
|
import org.dspace.storage.rdbms.TableRow;
|
||||||
import org.dspace.storage.rdbms.TableRowIterator;
|
import org.dspace.storage.rdbms.TableRowIterator;
|
||||||
@@ -195,10 +194,6 @@ public class WorkflowManager
|
|||||||
wfi.setMultipleTitles(wsi.hasMultipleTitles());
|
wfi.setMultipleTitles(wsi.hasMultipleTitles());
|
||||||
wfi.setPublishedBefore(wsi.isPublishedBefore());
|
wfi.setPublishedBefore(wsi.isPublishedBefore());
|
||||||
|
|
||||||
// Write history creation event
|
|
||||||
HistoryManager.saveHistory(c, wfi, HistoryManager.CREATE, c
|
|
||||||
.getCurrentUser(), c.getExtraLogInfo());
|
|
||||||
|
|
||||||
// remove the WorkspaceItem
|
// remove the WorkspaceItem
|
||||||
wsi.deleteWrapper();
|
wsi.deleteWrapper();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user