/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: StandardResourceAssignmentService.java 2548 2007-10-22 14:00:52Z $
*
* $Log$
* Revision 1.7 2007/02/27 14:34:18 drmlipp
* Some refactoring to reduce cyclic dependencies.
*
* Revision 1.6 2006/10/15 19:29:51 mlipp
* Merged changes from 1.4.x up to 1.4ea3pre1.
*
* Revision 1.5.2.2 2006/10/15 18:25:12 mlipp
* Fixed visibility.
*
* Revision 1.5.2.1 2006/10/14 21:34:06 mlipp
* Simplified resource assignment service implementation.
*
* Revision 1.5 2006/09/29 12:32:12 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.4 2005/10/15 21:19:38 mlipp
* Added support for providing WfAssignment
* implementations based purely on methods of Activity.
*
* Revision 1.3 2005/08/17 21:15:31 mlipp
* Synchronized with 1.3.1p3.
*
* Revision 1.1.1.2.6.1 2005/08/16 14:04:04 drmlipp
* Backported LDAP RMS and security role fixes.
*
* Revision 1.1.1.2.4.2 2005/08/15 16:38:13 drmlipp
* Improved sealing of exceptions from RMS.
*
* Revision 1.1.1.2.4.1 2005/08/14 21:07:55 drmlipp
* Fixed initialization problem (RMS initialized in wrong context).
*
* Revision 1.2 2005/07/04 20:40:25 mlipp
* Improved problem reporting.
*
* Revision 1.1.1.2 2004/08/18 15:17:36 drmlipp
* Update to 1.2
*
* Revision 1.28 2004/06/14 19:37:19 lipp
* Fixed assignment functions and cleaned up assignment related
* interfaces.
*
* Revision 1.27 2004/03/03 17:23:13 lipp
* Implemented setAssignee and cleaned up code a bit.
*
* Revision 1.26 2003/06/27 08:51:46 lipp
* Fixed copyright/license information.
*
* Revision 1.25 2003/04/26 16:11:15 lipp
* Moved some classes to reduce package dependencies.
*
* Revision 1.24 2003/04/25 14:50:59 lipp
* Fixed javadoc errors and warnings.
*
* Revision 1.23 2002/12/19 21:37:43 lipp
* Reorganized interfaces.
*
* Revision 1.22 2002/11/26 11:23:30 lipp
* Modified RemoteException comment.
*
* Revision 1.21 2002/06/27 10:55:35 lipp
* Delayed initialization even more.
*
* Revision 1.20 2002/01/23 15:22:53 huaiyang
* Add M:<name> as resource selection in autoAssignResources method.
*
* Revision 1.19 2002/01/15 13:42:21 lipp
* Added resourceByKey to ResourceAssignmentService and some missing
* NoSuchResourceExceptions in various methods.
*
* Revision 1.18 2002/01/15 11:25:59 huaiyang
* Add the assigned activity function to the mgmt client.
*
* Revision 1.17 2002/01/09 14:48:51 lipp
* Changed access to current user as resource.
*
* Revision 1.16 2002/01/09 14:00:01 lipp
* Cleaned up relation between wfcore, resource assignment and resource
* management service.
*
* Revision 1.15 2002/01/08 18:12:06 lipp
* Method to determined currently logged on user moved to resource
* management service.
*
* Revision 1.14 2001/12/20 22:32:06 lipp
* Removed no longer needed method.
*
* Revision 1.13 2001/12/20 22:27:34 lipp
* WfResource release semantics fixed.
*
* Revision 1.12 2001/12/20 22:22:50 lipp
* Resource release implemented.
*
* Revision 1.11 2001/12/20 16:24:25 lipp
* Resource assignment extended.
*
* Revision 1.10 2001/12/19 22:07:29 lipp
* Automatic resource assignment (workflow core part) implemented.
*
* Revision 1.9 2001/12/18 22:16:52 lipp
* Restructured DOM generation, implemented "assignments" method from ras.
*
* Revision 1.8 2001/12/18 15:35:11 lipp
* Implemented workItems and isMemberOfWorkItem.
*
* Revision 1.7 2001/12/17 19:56:03 lipp
* Implementation of equality checking improved.
*
* Revision 1.6 2001/12/17 15:50:57 lipp
* Better handling of resource refs.
*
* Revision 1.5 2001/12/17 12:14:04 lipp
* Adapted to configurable ResourceManagement/AssignmentServices.
*
* Revision 1.4 2001/12/17 10:52:19 lipp
* Added configurable resource management service.
*
* Revision 1.3 2001/12/17 09:15:50 lipp
* Javadoc fixes.
*
* Revision 1.2 2001/12/16 21:48:57 lipp
* addAssignment implemented.
*
* Revision 1.1 2001/12/16 10:37:35 lipp
* Assignment service implemented.
*
*/
package de.danet.an.workflow.assignment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.io.IOException;
import java.io.OptionalDataException;
import java.rmi.RemoteException;
import java.security.Principal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.ejb.EJBException;
import javax.sql.DataSource;
import de.danet.an.util.EJBUtil;
import de.danet.an.util.JDBCUtil;
import de.danet.an.util.ResourceNotAvailableException;
import de.danet.an.util.UniversalPrepStmt;
import de.danet.an.workflow.omgcore.InvalidResourceException;
import de.danet.an.workflow.omgcore.NotAssignedException;
import de.danet.an.workflow.omgcore.WfActivity;
import de.danet.an.workflow.omgcore.WfAssignment;
import de.danet.an.workflow.omgcore.WfResource;
import de.danet.an.workflow.api.AlreadyAssignedException;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.NoSuchResourceException;
import de.danet.an.workflow.api.Participant;
import de.danet.an.workflow.api.Participant.ParticipantType;
import de.danet.an.workflow.spis.ras.ActivityFinder;
import de.danet.an.workflow.spis.ras.FactoryConfigurationError;
import de.danet.an.workflow.spis.ras.NoSuchActivityException;
import de.danet.an.workflow.spis.ras.ResourceAssignmentService;
import de.danet.an.workflow.spis.rms.ResourceAssignmentContext;
import de.danet.an.workflow.spis.rms.ResourceManagementService;
import de.danet.an.workflow.spis.rms.ResourceManagementServiceFactory;
import de.danet.an.workflow.spis.rms.ResourceNotFoundException;
/**
* This class implements the standard resource assignment service provided
* as part of the workflow package.
*/
public class StandardResourceAssignmentService
implements ResourceAssignmentService {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog
(StandardResourceAssignmentService.class);
/** Warned about RMS not supporting resource selection? */
private static boolean rmsUnsuppportedWarned = false;
/** An in memory representation of the known finders. */
private static Map finderByDBIdCache = new HashMap(); // used for sync
private static Map dbIdByFinderCache = null; // indicates uninitialized
/**
* The data source of the database.
* @see javax.sql.DataSource
*/
private DataSource ds = null;
/** The resource management service associated with this service. */
private ResourceManagementService rms = null;
/**
* Constructs a new resource assignment service.
*
* @param rasCtx an implementation of the resource Assignment context
* @param rmsFac the resource management service factory.
* @throws FactoryConfigurationError if a problem creating the RMS
* occurs
*/
public StandardResourceAssignmentService
(ResourceManagementServiceFactory rmsFac,
ResourceAssignmentContext rasCtx, DataSource ds)
throws FactoryConfigurationError {
try {
rmsFac.setResourceAssignmentContext (rasCtx);
rms = rmsFac.newResourceManagementService ();
} catch (de.danet.an.workflow.spis.rms.FactoryConfigurationError e) {
throw (FactoryConfigurationError)
(new FactoryConfigurationError
("Cannot create RMS: " + e.getMessage())).initCause(e);
}
this.ds = ds;
}
/**
* Return the data source oassed to the constructor.
* @return Returns the data source.
*/
protected DataSource getDataSource() {
return ds;
}
/**
* Return the resource management service passed to the constructor.
* @return Returns the rms.
*/
protected ResourceManagementService getResourceManagementService() {
return rms;
}
/**
* @throws EJBException
*/
private void initFinderCache() throws EJBException {
synchronized (finderByDBIdCache) {
if (dbIdByFinderCache == null) {
// read finders from database. we cannot do lazy loading,
// because we cannot lookup by finder (being binary)
Map finderLookup = new HashMap();
Map dbIdLookup = new HashMap();
try {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
String selectStatement
= "SELECT DBId, LocData FROM ActivityFinders";
prepStmt = con.prepareStatement(selectStatement);
rs = prepStmt.executeQuery();
while (rs.next()) {
long idx = rs.getLong(1);
Object finder = JDBCUtil.getBinary(rs, 2);
finderLookup.put (new Long(idx), finder);
dbIdLookup.put (finder, new Long(idx));
}
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
} catch (OptionalDataException ode) {
throw new EJBException(ode);
} catch (IOException ioe) {
throw new EJBException(ioe);
} catch (ClassNotFoundException cnf) {
throw new EJBException(cnf);
}
finderByDBIdCache = finderLookup;
dbIdByFinderCache = dbIdLookup;
}
}
}
/**
* Get the finder id for a finder.
*
* @param finder the activity finder in question.
* @return the associated index.
* @throws RemoteException if a system-level error occurs.
*/
protected long finderId (ActivityFinder finder)
throws RemoteException {
synchronized (finderByDBIdCache) {
initFinderCache();
Long idx = (Long)dbIdByFinderCache.get (finder);
if (idx != null) {
return idx.longValue();
}
// new finder, insert
try {
Connection con = ds.getConnection();
UniversalPrepStmt prepStmt = null;
long newIdx = EJBUtil.newPrimaryKey ("ActivityFinders");
try {
prepStmt = new UniversalPrepStmt
(ds, con, "INSERT INTO ActivityFinders (DBId, LocData) "
+ "VALUES (?, ?)");
prepStmt.setLong(1, newIdx);
prepStmt.setBinary(2, finder);
prepStmt.executeUpdate();
} finally {
JDBCUtil.closeAll (null, prepStmt, con);
}
finderByDBIdCache.put (new Long(newIdx), finder);
dbIdByFinderCache.put (finder, new Long(newIdx));
return newIdx;
} catch (ResourceNotAvailableException e) {
throw new EJBException (e);
} catch (SQLException se) {
throw new EJBException(se);
} catch (OptionalDataException ode) {
throw new EJBException(ode);
} catch (IOException ioe) {
throw new EJBException(ioe);
}
}
}
/**
* Lookup a finder for a given finder id.
*
* @param finderId the finder id
* @return the finder
*/
protected ActivityFinder finderByIndex (long finderId) {
initFinderCache();
return (ActivityFinder)finderByDBIdCache.get(new Long(finderId));
}
/**
* Change an assignment for enacting an activity.<P>
*
* @param finder the finder used to lookup activities by
* their <code>finderId</code>s
* @param actId a unique (with respect to an <code>ActivityFinder</code>)
* identifier for the Activity. The length of <code>actId</code> is
* guaranteed not to exceed 64
* @param activity the activity being enacted
* @param oldResource the resource that has its assignment removed
* @param newResource the resource to be assigned
* @throws RemoteException if a system-level error occurs
* @throws InvalidResourceException if the resource is invalid.
* As the environment is a concurrent multi user environment,
* <code>WfResource</code> objects may become invalid
* @throws AlreadyAssignedException if the assignment already
* exists
* @throws NotAssignedException if there is no assignment to the
* old resource
* @see ActivityFinder
*/
public void changeAssignment
(ActivityFinder finder, String actId, WfActivity activity,
WfResource oldResource, WfResource newResource)
throws RemoteException, InvalidResourceException,
AlreadyAssignedException, NotAssignedException {
long finderId = finderId (finder);
try {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
prepStmt = con.prepareStatement
("UPDATE Assignments SET assignedresource=? WHERE "
+ "actfinder=? AND activity=? AND assignedresource=?");
prepStmt.setString (1, newResource.resourceKey());
prepStmt.setLong (2, finderId);
prepStmt.setString (3, actId);
prepStmt.setString (4, oldResource.resourceKey());
if (prepStmt.executeUpdate() != 1) {
throw new NotAssignedException ();
}
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
}
}
/**
* Remove the assignment of a resource to an activity. This method
* is called by the workflow engine to implement the assignment
* manipulation methods provided by its API.<P>
*
* @param actId a unique (with respect to an <code>ActivityFinder</code>)
* identifier for the Activity. The length of <code>actId</code> is
* guaranteed not to exceed 64.
* @param finder the finder used to lookup activities by
* their <code>finderId</code>s.
* @param activity the activity that is about to become ready.
* @param resource the resource to be assigned.
* @throws RemoteException if a system-level error occurs.
* @throws InvalidResourceException if the resource is invalid.
* @throws NotAssignedException if the resource is not assigned to
* the given activity
* @see ActivityFinder
*/
public void removeAssignment (ActivityFinder finder, String actId,
WfActivity activity, WfResource resource)
throws RemoteException, InvalidResourceException, NotAssignedException {
long finderId = finderId (finder);
try {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
prepStmt = con.prepareStatement
("DELETE FROM Assignments WHERE "
+ "actfinder=? AND activity=? AND assignedresource=?");
prepStmt.setLong (1, finderId);
prepStmt.setString (2, actId);
prepStmt.setString (3, resource.resourceKey());
if (prepStmt.executeUpdate() != 1) {
throw new NotAssignedException ();
}
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
}
}
/**
* Get the resource associated with an Assignment.<P>
*
* @param asnmnt the assignment
* @return the resource
* @throws RemoteException if a system-level error occurs.
* @see de.danet.an.workflow.spis.ras.ActivityFinder
* @ejb.interface-method view-type="remote"
*/
public WfResource getResource (WfAssignment asnmnt)
throws RemoteException {
String resKey = null;
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
try {
prepStmt = con.prepareStatement
("SELECT AssignedResource FROM Assignments WHERE DBId = ?");
prepStmt.setLong (1, ((Assignment)asnmnt).key());
rs = prepStmt.executeQuery();
if (!rs.next()) {
throw new IllegalStateException
("Cannot access assignment info, "
+ "assignment has probably been removed");
}
resKey = rs.getString(1);
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
}
try {
return rms.resourceByKey (resKey);
} catch (ResourceNotFoundException rnf) {
logger.error (rnf.getMessage (), rnf);
throw new IllegalStateException
("Cannot lookup resource, "
+ "has probably been deleted while being assigned");
} catch (RemoteException e) {
throw e;
} catch (Exception e) {
logger.error
(rms + " has thrown an unexpected exception "
+ "(mapped to IllegalStateException): "
+ e.getMessage (), e);
throw (IllegalStateException)
(new IllegalStateException
("Unexpected exception from RMS: " + e.getMessage ()))
.initCause (e);
}
}
/**
* Return the assignments to an activity.
*
* @param actId a unique (with respect to an <code>ActivityFinder</code>)
* identifier for the Activity. The length of <code>actId</code> is
* guaranteed not to exceed 64.
* @param finder the finder used to lookup activities by
* their <code>finderId</code>s.
* @param activity the activity.
* @return the collection of assignments (instances of
* {@link de.danet.an.workflow.omgcore.WfAssignment
* <code>WfAssignment</code>}).
* @throws RemoteException if a system-level error occurs.
*/
public Collection assignments (ActivityFinder finder, String actId,
WfActivity activity)
throws RemoteException {
Collection res = new ArrayList ();
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
try {
con = ds.getConnection();
String selectStatement
= "SELECT DBId FROM Assignments "
+ "WHERE actfinder=? AND activity=?";
prepStmt = con.prepareStatement(selectStatement);
prepStmt.setLong (1, finderId(finder));
prepStmt.setString (2, actId);
rs = prepStmt.executeQuery();
while (rs.next()){
res.add (new Assignment(rs.getLong (1), activity));
}
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
}
return res;
}
/**
* Return the assignments of a given resource.
*
* @param resource the resource.
* @return the collection of assigned work items (instances of
* {@link de.danet.an.workflow.omgcore.WfAssignment
* <code>WfAssignment</code>}).
* @throws RemoteException if a system-level error occurs.
* @see de.danet.an.workflow.spis.rms
*/
public Collection workItems (WfResource resource)
throws RemoteException {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
Collection res = new ArrayList();
try {
try {
con = ds.getConnection();
prepStmt = con.prepareStatement
("SELECT DBId, actfinder, activity FROM Assignments "
+ "WHERE assignedresource=?");
prepStmt.setString (1, resource.resourceKey());
rs = prepStmt.executeQuery();
while (rs.next()){
long dbid = rs.getLong (1);
long idx = rs.getLong (2);
ActivityFinder finder = finderByIndex(idx);
String actKey = rs.getString(3);
try {
res.add (new Assignment (dbid, finder.find (actKey)));
} catch (NoSuchActivityException e) {
// race condition
logger.debug
("Found assignment to activity key " + actKey
+ " but not the activity: " + e.getMessage ());
} catch (RemoteException rex) {
throw new EJBException (rex);
}
}
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (RemoteException e) {
throw new EJBException(e);
} catch (SQLException se) {
throw new EJBException(se);
}
return res;
}
/**
* Find out if a given assignment belongs to the work items assigned to
* a particular resource.
*
* @param resource the resource.
* @param assignment the assignment in question.
* @return <code>true</code> if the <code>assignment</code> belongs to
* the work items of the <code>resource</code>.
* @throws RemoteException if a system-level error occurs.
* @throws NoSuchResourceException if the resource is invalid.
* @see de.danet.an.workflow.spis.rms
*/
public boolean isMemberOfWorkItems (WfResource resource,
WfAssignment assignment)
throws RemoteException, NoSuchResourceException {
if (!(assignment instanceof Assignment)) {
return false;
}
Assignment assmnt = (Assignment)assignment;
return resource.equals (assmnt.assignee());
}
/**
* Triggers the automatic assignment of resources to an activity that
* is about to become ready.<P>
*
* If <code>resSel</code> is of type string, the following cases
* are handled by the assignment service:
* <dl>
* <dt><code>!:currentUser</code></dt>
* <dd>Assigns the current user.</dd>
* </dl>
*
* In all other cases the parameter <code>resSel</code> is simply
* passed through to
* {@link ResourceManagementService#selectResources the resource
* selection service}.
*
* @param actId a unique (with respect to an <code>ActivityFinder</code>)
* identifier for the Activity. The length of <code>actId</code> is
* guaranteed not to exceed 64.
* @param finder the finder used to lookup activities by
* their <code>finderId</code>s.
* @param activity the activity that is about to become ready.
* @param principal the current caller as known in the EJB context,
* may be <code>null</code>.
* @param participant the <code>Participant</code> that describes the
* resource selection criteria.
* @return the assigned resources (instances of {@link
* de.danet.an.workflow.omgcore.WfResource
* <code>WfResource</code>}).
* @throws RemoteException if a system-level error occurs.
* @see ActivityFinder
*/
public Collection autoAssignResources
(ActivityFinder finder, String actId, WfActivity activity,
Principal principal, Participant participant)
throws RemoteException {
if (participant == null) {
return new ArrayList ();
}
Object resSel = null;
ParticipantType type = participant.getParticipantType();
Collection assigned = new ArrayList ();
if (type.isResourceSet()) {
resSel = "G:" + participant.getName();
} else if (type.isRole()) {
resSel = "R:" + participant.getName();
} else if (type.isHuman()) {
String crit = (String)participant.getResourceSelection();
if (crit != null && crit.startsWith ("!:currentUser")
&& principal != null) {
try {
WfResource res = asResource (principal);
assigned.add (res);
addAssignment (finderId(finder), actId, res);
return assigned;
} catch (AlreadyAssignedException rnf) {
return assigned;
} catch (InvalidKeyException rnf) {
return assigned;
}
}
resSel = "M:" + participant.getName();
}
// fall through
try {
Collection reses = rms.selectResources (resSel);
if (reses.size() == 0) {
return assigned;
}
long finderId = finderId (finder);
for (Iterator i = reses.iterator(); i.hasNext();) {
WfResource res = (WfResource)i.next();
assigned.add (res);
addAssignment (finderId, actId, res);
}
return assigned;
} catch (AlreadyAssignedException rnf) {
return assigned;
} catch (UnsupportedOperationException uo) {
if (!rmsUnsuppportedWarned) {
logger.warn ("Configured RMS does not support resource "
+ "selection, no resources assigned.");
rmsUnsuppportedWarned = true;
}
return assigned;
} catch (RemoteException e) {
throw e;
} catch (Exception e) {
logger.error
(rms + " has thrown an unexpected exception, "
+ "no resources are assigned: " + e.getMessage (), e);
return assigned;
}
}
/**
* Assign a resource to an activity.
*
* @param actId a unique (with respect to an <code>ActivityFinder</code>)
* identifier for the Activity. The length of <code>actId</code> is
* guaranteed not to exceed 64.
* @param finderId the <code>finderId</code>s.
* @param activity the activity that is about to become ready.
* @param resource the resource to be assigned.
* @throws RemoteException if a system-level error occurs.
* @throws NoSuchResourceException if the resource is invalid.
* @see ActivityFinder
* @throws AlreadyAssignedException if the assignment already
* exists
*/
protected void addAssignment
(long finderId, String actId, WfResource resource)
throws RemoteException, AlreadyAssignedException {
try {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
prepStmt = con.prepareStatement
("SELECT DBId FROM Assignments WHERE "
+ "actfinder=? AND activity=? AND assignedresource=?");
prepStmt.setLong (1, finderId);
prepStmt.setString (2, actId);
prepStmt.setString (3, resource.resourceKey());
rs = prepStmt.executeQuery();
if (rs.next()){
throw new AlreadyAssignedException ();
}
rs.close ();
rs = null;
prepStmt.close ();
prepStmt = con.prepareStatement
("INSERT INTO Assignments "
+ "(DBId, actfinder, activity, assignedresource) "
+ "VALUES (?, ?, ?, ?)");
long id = EJBUtil.newPrimaryKey ("Assignments");
prepStmt.setLong (1, id);
prepStmt.setLong(2, finderId);
prepStmt.setString (3, actId);
prepStmt.setString (4, resource.resourceKey());
prepStmt.executeUpdate();
} catch (ResourceNotAvailableException e) {
throw new SQLException
("Cannot get primary key" + e.getMessage());
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
} catch (SQLException se) {
throw new EJBException(se);
}
}
/**
* Returns at least the collection of all the workflow resources whom has
* been assigned work items, but optionally it can return the additional
* workflow resources who are known to the resource assignment service.
*
* @return the collection of the known resources to the ras (instances of
* {@link de.danet.an.workflow.omgcore.WfResource
* <code>WfResource</code>}).
* @throws RemoteException if a system-level error occurs.
* @see de.danet.an.workflow.assignment
*/
public Collection knownResources ()
throws RemoteException {
try {
return rms.listResources();
} catch (RemoteException e) {
throw e;
} catch (Exception e) {
logger.error
(rms + " has thrown an unexpected exception, "
+ "no resources are listed: " + e.getMessage (), e);
return new ArrayList ();
}
}
/* Comment copied from interface. */
public Collection authorizers (WfResource resource)
throws RemoteException {
try {
return rms.authorizers(resource);
} catch (RemoteException e) {
throw e;
} catch (Exception e) {
logger.error
(rms + " has thrown an unexpected exception, "
+ "no authorizers returned: "
+ e.getMessage (), e);
return new ArrayList ();
}
}
/**
* Given a {@link java.security.Principal principal}, return the
* workflow resource associated with this principal. This implementation
* simply delegates the request to the resource management service.
*
* @param principal the principal.
* @return a <code>WfResource</code> object corresponding to the
* given principal.
* @throws NoSuchResourceException if the StaffMember with the given key
* can't be found or the key is not associate with an StaffMember object.
* @throws RemoteException if a system-level error occurs.
*/
public WfResource asResource (Principal principal)
throws RemoteException, InvalidKeyException {
try {
return rms.asResource (principal);
} catch (ResourceNotFoundException rnf) {
throw new InvalidKeyException (rnf.getMessage());
}
}
/**
* Given the <code>key</code> of a <code>WfResource</code>
* (obtained with {@link WfResource#resourceKey
* <code>resourceKey()</code>}), return the workflow resource
* associated with this key.<P>
*
* This method is implemented by simply calling
* {@link ResourceManagementService#resourceByKey
* <code>resourceByKey</code>} of the underlying resource
* management service.
*
* @param key the key.
* @return a <code>WfResource</code> object corresponding to the
* given key.
* @throws NoSuchResourceException if the resource with the given
* key can't be found. As the environment is a concurrent multi
* user environment, <code>WfResource</code> objects (and keys obtained
* from <code>WfResource</code> objects) may become invalid.
* @throws RemoteException if a system-level error occurs.
*/
public WfResource resourceByKey (String key)
throws InvalidKeyException, RemoteException {
try {
return rms.resourceByKey (key);
} catch (ResourceNotFoundException rnf) {
throw new InvalidKeyException (rnf.getMessage());
}
}
}