/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 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: EisRmsService.java 2052 2006-12-12 10:03:10Z drmlipp $
*
* $Log$
* Revision 1.4 2006/10/15 19:29:51 mlipp
* Merged changes from 1.4.x up to 1.4ea3pre1.
*
* Revision 1.3.2.1 2006/10/14 21:34:06 mlipp
* Simplified resource assignment service implementation.
*
* Revision 1.3 2006/10/03 17:05:52 mlipp
* Using new default resource classes.
*
* Revision 1.2 2006/09/29 12:32:13 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.1 2006/09/24 20:57:17 mlipp
* Moved RMS implementations in own sub-package.
*
* Revision 1.7 2006/07/11 11:48:29 drmlipp
* Fixed message.
*
* Revision 1.6 2006/07/11 11:13:13 drmlipp
* Props RMS running.
*
* Revision 1.5 2006/07/11 09:19:10 drmlipp
* Fixed exception categorization.
*
* Revision 1.4 2006/07/10 13:47:09 drmlipp
* Implemented EisRmsService.
*
* Revision 1.3 2006/07/10 10:34:49 drmlipp
* Added resource adaptor lookup.
*
* Revision 1.2 2006/07/05 10:58:28 drmlipp
* Fixed package names.
*
* Revision 1.1 2006/07/05 10:53:27 drmlipp
* Separated generic RMS adapter client from properties based adapter.
*
* Revision 1.1 2006/07/04 13:49:57 drmlipp
* Started.
*
*/
package de.danet.an.workflow.rmsimpls.eisrms;
import java.rmi.RemoteException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.naming.NameNotFoundException;
import javax.resource.ResourceException;
import javax.resource.spi.ApplicationServerInternalException;
import javax.resource.spi.CommException;
import javax.resource.spi.EISSystemException;
import javax.resource.spi.LocalTransactionException;
import javax.resource.spi.ResourceAllocationException;
import de.danet.an.workflow.omgcore.WfResource;
import de.danet.an.workflow.rmsimpls.eisrms.aci.RmsConnection;
import de.danet.an.workflow.rmsimpls.eisrms.aci.RmsConnectionFactory;
import de.danet.an.workflow.rmsimpls.eisrms.aci.RmsEntry;
import de.danet.an.workflow.spis.rms.DefaultGroupResource;
import de.danet.an.workflow.spis.rms.DefaultResource;
import de.danet.an.workflow.spis.rms.DefaultRoleResource;
import de.danet.an.workflow.spis.rms.DefaultUserResource;
import de.danet.an.workflow.spis.rms.FactoryConfigurationError;
import de.danet.an.workflow.spis.rms.ResourceAssignmentContext;
import de.danet.an.workflow.spis.rms.ResourceManagementService;
import de.danet.an.workflow.spis.rms.ResourceNotFoundException;
/**
* Implements the {@link
* de.danet.an.workflow.spis.rms.ResourceManagementService resource
* management service} based on an LDAP server.
*
* @author <a href="mailto:lipp@danet.de">Michael Lipp</a>
* @version $Revision: 2052 $
*/
public class EisRmsService implements ResourceManagementService {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(EisRmsService.class);
private RmsConnectionFactory conFac = null;
private ResourceAssignmentContext rasCtx = null;
/**
* Constructs a new resource management service.
*
* @param props the configuration properties
* @param rasvc the resource assignment service
* @throws FactoryConfigurationError if the required resources
* cannot be obtained
*/
public EisRmsService
(RmsConnectionFactory conFac, ResourceAssignmentContext rasCtx)
throws FactoryConfigurationError {
this.conFac = conFac;
this.rasCtx = rasCtx;
}
/**
* Given a {@link java.security.Principal principal}, return the
* workflow resource associated with this principal by the
* resource management facility.<P>
*
* @param principal the principal.
* @return a <code>WfResource</code> object corresponding to the
* given principal.
* @throws ResourceNotFoundException 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 ResourceNotFoundException, RemoteException {
RmsConnection con = null;
try {
con = conFac.getConnection();
RmsEntry e = con.lookupUserByAccountName (principal.getName());
return new DefaultUserResource(rasCtx, e.getKey(), e.getDisplayName());
} catch (ResourceException e) {
maybeMapToRemoteException (e);
throw new ResourceNotFoundException("Not found: " + e.getMessage());
} catch (NameNotFoundException e) {
throw new ResourceNotFoundException
("No user \"" + principal.getName() + "\" found: "
+ e.getMessage());
} finally {
closeConnection(con);
}
}
/* Comment copied from interface */
public Collection authorizers (WfResource wfResource)
throws RemoteException {
RmsConnection con = null;
try {
Collection res = new ArrayList ();
if (!(wfResource instanceof DefaultUserResource)) {
return res;
}
con = conFac.getConnection();
Collection resRaw
= con.authorizers (((DefaultUserResource)wfResource).getId());
for (Iterator i = resRaw.iterator(); i.hasNext();) {
RmsEntry e = (RmsEntry)i.next();
addAsTyped(res, e);
}
return res;
} catch (ResourceException e) {
maybeMapToRemoteException (e);
throw new IllegalStateException
("Cannot get authorizers: " + e.getMessage());
} finally {
closeConnection(con);
}
}
/* Comment copied from interface */
public WfResource resourceByKey (String key)
throws ResourceNotFoundException, RemoteException {
RmsConnection con = null;
try {
con = conFac.getConnection();
if (DefaultUserResource.isValidKey(key)) {
RmsEntry e = con.lookupResource(DefaultUserResource.getId(key));
return new DefaultUserResource(rasCtx, e.getKey(), e.getDisplayName());
} else if (DefaultRoleResource.isValidKey(key)) {
RmsEntry e = con.lookupResource(DefaultRoleResource.getId(key));
return new DefaultRoleResource(rasCtx, e.getKey(), e.getDisplayName());
} else if (DefaultGroupResource.isValidKey(key)) {
RmsEntry e
= con.lookupResource(DefaultGroupResource.getId(key));
return new DefaultGroupResource(rasCtx, e.getKey(), e.getDisplayName());
} else {
RmsEntry e = con.lookupResource (key);
return new DefaultResource(rasCtx, e.getKey(), e.getDisplayName());
}
} catch (ResourceException e) {
maybeMapToRemoteException (e);
throw new ResourceNotFoundException("Not found: " + e.getMessage());
} catch (NameNotFoundException e) {
throw new ResourceNotFoundException
("No entry with key \"" + key + "\" found: " + e.getMessage());
} finally {
closeConnection(con);
}
}
/* Comment copied from interface. */
public Collection listResources () throws RemoteException {
RmsConnection con = null;
try {
con = conFac.getConnection();
Collection resRaw = con.listResources();
Collection res = new ArrayList ();
for (Iterator i = resRaw.iterator(); i.hasNext();) {
RmsEntry e = (RmsEntry)i.next();
addAsTyped(res, e);
}
return res;
} catch (ResourceException e) {
maybeMapToRemoteException (e);
throw new IllegalStateException
("Cannot list resources: " + e.getMessage());
} finally {
closeConnection(con);
}
}
/**
* The <code>resSel</code> paramter is poassed to the resource adapter.
* See the description of the configured resource adapter to find out
* about its interpretation.
*
* @param resSel an object that describes resource selection criteria
* @return collection of <code>WfResource</code> objects
* @throws RemoteException if a system-level error occurs
* @throws UnsupportedOperationException if the resource management
* service does not support this feature.
*/
public Collection selectResources (Object resSel)
throws RemoteException, UnsupportedOperationException {
RmsConnection con = null;
try {
con = conFac.getConnection();
Collection resRaw = con.selectResources(resSel);
Collection res = new ArrayList ();
for (Iterator i = resRaw.iterator(); i.hasNext();) {
RmsEntry e = (RmsEntry)i.next();
addAsTyped(res, e);
}
return res;
} catch (ResourceException e) {
maybeMapToRemoteException (e);
throw new IllegalStateException
("Cannot select resources: " + e.getMessage());
} finally {
closeConnection(con);
}
}
/**
* @param res
* @param e
*/
private void addAsTyped(Collection res, RmsEntry e) {
if (e.getType() == RmsEntry.RESOURCE_TYPE_USER) {
res.add(new DefaultUserResource
(rasCtx, e.getKey(), e.getDisplayName()));
} else if (e.getType() == RmsEntry.RESOURCE_TYPE_ROLE) {
res.add(new DefaultRoleResource
(rasCtx, e.getKey(), e.getDisplayName()));
} else if (e.getType() == RmsEntry.RESOURCE_TYPE_GROUP) {
res.add(new DefaultGroupResource
(rasCtx, e.getKey(), e.getDisplayName()));
} else {
res.add(new DefaultResource
(rasCtx, e.getKey(), e.getDisplayName()));
}
}
private void maybeMapToRemoteException (ResourceException e)
throws RemoteException {
// Will repeating the operation help? Depends...
if (e instanceof ApplicationServerInternalException
|| e instanceof CommException
|| e instanceof EISSystemException
|| e instanceof javax.resource.spi.IllegalStateException
|| e instanceof LocalTransactionException
|| e instanceof ResourceAllocationException) {
throw (RemoteException)
(new RemoteException("Problem accessing resource: "
+ e.getMessage())).initCause(e);
}
}
private void closeConnection (RmsConnection con) {
if (con != null) {
try {
con.close();
} catch(ResourceException e) {
logger.warn ("Problem closing connection (ignored): "
+ e.getMessage());
}
}
}
}