/*
* 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: ConfigurationEJB.java 2941 2009-02-17 14:15:59Z drmlipp $
*
* $Log$
* Revision 1.11 2006/10/12 10:51:02 drmlipp
* Binding installation id to db.
*
* Revision 1.10 2006/10/07 20:41:34 mlipp
* Merged J2EE 1.4 adaptions from test branch.
*
* Revision 1.9 2006/10/01 10:03:19 mlipp
* Removed "hidden" process initialization.
*
* Revision 1.8 2006/09/29 12:32:10 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.7 2005/04/22 15:11:03 drmlipp
* Merged changes from 1.3 branch up to 1.3p15.
*
* Revision 1.4.2.3 2005/04/13 16:14:07 drmlipp
* Optimized db access.
*
* Revision 1.6 2005/04/08 11:28:03 drmlipp
* Merged changes from 1.3 branch up to 1.3p6.
*
* Revision 1.4.2.2 2005/04/04 20:09:04 drmlipp
* Changed WLS transaction isolation.
*
* Revision 1.5 2005/02/23 15:43:06 drmlipp
* Synchronized with 1.3.
*
* Revision 1.4.2.1 2005/02/15 14:46:15 drmlipp
* Fixed reentrant attribute (must be capitalized after all).
*
* Revision 1.4 2004/12/20 22:28:42 drmlipp
* Fixed reentrant attribute.
*
* Revision 1.3 2004/09/10 12:44:29 drmlipp
* Enabled call by reference for weblogic by default.
*
* Revision 1.2 2004/08/19 13:24:49 drmlipp
* Fixed AVK errors and (many) warnings.
*
* Revision 1.1.1.4 2004/08/18 15:17:38 drmlipp
* Update to 1.2
*
* Revision 1.23 2004/07/07 11:34:00 lipp
* Clarified transaction attributes.
*
* Revision 1.22 2004/07/04 17:36:03 lipp
* Added JOnAS support.
*
* Revision 1.21 2004/06/14 19:37:20 lipp
* Fixed assignment functions and cleaned up assignment related
* interfaces.
*
* Revision 1.20 2004/01/14 07:59:44 lipp
* Added transaction isolation attribute for WLS.
*
* Revision 1.19 2003/11/27 16:27:38 lipp
* Improved handling of SQLExceptions.
*
* Revision 1.18 2003/10/06 15:32:57 lipp
* More WebLogic adaptations.
*
* Revision 1.17 2003/09/26 12:52:01 lipp
* Changed role names.
*
* Revision 1.16 2003/06/29 21:26:35 lipp
* Javadoc fixes.
*
* Revision 1.15 2003/06/27 08:51:45 lipp
* Fixed copyright/license information.
*
* Revision 1.14 2003/06/04 13:15:50 lipp
* Optimized resource allocation/caching.
*
* Revision 1.13 2003/05/23 15:42:41 lipp
* Fixed deployment unit dependencies.
*
* Revision 1.12 2003/05/23 15:09:48 huaiyang
* clean up the methods and variable for caching home interface.
*
* Revision 1.11 2003/05/23 12:35:55 huaiyang
* setConnection as null for JDBCPersistentMap after used.
*
* Revision 1.10 2003/04/25 14:50:59 lipp
* Fixed javadoc errors and warnings.
*
* Revision 1.9 2003/03/31 16:50:28 huaiyang
* Logging using common-logging.
*
* Revision 1.8 2003/02/08 13:17:11 lipp
* Fixed usage of import exception.
*
* Revision 1.7 2003/01/21 12:12:10 ott
* next step weblogic 7.0
*
* Revision 1.6 2002/12/19 21:37:43 lipp
* Reorganized interfaces.
*
* Revision 1.5 2002/12/04 10:29:51 huaiyang
* Use the messages method of ImportException
*
* Revision 1.4 2002/12/02 15:55:31 huaiyang
* Replace ParseException with ImportException.
*
* Revision 1.3 2002/11/26 11:23:30 lipp
* Modified RemoteException comment.
*
* Revision 1.2 2002/11/22 13:16:44 lipp
* Made ResourceNotAvailableException a RemoteException.
*
* Revision 1.1 2002/11/21 12:09:12 montag
* Moved *Bean to *EJB for workflow.
*
* Revision 1.32 2002/11/21 11:37:11 montag
* xdoclet for wfcore finished.
*
* Revision 1.31 2002/11/20 14:32:41 montag
* begin generation of home and remote interfaces.
*
* Revision 1.30 2002/11/19 11:29:39 montag
* begin generation of deployment descriptors.
*
* Revision 1.29 2002/10/17 13:53:28 lipp
* Fixed initial process definition bootstrap.
*
* Revision 1.28 2002/10/15 13:22:32 huaiyang
* Remove system.out.println and printStackTrace.
*
* Revision 1.27 2002/09/18 11:10:32 barzik
* extended to rollback transactions in case of application exceptions
*
* Revision 1.26 2002/09/02 12:25:26 huaiyang
* Use initialProcesses.xml as initial file.
*
* Revision 1.25 2002/08/30 21:32:07 lipp
* Finished transition to WorkflowEngine.
*
* Revision 1.24 2002/08/30 13:37:05 lipp
* Using Workflow engine facade now.
*
* Revision 1.23 2002/08/26 20:23:13 lipp
* Lots of method renames.
*
* Revision 1.22 2002/02/01 14:30:36 lipp
* Added error handling for process definition parsing.
*
* Revision 1.21 2002/01/26 19:17:42 lipp
* New installation id.
*
* Revision 1.20 2002/01/16 14:21:54 robert
* replace ProcessDefinitionDirectoryHome interface
* from workflow/ejbs/admin to workflow/api/ejbhomes
*
* Revision 1.19 2002/01/15 16:10:51 robert
* replace ProcessDefinitionDirectory interface from workflow/domain
* to workflow/api
*
* Revision 1.18 2002/01/11 12:51:13 robert
* cleanup not needed import statements
*
* 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/09 10:23:37 lipp
* Removed no longer needed newRMSFactory.
*
* Revision 1.14 2002/01/05 19:35:03 lipp
* Final log solution.
*
* Revision 1.13 2002/01/04 13:01:24 lipp
* Loading application specific log4j classes (1. try).
*
* Revision 1.12 2002/01/03 16:23:54 lipp
* Added info for loading process descriptions.
*
* Revision 1.11 2001/12/19 10:04:59 lipp
* ActivityFinder moved to ejbs/util.
*
* Revision 1.10 2001/12/17 15:51:55 lipp
* New methods for accessing services.
*
* Revision 1.9 2001/12/15 16:42:08 lipp
* Cleand up exception declaration for finder methods in home interfaces.
*
* Revision 1.8 2001/12/15 15:52:01 lipp
* Implementation of ActivityFinder completed.
*
* Revision 1.7 2001/12/14 16:05:45 lipp
* Partial implementation of ActivityFinder.
*
* Revision 1.6 2001/12/14 13:28:25 lipp
* Cleaned up implementation structure of ProcessDefinitionDirectory,
* renamed Package to ProcessDirectoryPackage and restored initial load
* of process definitions.
*
* Revision 1.5 2001/12/13 16:19:59 robert
* Temporary test method for resource management service.
*
* Revision 1.4 2001/12/11 12:47:37 lipp
* JavaDoc fixes.
*
* Revision 1.3 2001/12/10 09:53:58 robert
* changed Vector to ArrayList
*
* Revision 1.2 2001/12/05 07:53:23 ott
* Fehler korrigiert
*
* Revision 1.1 2001/12/04 13:58:40 ott
* new classes
*
*
*/
package de.danet.an.workflow.ejbs.admin;
import java.io.IOException;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.SQLException;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.ObjectNotFoundException;
import javax.naming.NamingException;
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.persistentmaps.JDBCPersistentMap;
import de.danet.an.util.persistentmaps.PersistentMapSQLException;
import de.danet.an.workflow.domain.AbstractConfiguration;
import de.danet.an.workflow.ejbs.core.WfActivityHome;
import de.danet.an.workflow.spis.ras.NoSuchActivityException;
/**
* The entity bean <code>ConfigurationEJB</code> gives access to all
* configuration parameters for the workflow package and provides
* some utility methods that are (in the widest sense) associated with
* the configuration of the package.
*
* @ejbHome <{de.danet.an.workflow.ejbs.admin.ConfigurationHome}>
* @ejbRemote <{de.danet.an.workflow.ejbs.admin.Configuration}>
*
* @ejb.bean name="ConfigurationBean" display-name="ConfigurationBean"
* jndi-name="ejb/@@@_JNDI_Name_Prefix_@@@ConfigurationBean"
* type="BMP" reentrant="false" view-type="both"
* @jonas.bean ejb-name="ConfigurationBean"
* @ejb.pk class="java.lang.Integer" generate="false"
* @ejb.home
* remote-class="de.danet.an.workflow.ejbs.admin.ConfigurationHome"
* @ejb.interface
* extends="javax.ejb.EJBObject, de.danet.an.workflow.api.Configuration"
* remote-class="de.danet.an.workflow.ejbs.admin.Configuration"
* @ejb.transaction type="Required"
* @ejb.ejb-ref ejb-name="ActivityBean" view-type="remote"
* @ejb.resource-ref res-ref-name="jdbc/WfEngine"
* res-type="javax.sql.DataSource" res-auth="Container"
* @jonas.resource res-ref-name="jdbc/WfEngine" jndi-name="jdbc_1"
* @weblogic.enable-call-by-reference True
* @weblogic.resource-description
* res-ref-name="jdbc/WfEngine" jndi-name="DefaultDS"
* @ejb.permission role-name="WfMOpenAdmin"
* @weblogic.transaction-isolation TRANSACTION_READ_COMMITTED
*/
public class ConfigurationEJB extends AbstractConfiguration
implements EntityBean {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(ConfigurationEJB.class);
/** The EntityContext interface of the instance. */
private EntityContext ctx;
/**
* The data source of the database.
* @see javax.sql.DataSource
*/
private DataSource ds = null;
/** Database name */
private static final String DB_NAME = "java:comp/env/jdbc/WfEngine";
/** The configuration properties */
private JDBCPersistentMap confProps = null;
/** The installation id */
private static String installationId = null;
/** Track if ejbStore needs to do anything. */
private boolean modified = false;
/** The cached home interface of the activity. */
private WfActivityHome activityHomeCache = null;
/**
* The home interface of the WfActivityBean.
* @return home interface of the WfActivityBean
*/
private WfActivityHome activityHome()
throws ResourceNotAvailableException {
if (activityHomeCache == null) {
activityHomeCache = (WfActivityHome)EJBUtil.retrieveEJBHome
(WfActivityHome.class, "java:comp/env/ejb/ActivityBean");
}
return activityHomeCache;
}
/**
* Set the associated entity context. The container calls this method
* after the instance creation.
* @see javax.ejb.EntityBean
* @param context - A SessionContext interface for the instance
* @throws EJBException on any error.
*/
public void setEntityContext(EntityContext context)
throws EJBException {
ctx = context;
activityHomeCache = null;
// getting new data source
try {
ds = JDBCUtil.refreshDS(null, DB_NAME);
} catch (NamingException ne) {
throw new EJBException(ne);
}
}
/**
* Unset the associated entity context.
* @see javax.ejb.EntityBean
*/
public void unsetEntityContext() throws EJBException {
ds = null;
activityHomeCache = null;
ctx = null;
}
/**
* The activate method is called when the instance is activated from its
* "passive" state. The instance should acquire any resource that it has
* released earlier in the ejbPassivate() method.
* This method gets the primary key from container.
* @see javax.ejb.EntityBean
*/
public void ejbActivate() throws EJBException {
// getting data
try {
readConfiguration();
} catch (IOException ne) {
throw new EJBException(ne);
}
try {
confProps = new JDBCPersistentMap (ds, "Configuration");
} catch (SQLException ne) {
throw new EJBException(ne);
}
}
/**
* The passivate method is called before the instance enters the
* "passive" state. The instance should release any resources that it
* can re-acquire later in the ejbActivate() method.
* @see javax.ejb.EntityBean
*/
public void ejbPassivate() throws EJBException {
confProps = null;
}
/**
* A container invokes this method before it ends the life of the session
* object. This happens as a result of a client's invoking a remove
* operation, or when a container decides to terminate the session object
* after a timeout.
* @see javax.ejb.EntityBean
*/
public void ejbRemove() throws RemoteException, EJBException {
throw new EJBException ("Read-only bean");
}
/**
* This method saves modified configuration data in the
* database.
*
* @throws EJBException if an <code>SQLException</code> occurs.
*/
public void ejbStore() throws EJBException {
if (! modified) {
return;
}
try {
Connection con = null;
try {
con = ds.getConnection();
confProps.setConnection (con);
try {
confProps.store ();
} catch (PersistentMapSQLException e) {
throw (SQLException)e.getCause();
}
} finally {
confProps.setConnection (null);
JDBCUtil.closeAll (null, null, con);
}
} catch (SQLException ex) {
throw new EJBException(ex);
} catch (IOException ex) {
throw new EJBException(ex);
}
modified = false;
}
/**
* This method loads additional configuration data from the
* database. Note that most configuration data is read in
* {@link #ejbActivate <code>ejbActivate()</code>}.
*
* @throws EJBException if an <code>SQLException</code> occurs.
*/
public void ejbLoad() throws EJBException {
try {
Connection con = null;
try {
con = ds.getConnection();
confProps.setConnection (con);
confProps.load ();
} finally {
confProps.setConnection (null);
JDBCUtil.closeAll (null, null, con);
}
} catch (SQLException ex) {
throw new EJBException(ex);
} catch (IOException ex) {
throw new EJBException(ex);
}
}
/**
* Create an new instance. Not needed.
* @return primary key of the bean
* @throws CreateException Throws if the ProcessDirectoryBean can not
* be create.
* @throws EJBException Throws on any error except
* <CreateException>.
* @ejb.create-method
* view-type="remote"
*/
public Integer ejbCreate() throws CreateException, EJBException {
throw new CreateException ("Read-only bean");
}
/**
* Called after creating a new instance.
* @throws CreateException if the activity can not be create.
*/
public void ejbPostCreate()
throws CreateException {
}
/**
* Find the ConfigurationBean.
* Only one instance of this bean exists. The primary key is
* allways the integer value 0.
* @param pk The primary key of the bean
* @return The primary key.
* @throws FinderException (<code>ObjectNotFoundException</code>)
* if no activity found.
*/
public Integer ejbFindByPrimaryKey(Integer pk)
throws FinderException {
if (pk.intValue() != 0) {
throw new ObjectNotFoundException();
}
return pk;
}
/**
* This Method reads the configuration-files and updates
* the parameters.
*
* @throws IOException if an IO Error occurs.
*/
public void readConfiguration() throws IOException {
}
/**
* Returns an installation id for the component. The id remains
* the same until the database is re-created.
* @return an installation id
* @ejb.interface-method view-type="remote"
*/
public String workflowEngineInstanceKey () {
if (installationId == null) {
installationId = (String)confProps.get("InstallationId");
if (installationId == null) {
installationId = getDbId() + ";" + System.currentTimeMillis();
confProps.put("InstallationId", installationId);
modified = true;
}
}
return installationId;
}
private String getDbId () {
String dbCatalog = "(unknown)";
String dbUrl = "(unknown)";
Connection con = null;
try {
con = ds.getConnection();
dbUrl = con.getMetaData().getURL();
dbCatalog = con.getCatalog();
} catch (SQLException e) {
logger.warn ("Problem getting DB info, using defaults: "
+ e.getMessage(), e);
} finally {
try {
JDBCUtil.closeAll(null, null, con);
} catch (SQLException e) {
logger.debug("Problem closing connection (ignored): "
+ e.getMessage(), e);
}
}
return dbCatalog + "@" + dbUrl;
}
/**
* Find the activity with the given key. This method really has no
* logical association with the configuration. It must however be
* provided by an entity bean. See
* {@link de.danet.an.workflow.ejbs.admin.ActivityFinder
* the description of <code>ActivityFinder</code>} for details.
*
* @param key the activity's key.
* @return the activity found.
* @throws NoSuchActivityException if <code>key</code> is invalid.
* @ejb.interface-method view-type="remote"
*/
public de.danet.an.workflow.omgcore.WfActivity findActivity (String key)
throws NoSuchActivityException {
try {
return activityHome().findByPrimaryKey (new Long(key));
} catch (NumberFormatException nfex) {
ctx.setRollbackOnly();
throw new NoSuchActivityException
("Invalid activity key " + nfex.getMessage());
} catch (ObjectNotFoundException fex) {
throw new NoSuchActivityException (fex.getMessage());
} catch (FinderException fe) {
throw new EJBException (fe);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
}