[jbpm-commits] JBoss JBPM SVN: r4759 - in jbpm3/branches/jbpm-3.2.5.SP/modules/core/src: main/java/org/jbpm/configuration and 6 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu May 7 09:21:23 EDT 2009


Author: alex.guizar at jboss.com
Date: 2009-05-07 09:21:23 -0400 (Thu, 07 May 2009)
New Revision: 4759

Added:
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassLoadersTest.java
Removed:
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java
Modified:
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoader.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/XmlUtil.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmConfigurationTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmContextTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java
Log:
[JBPM-2202] merge r4689 from trunk;
take parent class loader into account when looking up a cached process class loader

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -24,10 +24,11 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.util.Stack;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -48,30 +49,31 @@
 
 /**
  * configuration of one jBPM instance.
- * 
  * <p>
- * During process execution, jBPM might need to use some services. A JbpmConfiguration contains the knowledge on how to
- * create those services.
+ * During process execution, jBPM might need to use some services. A JbpmConfiguration contains the
+ * knowledge on how to create those services.
  * </p>
- * 
  * <p>
- * A JbpmConfiguration is a thread safe object and serves as a factory for {@link org.jbpm.JbpmContext}s, which means
- * one JbpmConfiguration can be used to create {@link org.jbpm.JbpmContext}s for all threads. The single
- * JbpmConfiguration can be maintained in a static member or in the JNDI tree if that is available.
+ * A JbpmConfiguration is a thread safe object and serves as a factory for
+ * {@link org.jbpm.JbpmContext}s, which means one JbpmConfiguration can be used to create
+ * {@link org.jbpm.JbpmContext}s for all threads. The single JbpmConfiguration can be maintained in
+ * a static member or in the JNDI tree if that is available.
  * </p>
- * 
  * <p>
  * A JbpmConfiguration can be obtained in following ways:
+ * </p>
  * <ul>
  * <li>from a resource (by default <code>jbpm.cfg.xml</code> is used):
  * 
  * <pre>
+ * 
  * JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
  * </pre>
  * 
  * or
  * 
  * <pre>
+ * 
  * String myXmlResource = &quot;...&quot;;
  * JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance(myXmlResource);
  * </pre>
@@ -88,8 +90,8 @@
  * </pre>
  * 
  * </li>
- * <li>By specifying a custom implementation of an object factory. This can be used to specify a JbpmConfiguration in
- * other bean-style notations such as used by JBoss Microcontainer or Spring.
+ * <li>By specifying a custom implementation of an object factory. This can be used to specify a
+ * JbpmConfiguration in other bean-style notations such as used by JBoss Microcontainer or Spring.
  * 
  * <pre>
  * ObjectFactory of = new &lt;i&gt;MyCustomObjectFactory&lt;/i&gt;();
@@ -99,10 +101,9 @@
  * 
  * </li>
  * </ul>
- * </p>
- * 
  * <p>
- * JbpmConfigurations can be configured using a spring-like XML notation (in relax ng compact notation):
+ * JbpmConfigurations can be configured using a spring-like XML notation (in relax ng compact
+ * notation):
  * </p>
  * 
  * <pre>
@@ -234,123 +235,97 @@
  * </pre>
  * 
  * </p>
- * 
  * <p>
  * Other configuration properties
+ * </p>
  * <table>
  * <tr>
  * <td>jbpm.files.dir</td>
- * <td></td>
+ * <td/>
  * </tr>
  * <tr>
  * <td>jbpm.types</td>
- * <td></td>
+ * <td/>
  * </tr>
  * </table>
- * </p>
  */
-public class JbpmConfiguration implements Serializable
-{
+public class JbpmConfiguration implements Serializable {
 
   private static final long serialVersionUID = 1L;
 
   static ObjectFactory defaultObjectFactory;
-  static Map instances = new HashMap();
-  static ThreadLocal jbpmConfigurationsStacks = new ThreadLocal();
+  static final Map instances = new HashMap();
+  static final ThreadLocal jbpmConfigurationStacks = new StackThreadLocal();
 
-  private ObjectFactory objectFactory;
-  private ThreadLocal jbpmContextStacks = new ThreadLocal();
+  private final ObjectFactory objectFactory;
+  private final ThreadLocal jbpmContextStacks = new StackThreadLocal();
   private JobExecutor jobExecutor;
+  private boolean isClosed;
 
-  public JbpmConfiguration(ObjectFactory objectFactory)
-  {
+  static class StackThreadLocal extends ThreadLocal {
+
+    protected Object initialValue() {
+      return new ArrayList();
+    }
+  }
+
+  public JbpmConfiguration(ObjectFactory objectFactory) {
     this.objectFactory = objectFactory;
   }
 
-  public static JbpmConfiguration getInstance()
-  {
+  public static JbpmConfiguration getInstance() {
     return getInstance(null);
   }
 
-  public static JbpmConfiguration getInstance(String resource)
-  {
-    JbpmConfiguration instance = null;
-    synchronized (instances)
-    {
-      if (resource == null)
-      {
-        resource = "jbpm.cfg.xml";
-      }
+  public static JbpmConfiguration getInstance(String resource) {
+    if (resource == null) {
+      resource = "jbpm.cfg.xml";
+    }
 
-      instance = (JbpmConfiguration)instances.get(resource);
-      if (instance == null)
-      {
-
-        if (defaultObjectFactory != null)
-        {
-          log.debug("creating jbpm configuration from given default object factory '" + defaultObjectFactory + "'");
+    JbpmConfiguration instance;
+    synchronized (instances) {
+      // look for configuration in cache
+      instance = (JbpmConfiguration) instances.get(resource);
+      if (instance == null) {
+        // configuration does not exist or was evicted, construct it
+        if (defaultObjectFactory != null) {
+          if (log.isDebugEnabled()) {
+            log.debug("creating configuration from default object factory: " + defaultObjectFactory);
+          }
           instance = new JbpmConfiguration(defaultObjectFactory);
-
         }
-        else
-        {
-
-          try
-          {
-            log.info("using jbpm configuration resource '" + resource + "'");
-            InputStream jbpmCfgXmlStream = ClassLoaderUtil.getJbpmConfigurationStream(resource);
-
-            // if a custom resource is to be used, but is not found in the
-            // classpath
-            // log a warning (otherwise, users who want to load custom stuff
-            // will be confused if the resource is not found and not loaded,
-            // without
-            // any notice)
-            if (jbpmCfgXmlStream == null && !"jbpm.cfg.xml".equals(resource))
-            {
-              log.warn("jbpm configuration resource '" + resource + "' is not available");
-            }
-
-            ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
-            instance = createJbpmConfiguration(objectFactory);
-
+        else {
+          log.info("using configuration resource: " + resource);
+          InputStream jbpmCfgXmlStream = ClassLoaderUtil.getStream(resource, false);
+          /*
+           * if a custom resource is specified, but not found in the classpath, log a warning;
+           * otherwise, users who want to load custom stuff will not receive any feedback when their
+           * resource cannot be found
+           */
+          if (jbpmCfgXmlStream == null && !"jbpm.cfg.xml".equals(resource)) {
+            log.warn("configuration resource '" + resource + "' could not be found");
           }
-          catch (RuntimeException e)
-          {
-            throw new JbpmException("couldn't parse jbpm configuration from resource '" + resource + "'", e);
-          }
+          ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
+          instance = createJbpmConfiguration(objectFactory);
         }
-
+        // put configuration in cache
         instances.put(resource, instance);
       }
     }
-
     return instance;
   }
 
-  public static boolean hasInstance(String resource)
-  {
-    boolean hasInstance = false;
-    if (resource == null)
-    {
-      resource = "jbpm.cfg.xml";
-    }
-    if ((instances != null) && (instances.containsKey(resource)))
-    {
-      hasInstance = true;
-    }
-    return hasInstance;
+  public static boolean hasInstance(String resource) {
+    return instances.containsKey(resource != null ? resource : "jbpm.cfg.xml");
   }
 
-  protected static ObjectFactory parseObjectFactory(InputStream inputStream)
-  {
+  protected static ObjectFactory parseObjectFactory(InputStream inputStream) {
     log.debug("loading defaults in jbpm configuration");
     ObjectFactoryParser objectFactoryParser = new ObjectFactoryParser();
     ObjectFactoryImpl objectFactoryImpl = new ObjectFactoryImpl();
     objectFactoryParser.parseElementsFromResource("org/jbpm/default.jbpm.cfg.xml", objectFactoryImpl);
 
-    if (inputStream != null)
-    {
+    if (inputStream != null) {
       log.debug("loading specific configuration...");
       objectFactoryParser.parseElementsStream(inputStream, objectFactoryImpl);
     }
@@ -358,34 +333,26 @@
     return objectFactoryImpl;
   }
 
-  /**
-   * create an ObjectFacotory from an XML string.
-   */
-  public static JbpmConfiguration parseXmlString(String xml)
-  {
+  public static JbpmConfiguration parseXmlString(String xml) {
     log.debug("creating jbpm configuration from xml string");
     InputStream inputStream = null;
-    if (xml != null)
-    {
+    if (xml != null) {
       inputStream = new ByteArrayInputStream(xml.getBytes());
     }
     ObjectFactory objectFactory = parseObjectFactory(inputStream);
     return createJbpmConfiguration(objectFactory);
   }
 
-  protected static JbpmConfiguration createJbpmConfiguration(ObjectFactory objectFactory)
-  {
+  protected static JbpmConfiguration createJbpmConfiguration(ObjectFactory objectFactory) {
     JbpmConfiguration jbpmConfiguration = new JbpmConfiguration(objectFactory);
 
-    // now we make the bean jbpm.configuration always availble
-    if (objectFactory instanceof ObjectFactoryImpl)
-    {
-      ObjectFactoryImpl objectFactoryImpl = (ObjectFactoryImpl)objectFactory;
+    // make the bean jbpm.configuration always available
+    if (objectFactory instanceof ObjectFactoryImpl) {
+      ObjectFactoryImpl objectFactoryImpl = (ObjectFactoryImpl) objectFactory;
       ObjectInfo jbpmConfigurationInfo = new ValueInfo("jbpmConfiguration", jbpmConfiguration);
       objectFactoryImpl.addObjectInfo(jbpmConfigurationInfo);
 
-      if (getHideStaleObjectExceptions(objectFactory))
-      {
+      if (getHideStaleObjectExceptions(objectFactory)) {
         StaleObjectLogConfigurer.hideStaleObjectExceptions();
       }
     }
@@ -393,77 +360,68 @@
     return jbpmConfiguration;
   }
 
-  private static boolean getHideStaleObjectExceptions(ObjectFactory objectFactory)
-  {
-    if (!objectFactory.hasObject("jbpm.hide.stale.object.exceptions"))
-    {
-      return true;
-    }
+  private static boolean getHideStaleObjectExceptions(ObjectFactory objectFactory) {
+    if (!objectFactory.hasObject("jbpm.hide.stale.object.exceptions")) return true;
+
     Object object = objectFactory.createObject("jbpm.hide.stale.object.exceptions");
-    return object instanceof Boolean ? ((Boolean)object).booleanValue() : true;
+    return object instanceof Boolean ? ((Boolean) object).booleanValue() : true;
   }
 
-  public static JbpmConfiguration parseInputStream(InputStream inputStream)
-  {
-    ObjectFactory objectFactory = parseObjectFactory(inputStream);
+  public static JbpmConfiguration parseInputStream(InputStream inputStream) {
     log.debug("creating jbpm configuration from input stream");
+    ObjectFactory objectFactory = parseObjectFactory(inputStream);
     return createJbpmConfiguration(objectFactory);
   }
 
-  public static JbpmConfiguration parseResource(String resource)
-  {
+  public static JbpmConfiguration parseResource(String resource) {
+    if (log.isDebugEnabled()) {
+      log.debug("creating jbpm configuration from resource: " + resource);
+    }
     InputStream inputStream = null;
-    log.debug("creating jbpm configuration from resource '" + resource + "'");
-    if (resource != null)
-    {
-      inputStream = ClassLoaderUtil.getJbpmConfigurationStream(resource);
+    if (resource != null) {
+      inputStream = ClassLoaderUtil.getStream(resource, false);
     }
     ObjectFactory objectFactory = parseObjectFactory(inputStream);
     return createJbpmConfiguration(objectFactory);
   }
 
-  public JbpmContext createJbpmContext()
-  {
+  public JbpmContext createJbpmContext() {
     return createJbpmContext(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
   }
 
-  public JbpmContext createJbpmContext(String name)
-  {
-    JbpmContext jbpmContext = (JbpmContext)objectFactory.createObject(name);
+  public JbpmContext createJbpmContext(String name) {
+    ensureOpen();
+
+    JbpmContext jbpmContext = (JbpmContext) objectFactory.createObject(name);
     jbpmContext.jbpmConfiguration = this;
     jbpmContextCreated(jbpmContext);
     return jbpmContext;
   }
 
-  public ServiceFactory getServiceFactory(String serviceName)
-  {
+  private void ensureOpen() {
+    if (isClosed) throw new JbpmException("configuration closed");
+  }
+
+  public ServiceFactory getServiceFactory(String serviceName) {
     return getServiceFactory(serviceName, JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
   }
 
-  public ServiceFactory getServiceFactory(String serviceName, String jbpmContextName)
-  {
-    ServiceFactory serviceFactory = null;
+  public ServiceFactory getServiceFactory(String serviceName, String jbpmContextName) {
     JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
-    try
-    {
-      serviceFactory = jbpmContext.getServices().getServiceFactory(serviceName);
+    try {
+      return jbpmContext.getServices().getServiceFactory(serviceName);
     }
-    finally
-    {
+    finally {
       jbpmContext.close();
     }
-    return serviceFactory;
   }
 
-  public static ClassLoader getProcessClassLoader(ProcessDefinition processDefinition)
-  {
-    ProcessClassLoaderFactory factory = null;
-    if (Configs.hasObject("jbpm.processClassLoader"))
-    {
-      factory = (ProcessClassLoaderFactory)Configs.getObject("jbpm.processClassLoader");
+  public static ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
+    ProcessClassLoaderFactory factory;
+    if (Configs.hasObject("process.class.loader.factory")) {
+      factory = (ProcessClassLoaderFactory) Configs.getObject("process.class.loader.factory");
     }
-    else
-    {
+    else {
       factory = new DefaultProcessClassLoaderFactory();
     }
     return factory.getProcessClassLoader(processDefinition);
@@ -472,270 +430,232 @@
   /**
    * gives the jbpm domain model access to configuration information via the current JbpmContext.
    */
-  public abstract static class Configs
-  {
+  public static class Configs {
 
-    public static ObjectFactory getObjectFactory()
-    {
+    private Configs() {
+      // hide default constructor to prevent instantiation
+    }
+
+    public static ObjectFactory getObjectFactory() {
       ObjectFactory objectFactory = null;
       JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
-      if (jbpmContext != null)
-      {
+      if (jbpmContext != null) {
         objectFactory = jbpmContext.objectFactory;
       }
-      else
-      {
+      else {
         objectFactory = getInstance().objectFactory;
       }
       return objectFactory;
     }
 
-    public static void setDefaultObjectFactory(ObjectFactory objectFactory)
-    {
+    public static void setDefaultObjectFactory(ObjectFactory objectFactory) {
       defaultObjectFactory = objectFactory;
     }
 
-    public static boolean hasObject(String name)
-    {
+    public static boolean hasObject(String name) {
       ObjectFactory objectFactory = getObjectFactory();
       return objectFactory.hasObject(name);
     }
 
-    public static synchronized Object getObject(String name)
-    {
+    public static synchronized Object getObject(String name) {
       ObjectFactory objectFactory = getObjectFactory();
       return objectFactory.createObject(name);
     }
 
-    public static String getString(String name)
-    {
-      return (String)getObject(name);
+    public static String getString(String name) {
+      return (String) getObject(name);
     }
 
-    public static long getLong(String name)
-    {
-      return ((Long)getObject(name)).longValue();
+    public static long getLong(String name) {
+      return ((Long) getObject(name)).longValue();
     }
 
-    public static int getInt(String name)
-    {
-      return ((Integer)getObject(name)).intValue();
+    public static int getInt(String name) {
+      return ((Integer) getObject(name)).intValue();
     }
 
-    public static boolean getBoolean(String name)
-    {
-      return ((Boolean)getObject(name)).booleanValue();
+    public static boolean getBoolean(String name) {
+      return ((Boolean) getObject(name)).booleanValue();
     }
   }
 
-  public void cleanSchema()
-  {
+  public void cleanSchema() {
     cleanSchema(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
   }
 
-  public void cleanSchema(String jbpmContextName)
-  {
-    JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
-    try
-    {
-      Services services = jbpmContext.getServices();
-      DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory)services.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
-      persistenceServiceFactory.cleanSchema();
-    }
-    finally
-    {
-      jbpmContext.close();
-    }
+  public void cleanSchema(String jbpmContextName) {
+    getPersistenceServiceFactory(jbpmContextName).cleanSchema();
   }
 
-  public void createSchema()
-  {
+  public void createSchema() {
     createSchema(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
   }
 
-  public void createSchema(String jbpmContextName)
-  {
-    JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
-    try
-    {
-      Services services = jbpmContext.getServices();
-      DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory)services.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
-      persistenceServiceFactory.createSchema();
-    }
-    finally
-    {
-      jbpmContext.close();
-    }
+  public void createSchema(String jbpmContextName) {
+    getPersistenceServiceFactory(jbpmContextName).createSchema();
   }
 
-  public void dropSchema()
-  {
+  public void dropSchema() {
     dropSchema(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
   }
 
-  public void dropSchema(String jbpmContextName)
-  {
-    log.warn("Dropping schema: " + jbpmContextName);
-    JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
-    try
-    {
-      Services services = jbpmContext.getServices();
-      DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory)services.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
-      persistenceServiceFactory.dropSchema();
-    }
-    finally
-    {
-      jbpmContext.close();
-    }
+  public void dropSchema(String jbpmContextName) {
+    getPersistenceServiceFactory(jbpmContextName).dropSchema();
   }
 
-  public void close()
-  {
-    close(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
+  private DbPersistenceServiceFactory getPersistenceServiceFactory(String jbpmContextName) {
+    return (DbPersistenceServiceFactory) getServiceFactory(Services.SERVICENAME_PERSISTENCE, jbpmContextName);
   }
 
-  public void close(String jbpmContextName)
-  {
-    JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
-    try
-    {
+  public boolean isClosed() {
+    return isClosed;
+  }
 
-      synchronized (instances)
-      {
-        Iterator iter = instances.values().iterator();
-        while (iter.hasNext())
-        {
-          if (this == iter.next())
-          {
-            iter.remove();
-            break;
-          }
-        }
-      }
+  public void close() {
+    close(JbpmContext.DEFAULT_JBPM_CONTEXT_NAME);
+  }
 
-      if (jobExecutor != null)
-      {
-        jobExecutor.stop();
-      }
+  public void close(String jbpmContextName) {
+    // prevent configuration from being closed more than once
+    if (isClosed) return;
 
+    // stop job executor
+    if (jobExecutor != null) {
+      jobExecutor.stop();
+      jobExecutor = null;
+    }
+
+    // close service factories
+    JbpmContext jbpmContext = createJbpmContext(jbpmContextName);
+    try {
       Map serviceFactories = jbpmContext.getServices().getServiceFactories();
-      if (serviceFactories != null)
-      {
-        Iterator iter = serviceFactories.values().iterator();
-        while (iter.hasNext())
-        {
-          ServiceFactory serviceFactory = (ServiceFactory)iter.next();
+      if (serviceFactories != null) {
+        for (Iterator i = serviceFactories.values().iterator(); i.hasNext();) {
+          ServiceFactory serviceFactory = (ServiceFactory) i.next();
           serviceFactory.close();
         }
       }
     }
-    finally
-    {
+    finally {
       jbpmContext.close();
     }
+
+    // closing service factories requires open configuration
+    isClosed = true;
+
+    // release context stack
+    jbpmContextStacks.set(null);
+
+    // remove from configuration cache
+    synchronized (instances) {
+      for (Iterator i = instances.values().iterator(); i.hasNext();) {
+        if (this == i.next()) {
+          i.remove();
+          break;
+        }
+      }
+    }
   }
 
-  static JbpmConfiguration getCurrentJbpmConfiguration()
-  {
+  static JbpmConfiguration getCurrentJbpmConfiguration() {
     JbpmConfiguration currentJbpmConfiguration = null;
-    Stack stack = getJbpmConfigurationStack();
-    if (!stack.isEmpty())
-    {
-      currentJbpmConfiguration = (JbpmConfiguration)stack.peek();
+    List stack = getJbpmConfigurationStack();
+    if (!stack.isEmpty()) {
+      currentJbpmConfiguration = (JbpmConfiguration) stack.get(stack.size() - 1);
     }
     return currentJbpmConfiguration;
   }
 
-  static synchronized Stack getJbpmConfigurationStack()
-  {
-    Stack stack = (Stack)jbpmConfigurationsStacks.get();
-    if (stack == null)
-    {
-      stack = new Stack();
-      jbpmConfigurationsStacks.set(stack);
+  static List getJbpmConfigurationStack() {
+    return (List) jbpmConfigurationStacks.get();
+  }
+
+  static void clearJbpmConfigurationStack() {
+    List configStack = getJbpmConfigurationStack();
+    if (configStack != null) {
+      Object[] configs = configStack.toArray();
+      for (int f = 0; f < configs.length; f++) {
+        JbpmConfiguration config = (JbpmConfiguration) configs[f];
+        List contextStack = config.getJbpmContextStack();
+        if (contextStack != null) {
+          Object[] contexts = contextStack.toArray();
+          for (int t = 0; t < contexts.length; t++) {
+            JbpmContext context = (JbpmContext) contexts[t];
+            context.close();
+          }
+        }
+        contextStack.clear();
+      }
+      configStack.clear();
     }
-    return stack;
   }
 
-  synchronized void pushJbpmConfiguration()
-  {
-    getJbpmConfigurationStack().push(this);
+  synchronized void pushJbpmConfiguration() {
+    getJbpmConfigurationStack().add(this);
   }
 
-  synchronized void popJbpmConfiguration()
-  {
+  synchronized void popJbpmConfiguration() {
     getJbpmConfigurationStack().remove(this);
   }
 
-  public JbpmContext getCurrentJbpmContext()
-  {
+  public JbpmContext getCurrentJbpmContext() {
+    ensureOpen();
+
     JbpmContext currentJbpmContext = null;
-    Stack stack = getJbpmContextStack();
-    if (!stack.isEmpty())
-    {
-      currentJbpmContext = (JbpmContext)stack.peek();
+    List stack = getJbpmContextStack();
+    if (!stack.isEmpty()) {
+      currentJbpmContext = (JbpmContext) stack.get(stack.size() - 1);
     }
     return currentJbpmContext;
   }
 
-  Stack getJbpmContextStack()
-  {
-    Stack stack = (Stack)jbpmContextStacks.get();
-    if (stack == null)
-    {
-      stack = new Stack();
-      jbpmContextStacks.set(stack);
-    }
-    return stack;
+  List getJbpmContextStack() {
+    return (List) jbpmContextStacks.get();
   }
 
-  void pushJbpmContext(JbpmContext jbpmContext)
-  {
-    getJbpmContextStack().push(jbpmContext);
+  void pushJbpmContext(JbpmContext jbpmContext) {
+    getJbpmContextStack().add(jbpmContext);
   }
 
-  void popJbpmContext(JbpmContext jbpmContext)
-  {
-    Stack stack = getJbpmContextStack();
-    if (stack.isEmpty())
-    {
-      throw new JbpmException("closed JbpmContext more then once... check your try-finally's around JbpmContexts blocks");
+  void popJbpmContext(JbpmContext jbpmContext) {
+    List stack = getJbpmContextStack();
+    int size = stack.size();
+    if (size == 0) {
+      log.warn("closed JbpmContext more than once... "
+          + "check your try-finally clauses around JbpmContext blocks");
     }
-    JbpmContext popped = (JbpmContext)stack.pop();
-    if (jbpmContext != popped)
-    {
-      throw new JbpmException("closed JbpmContext in different order then they were created... check your try-finally's around JbpmContexts blocks");
+    else if (jbpmContext != stack.remove(size - 1)) {
+      stack.remove(jbpmContext); // prevent context from remaining in the stack
+      log.warn("closed JbpmContext in some order that differs from creation... "
+          + "check your try-finally clauses around JbpmContext blocks");
     }
   }
 
-  void jbpmContextCreated(JbpmContext jbpmContext)
-  {
+  void jbpmContextCreated(JbpmContext jbpmContext) {
     pushJbpmConfiguration();
     pushJbpmContext(jbpmContext);
   }
 
-  void jbpmContextClosed(JbpmContext jbpmContext)
-  {
-    popJbpmConfiguration();
+  void jbpmContextClosed(JbpmContext jbpmContext) {
     popJbpmContext(jbpmContext);
+    popJbpmConfiguration();
   }
 
-  public void startJobExecutor()
-  {
+  public void startJobExecutor() {
     getJobExecutor().start();
   }
 
-  public synchronized JobExecutor getJobExecutor()
-  {
-    if (jobExecutor == null)
-    {
-      try
-      {
-        jobExecutor = (JobExecutor)this.objectFactory.createObject("jbpm.job.executor");
+  public synchronized JobExecutor getJobExecutor() {
+    ensureOpen();
+
+    if (jobExecutor == null) {
+      Object object = objectFactory.createObject("jbpm.job.executor");
+      if (object instanceof JobExecutor) {
+        jobExecutor = (JobExecutor) object;
       }
-      catch (ClassCastException e)
-      {
-        throw new JbpmException("jbpm configuration object under key 'jbpm.job.executor' is not a " + JobExecutor.class.getName(), e);
+      else if (object != null) {
+        throw new JbpmException("configuration object 'jbpm.job.executor' is not an "
+            + JobExecutor.class.getName());
       }
     }
     return jobExecutor;

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -37,6 +37,7 @@
   
   private static final long serialVersionUID = 1L;
 
+  ClassLoader classLoader = null; // lazy load it later! See below..
   List objectInfos = null;
   Map namedObjectInfos = null;
   Map singletons = new HashMap();
@@ -160,7 +161,14 @@
     // "lazy load" classloader, shouldn't be loaded too early 
     // because if jbpm.cfg.xml is not yet parsed, the correct class loader
     // may not be initialized yet.
-    return ClassLoaderUtil.loadClass(className);
+    if (classLoader==null) {
+      classLoader = ClassLoaderUtil.getClassLoader();
+    }    
+    try {
+      return classLoader.loadClass(className);
+    } catch (ClassNotFoundException e) {
+      throw new JbpmException("couldn't load class '"+className+"'", e);
+    }
   }
 
   Object getRegistryKey(ObjectInfo objectInfo) {

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -1,7 +1,5 @@
 package org.jbpm.instantiation;
 
-import java.io.Serializable;
-
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.util.ClassLoaderUtil;
 
@@ -10,12 +8,12 @@
  * 
  * @author bernd.ruecker at camunda.com
  */
-public class DefaultProcessClassLoaderFactory implements ProcessClassLoaderFactory, Serializable {
-  
+public class DefaultProcessClassLoaderFactory implements ProcessClassLoaderFactory {
+
   private static final long serialVersionUID = 1L;
 
   public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
     // default behavior like before https://jira.jboss.org/jira/browse/JBPM-1148    
     return new ProcessClassLoader(ClassLoaderUtil.getClassLoader(), processDefinition);
-  }  
+  }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoader.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoader.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoader.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -29,106 +29,127 @@
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
 
+import org.jbpm.JbpmContext;
 import org.jbpm.JbpmException;
 import org.jbpm.file.def.FileDefinition;
 import org.jbpm.graph.def.ProcessDefinition;
 
 public class ProcessClassLoader extends ClassLoader {
-  
-  private ProcessDefinition processDefinition = null;
 
-  public ProcessClassLoader( ClassLoader parent, ProcessDefinition processDefinition ) {
+  private ProcessDefinition processDefinition;
+  private long processDefinitionId;
+
+  public ProcessClassLoader(ClassLoader parent, ProcessDefinition processDefinition) {
     super(parent);
-    this.processDefinition = processDefinition;
+    // check whether the given process definition is transient
+    long id = processDefinition.getId();
+    if (id != 0) {
+      // persistent, keep id only
+      processDefinitionId = id;
+    }
+    else {
+      // transient, keep full object
+      this.processDefinition = processDefinition;
+    }
   }
 
+  protected ProcessDefinition getProcessDefinition() {
+    return processDefinition != null ? processDefinition : JbpmContext.getCurrentJbpmContext()
+        .getGraphSession()
+        .loadProcessDefinition(processDefinitionId);
+  }
+
   public URL findResource(String name) {
-    URL url = null;
+    ProcessDefinition processDefinition = getProcessDefinition();
     FileDefinition fileDefinition = processDefinition.getFileDefinition();
-    if (fileDefinition!=null) {
-      // if the name of the resources starts with a / 
-      if (name.startsWith("/")) {
-        // then we start searching from the root of the process archive
+    if (fileDefinition != null) {
+      // we know that the leading slashes are removed in the names of the
+      // file definitions, therefore we skip the leading slashes
+      int off = 0;
+      for (int len = name.length(); off < len && name.charAt(off) == '/'; off++)
+        /* just increase offset */;
 
-        // we know that the leading slashes are removed in the names of the 
-        // file definitions, therefor we skip the leading slashes
-        while (name.startsWith("/")) {
-          name = name.substring(1);
-        }
-      } else {
-        // otherwise, (if the resource is relative), we look in the classes
+      // if the name of the resources is absolute (starts with one or more slashes)
+      if (off > 0) {
+        // then start searching from the root of the process archive
+        name = name.substring(off);
+      }
+      else {
+        // otherwise (if the resource is relative), look in the classes
         // directory in the process archive
-        name = "classes/"+name;
+        name = "classes/" + name;
       }
 
       byte[] bytes = null;
       if (fileDefinition.hasFile(name)) {
         bytes = fileDefinition.getBytes(name);
       }
-      if (bytes!=null) {
+      if (bytes != null) {
         try {
-          url = new URL(null, "processresource://"+processDefinition.getName()+"/classes/"+name, new BytesUrlStreamHandler(bytes));
-        } catch (MalformedURLException e) {
+          return new URL(null, "processresource://"
+              + processDefinition.getName()
+              + "/classes/"
+              + name, new BytesUrlStreamHandler(bytes));
+        }
+        catch (MalformedURLException e) {
           throw new JbpmException("couldn't create url", e);
         }
       }
     }
-    return url;
+    return null;
   }
-  
+
   public static class BytesUrlStreamHandler extends URLStreamHandler {
+
     byte[] bytes;
+
     public BytesUrlStreamHandler(byte[] bytes) {
       this.bytes = bytes;
     }
+
     protected URLConnection openConnection(URL u) throws IOException {
       return new BytesUrlConnection(bytes, u);
     }
   }
 
   public static class BytesUrlConnection extends URLConnection {
+
     byte[] bytes = null;
+
     public BytesUrlConnection(byte[] bytes, URL u) {
       super(u);
       this.bytes = bytes;
     }
+
     public void connect() throws IOException {
     }
+
     public InputStream getInputStream() throws IOException {
       return new ByteArrayInputStream(bytes);
     }
   }
 
-  public Class findClass(String name) throws ClassNotFoundException {
-    Class clazz = null;
+  public Class findClass(String className) throws ClassNotFoundException {
+    FileDefinition fileDefinition = getProcessDefinition().getFileDefinition();
+    if (fileDefinition != null) {
+      String fileName = "classes/" + className.replace('.', '/') + ".class";
+      byte[] classBytes = fileDefinition.getBytes(fileName);
 
-    FileDefinition fileDefinition = processDefinition.getFileDefinition();
-    if (fileDefinition!=null) {
-      String fileName = "classes/" + name.replace( '.', '/' ) + ".class";
-      byte[] classBytes;
-      try {
-        classBytes = fileDefinition.getBytes(fileName);
-        clazz = defineClass(name, classBytes, 0, classBytes.length);
-      } catch (JbpmException e) {
-        clazz = null;
-      }
-      
-      // Add the package information
-      // see https://jira.jboss.org/jira/browse/JBPM-1404
-      final int packageIndex = name.lastIndexOf('.');
-      if (packageIndex != -1) {
-        final String packageName = name.substring(0, packageIndex);
-        final Package classPackage = getPackage(packageName);
-        if (classPackage == null) {
-          definePackage(packageName, null, null, null, null, null, null, null);
+      if (classBytes != null) {
+        // define the package before defining the class
+        // see https://jira.jboss.org/jira/browse/JBPM-1404
+        int packageIndex = className.lastIndexOf('.');
+
+        if (packageIndex != -1) {
+          String packageName = className.substring(0, packageIndex);
+
+          if (getPackage(packageName) == null) {
+            definePackage(packageName, null, null, null, processDefinition.getName(), Integer.toString(processDefinition.getVersion()), null, null);
+          }
         }
+        return defineClass(className, classBytes, 0, classBytes.length);
       }
     }
-
-    if (clazz==null) {
-      throw new ClassNotFoundException("class '"+name+"' could not be found by the process classloader");
-    }
-
-    return clazz;
+    throw new ClassNotFoundException(className);
   }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -1,21 +1,31 @@
 package org.jbpm.instantiation;
 
+import java.io.Serializable;
+
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.graph.def.ProcessDefinition;
 
 /**
- * Factory to retrieve the Process{@link ClassLoader} which is then used
- * to load delegation classes used by the process.
+ * <p>
+ * Factory to retrieve the Process {@link ClassLoader} which is then used to load delegation classes
+ * used by the process.
+ * </p>
+ * <p>
+ * Default is the build in {@link ProcessClassLoader}, which tries to load the classes from the jBPM
+ * database first.
+ * </p>
+ * <p>
+ * Can be configured by setting the property <code>jbpm.process.class.loader</code> in the
+ * configuration file to the class name of the custom class loader.
+ * </p>
+ * <p>
+ * Implementations should be serializable, as the {@link JbpmConfiguration} that references them is.
+ * </p>
  * 
- * Default is the build in {@link ProcessClassLoader}, which 
- * tries to load the classes from the jbpm database first.
- * 
- * Can be configured by setting the property <b>'jbpm.processClassLoader'</b>
- * in the jbpm.cfg.xml to the class name of the custom class loader.
- * 
  * @author bernd.ruecker at camunda.com
  */
-public interface ProcessClassLoaderFactory {
+public interface ProcessClassLoaderFactory extends Serializable {
 
   public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition);
-  
+
 }
\ No newline at end of file

Copied: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java (from rev 4689, jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java)
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.instantiation;
+
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.util.ClassLoaderUtil;
+
+/**
+ * Refined process class loader factory that maintains a cache of the class loaders it returns. The
+ * cache does not prevent class loaders from being discarded by the garbage collector.
+ * 
+ * @author Alejandro Guizar
+ */
+public class SharedProcessClassLoaderFactory implements ProcessClassLoaderFactory {
+
+  private transient Map classLoaderRefs = new HashMap();
+
+  private static final long serialVersionUID = 1L;
+
+  public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
+    // determine the key to lookup a cached class loader
+    // observe that the given process definition may be transient
+    long id = processDefinition.getId();
+    if (id == 0L) id = processDefinition.hashCode();
+    Long key = new Long(id);
+    // consider that the context class loader changes among applications
+    ClassLoader parentClassLoader = ClassLoaderUtil.getClassLoader();
+    assert parentClassLoader != null : "parent class loader is null";
+
+    synchronized (classLoaderRefs) {
+      // lookup the class loader reference
+      ClassLoader processClassLoader = getProcessClassLoader(key, parentClassLoader);
+      // the reference may not exist or may have been cleared already
+      if (processClassLoader == null) {
+        // (re-)create the class loader and the reference
+        processClassLoader = new ProcessClassLoader(parentClassLoader, processDefinition);
+        // cache the reference
+        putProcessClassLoader(key, processClassLoader);
+      }
+      return processClassLoader;
+    }
+  }
+
+  private ClassLoader getProcessClassLoader(Long processDefinitionKey, ClassLoader parentClassLoader) {
+    List referenceList = (List) classLoaderRefs.get(processDefinitionKey);
+    if (referenceList != null) {
+      for (Iterator i = referenceList.iterator(); i.hasNext();) {
+        SoftReference reference = (SoftReference) i.next();
+        ClassLoader processClassLoader = (ClassLoader) reference.get();
+        // reference may have been cleared already
+        if (processClassLoader == null) {
+          // remove cleared reference
+          i.remove();
+        }
+        // process class loader may have a different parent
+        else if (processClassLoader.getParent() == parentClassLoader) {
+          return processClassLoader;
+        }
+      }
+    }
+    return null;
+  }
+
+  private void putProcessClassLoader(Long processDefinitionKey, ClassLoader processClassLoader) {
+    List referenceList = (List) classLoaderRefs.get(processDefinitionKey);
+    if (referenceList == null) {
+      referenceList = new ArrayList();
+      classLoaderRefs.put(processDefinitionKey, referenceList);
+    }
+    referenceList.add(new SoftReference(processClassLoader));
+  }
+}

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -29,126 +29,132 @@
 import org.jbpm.JbpmException;
 
 /**
- * provides centralized classloader lookup. 
+ * provides centralized classloader lookup.
  */
-public class ClassLoaderUtil
-{
+public class ClassLoaderUtil {
 
-  private ClassLoaderUtil()
-  {
+  private ClassLoaderUtil() {
     // hide default constructor to prevent instantiation
   }
 
-  public static Class loadClass(String className)
-  {
-    try
-    {
+  /**
+   * Bad usage of ClassLoader.loadClass() under JDK 6.
+   * 
+   * @deprecated Use {@linkplain #classForName(String) classForName()} instead
+   * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1976">JBPM-1976</a>
+   */
+  public static Class loadClass(String className) {
+    try {
       return getClassLoader().loadClass(className);
     }
-    catch (ClassNotFoundException e)
-    {
+    catch (ClassNotFoundException e) {
       throw new JbpmException("class not found '" + className + "'", e);
     }
   }
 
-  /*
-   * returns the {@link ClassLoader} which is used in jbpm. Can be configured in jbpm.cfg.xml by the property <b>'jbpm.classloader'</b> <td> <li>'jbpm': (default value)
-   * uses the {@link ClassLoaderUtil}.class.getClassLoader() {@link ClassLoader}. This was the only behavior available before <a
-   * href="https://jira.jboss.org/jira/browse/JBPM-1148">JBPM-1148</a>.</li> <li>'context': uses the Thread.currentThread().getContextClassLoader().</li> <li>'custom':
-   * means that a ClassLoader class has to be provided in the property <b>'jbpm.classloader.classname'</b></li> </td>
+  public static Class classForName(String className) {
+    try {
+      return Class.forName(className, true, getClassLoader());
+    }
+    catch (ClassNotFoundException e) {
+      throw new JbpmException("class not found '" + className + "'", e);
+    }
+  }
+
+  public static Class classForName(String className, boolean useConfiguredLoader) {
+    if (useConfiguredLoader) return classForName(className);
+
+    // try context class loader first, so that applications can override provided classes
+    try {
+      return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
+    }
+    catch (ClassNotFoundException e) {
+      // try the class loader of the current class
+      try {
+        return Class.forName(className);
+      }
+      catch (ClassNotFoundException e2) {
+        // give up
+        throw new JbpmException("class not found '" + className + "'", e);
+      }
+    }
+  }
+
+  /**
+   * Returns the {@link ClassLoader} employed by jBPM to load classes referenced in the
+   * configuration. The class loader can be changed in <code>jbpm.cfg.xml</code> by setting the
+   * string property <code>jbpm.class.loader</code>. The possible values are:
+   * <ul>
+   * <li><code>jbpm</code> (default) indicates the class loader of the jBPM classes. Before <a
+   * href="https://jira.jboss.org/jira/browse/JBPM-1148">JBPM-1148</a> no other behavior was
+   * available</li>
+   * <li><code>context</code> indicates the {@linkplain Thread#getContextClassLoader() context class
+   * loader}</li>
+   * <li>any other value is interpreted as a reference to a class loader bean described in the
+   * configuration</li>
+   * </ul>
    */
-  public static ClassLoader getClassLoader()
-  {
-    if (JbpmConfiguration.Configs.hasObject("jbpm.classLoader"))
-    {
-      String jbpmClassloader = JbpmConfiguration.Configs.getString("jbpm.classLoader");
+  public static ClassLoader getClassLoader() {
+    if (JbpmConfiguration.Configs.hasObject("jbpm.class.loader")) {
+      String jbpmClassLoader = JbpmConfiguration.Configs.getString("jbpm.class.loader");
 
-      if (jbpmClassloader.equals("jbpm"))
-      {
+      if (jbpmClassLoader.equals("jbpm")) {
+        // use class loader that loaded the jbpm classes
         return ClassLoaderUtil.class.getClassLoader();
       }
-      else if (jbpmClassloader.equals("context"))
-      {
+
+      if (jbpmClassLoader.equals("context")) {
+        // use the context class loader
         return Thread.currentThread().getContextClassLoader();
       }
-      else if (jbpmClassloader.equals("custom"))
-      {
-        String jbpmClassloaderClassname = null;
-        try
-        {
-          if (!JbpmConfiguration.Configs.hasObject("jbpm.customClassLoader.className"))
-          {
-            throw new JbpmException("'jbpm.classloader' property set to 'custom' but 'jbpm.customClassLoader.className' is empty!");
-          }
-          jbpmClassloaderClassname = JbpmConfiguration.Configs.getString("jbpm.customClassLoader.className");
-          if (jbpmClassloaderClassname == null)
-          {
-            throw new JbpmException("'jbpm.classloader' property set to 'custom' but 'jbpm.customClassLoader.className' is empty!");
-          }
 
-          Class clazz = ClassLoaderUtil.class.getClassLoader().loadClass(jbpmClassloaderClassname);
-          if (clazz == null)
-            clazz = Thread.currentThread().getContextClassLoader().loadClass(jbpmClassloaderClassname);
-
-          return (ClassLoader)clazz.newInstance();
-        }
-        catch (InstantiationException e)
-        {
-          throw new JbpmException("Error instantiating custom classloader " + jbpmClassloaderClassname, e);
-        }
-        catch (IllegalAccessException e)
-        {
-          throw new JbpmException("Error accessing custom classloader " + jbpmClassloaderClassname, e);
-        }
-        catch (ClassNotFoundException e)
-        {
-          throw new JbpmException("Custom classloader " + jbpmClassloaderClassname + " not found ", e);
-        }
+      // interpret value as a reference to a class loader bean
+      Object bean = JbpmConfiguration.Configs.getObject(jbpmClassLoader);
+      if (!(bean instanceof ClassLoader)) {
+        throw new JbpmException("bean '" + jbpmClassLoader + "' is not a class loader");
       }
-      else
-      {
-        throw new JbpmException("'jbpm.classloader' property set to '" + jbpmClassloader + "' but only the values 'jbpm'/'context'/'custom' are supported!");
-      }
+      return (ClassLoader) bean;
     }
-    else
-    {
-      // default behavior like before https://jira.jboss.org/jira/browse/JBPM-1148
+    else {
+      // behave like before JBPM-1148
       return ClassLoaderUtil.class.getClassLoader();
     }
   }
 
-  public static InputStream getStream(String resource)
-  {
+  public static InputStream getStream(String resource) {
     return getClassLoader().getResourceAsStream(resource);
   }
 
-  /*
-   * Load jbpm configuration related resources as stream (normally jbpm.cfg.xml). This method first tries to load the resource from the {@link ClassLoaderUtil} class
-   * loader, if not found it tries the context class loader. If this doesn't return any ressource the call is delegated to the class loader configured by calling
-   * getClassLoader(). This is a special method because the class loader which has to be used for loading the jbpm.cfg.xml cannot be configured in the jbpm.cfg.xml
-   * itself.
+  /**
+   * Load jbpm configuration related resources as stream (normally jbpm.cfg.xml). This method first
+   * tries to load the resource from the {@link ClassLoaderUtil} class loader, if not found it tries
+   * the context class loader. If this doesn't return any ressource the call is delegated to the
+   * class loader configured by calling getClassLoader(). This is a special method because the class
+   * loader which has to be used for loading the jbpm.cfg.xml cannot be configured in the
+   * jbpm.cfg.xml itself.
    */
-  public static InputStream getJbpmConfigurationStream(String resource)
-  {
-    InputStream jbpmCfgStream = ClassLoaderUtil.class.getClassLoader().getResourceAsStream(resource);
-    if (jbpmCfgStream == null)
-    {
-      jbpmCfgStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
+  public static InputStream getStream(String resource, boolean useConfiguredLoader) {
+    if (useConfiguredLoader) return getStream(resource);
+
+    // try context class loader first, so that applications can override provided classes
+    InputStream stream = Thread.currentThread()
+        .getContextClassLoader()
+        .getResourceAsStream(resource);
+    if (stream == null) {
+      // try the class loader of the current class
+      stream = ClassLoaderUtil.class.getClassLoader().getResourceAsStream(resource);
     }
-    return jbpmCfgStream;
+    return stream;
   }
 
-  public static Properties getProperties(String resource)
-  {
+  public static Properties getProperties(String resource) {
     Properties properties = new Properties();
-    try
-    {
+    try {
       InputStream inStream = getStream(resource);
       properties.load(inStream);
       inStream.close();
     }
-    catch (IOException e)
-    {
+    catch (IOException e) {
       throw new JbpmException("couldn't load properties file '" + resource + "'", e);
     }
     return properties;

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/XmlUtil.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/XmlUtil.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/XmlUtil.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -59,20 +59,20 @@
   }
 
   /**
-   * @param isJbpmConfiguration specifies if the resource should be loaded
-   * with the "limited" bootstrap class loader for jbpm config.
+   * @param isJbpmConfiguration specifies if the resource should be loaded with the "limited"
+   *        bootstrap class loader for jbpm config.
    */
-  public static Document parseXmlResource(String resource, boolean isJbpmConfiguration) {    
+  public static Document parseXmlResource(String resource, boolean isJbpmConfiguration) {
     // decide which class loading mechanism to use for loading the jbpm
     // configuration (see https://jira.jboss.org/jira/browse/JBPM-1148)
     InputStream inputStream = null;
     if (isJbpmConfiguration)
-      inputStream = ClassLoaderUtil.getJbpmConfigurationStream(resource);
+      inputStream = ClassLoaderUtil.getStream(resource, false);
     else
       inputStream = ClassLoaderUtil.getStream(resource);
-    
+
     if (inputStream == null)
-    	throw new IllegalArgumentException("Cannot load resource: " + resource);
+      throw new IllegalArgumentException("Cannot load resource: " + resource);
     InputSource inputSource = new InputSource(inputStream);
     return parseXmlInputSource(inputSource);
   }
@@ -80,8 +80,9 @@
   public static Document parseXmlInputStream(InputStream inputStream) {
     Document document = null;
     try {
-      document  = getDocumentBuilder().parse(inputStream);
-    } catch (Exception e) {
+      document = getDocumentBuilder().parse(inputStream);
+    }
+    catch (Exception e) {
       throw new XmlException("couldn't parse xml", e);
     }
     return document;
@@ -90,14 +91,16 @@
   public static Document parseXmlInputSource(InputSource inputSource) {
     Document document = null;
     try {
-      document  = getDocumentBuilder().parse(inputSource);
-    } catch (Exception e) {
+      document = getDocumentBuilder().parse(inputSource);
+    }
+    catch (Exception e) {
       throw new XmlException("couldn't parse xml", e);
     }
     return document;
   }
 
-  public static DocumentBuilder getDocumentBuilder() throws FactoryConfigurationError, ParserConfigurationException {
+  public static DocumentBuilder getDocumentBuilder() throws FactoryConfigurationError,
+      ParserConfigurationException {
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     return factory.newDocumentBuilder();
   }
@@ -109,9 +112,9 @@
   public static List elements(Element element, String tagName) {
     NodeList nodeList = element.getElementsByTagName(tagName);
     List elements = new ArrayList(nodeList.getLength());
-    for (int i=0; i<nodeList.getLength(); i++) {
+    for (int i = 0; i < nodeList.getLength(); i++) {
       Node child = nodeList.item(i);
-      if(child.getParentNode()==element) {
+      if (child.getParentNode() == element) {
         elements.add(child);
       }
     }
@@ -121,7 +124,7 @@
   public static Element element(Element element, String name) {
     Element childElement = null;
     NodeList nodeList = element.getElementsByTagName(name);
-    if (nodeList.getLength()>0) {
+    if (nodeList.getLength() > 0) {
       childElement = (Element) nodeList.item(0);
     }
     return childElement;
@@ -134,43 +137,41 @@
   public static List elements(Element element) {
     List elements = new ArrayList();
     NodeList nodeList = element.getChildNodes();
-    for (int i=0; i<nodeList.getLength(); i++) {
+    for (int i = 0; i < nodeList.getLength(); i++) {
       Node node = nodeList.item(i);
-      if ( (node instanceof Element)
-           && (element==node.getParentNode())
-         ){
+      if ((node instanceof Element) && (element == node.getParentNode())) {
         elements.add(node);
       }
     }
     return elements;
   }
 
-
   public static Element element(Element element) {
     Element onlyChild = null;
     List elements = elements(element);
-    if (! elements.isEmpty()) {
+    if (!elements.isEmpty()) {
       onlyChild = (Element) elements.get(0);
     }
     return onlyChild;
   }
 
   public static String toString(Element element) {
-    if (element==null) return "null";
+    if (element == null) return "null";
 
     Source source = new DOMSource(element);
 
     StringWriter stringWriter = new StringWriter();
     PrintWriter printWriter = new PrintWriter(stringWriter);
     Result result = new StreamResult(printWriter);
-    
+
     try {
       Transformer transformer = TransformerFactory.newInstance().newTransformer();
       transformer.transform(source, result);
-    } catch (Exception e) {
-      throw new XmlException("couldn't write element '"+element.getTagName()+"' to string", e);
     }
-    
+    catch (Exception e) {
+      throw new XmlException("couldn't write element '" + element.getTagName() + "' to string", e);
+    }
+
     printWriter.close();
 
     return stringWriter.toString();
@@ -179,7 +180,7 @@
   public static String getContentText(Element element) {
     StringBuffer buffer = new StringBuffer();
     NodeList nodeList = element.getChildNodes();
-    for (int i=0; i<nodeList.getLength(); i++) {
+    for (int i = 0; i < nodeList.getLength(); i++) {
       Node node = nodeList.item(i);
       if (node instanceof CharacterData) {
         CharacterData characterData = (CharacterData) node;

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2009-05-07 13:21:23 UTC (rev 4759)
@@ -33,11 +33,8 @@
   <string name="resource.mail.templates" value="jbpm.mail.templates.xml" />
 
   <!-- class loading -->
-  <!--
-  <string name="jbpm.classLoader" value="jbpm" />
-  <string name="jbpm.customClassLoader.className" value="org.example.ClassLoader" /> 
-  <bean name="jbpm.processClassLoader" class="org.jbpm.instantiation.DefaultProcessClassLoaderFactory" singleton="true" />
-  -->
+  <string name="jbpm.class.loader" value="context" />
+  <bean name="process.class.loader.factory" class="org.jbpm.instantiation.SharedProcessClassLoaderFactory" singleton="true" />
 
   <!-- make sure the block size matches the length in ByteArray.hbm.xml -->
   <int    name="jbpm.byte.block.size" value="1024" singleton="true" />

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmConfigurationTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmConfigurationTest.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmConfigurationTest.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -21,36 +21,22 @@
  */
 package org.jbpm;
 
-import java.util.HashMap;
-
+import org.hibernate.SessionFactory;
 import org.jbpm.configuration.ConfigurationException;
 import org.jbpm.configuration.ObjectFactory;
 import org.jbpm.configuration.ObjectFactoryImpl;
 import org.jbpm.configuration.ObjectFactoryParser;
-import org.jbpm.persistence.db.DbPersistenceServiceFactory;
-import org.jbpm.svc.Services;
 import org.jbpm.util.XmlException;
 
 public class JbpmConfigurationTest extends AbstractJbpmTestCase {
 
-  protected void setUp() throws Exception 
-  {
+  protected void setUp() throws Exception {
     super.setUp();
-    JbpmConfiguration.instances = new HashMap();
+    JbpmConfiguration.clearJbpmConfigurationStack();
     JbpmConfiguration.defaultObjectFactory = null;
-    JbpmConfiguration.jbpmConfigurationsStacks =  new ThreadLocal();
-    JbpmContext.currentContextsStack = new ThreadLocal();
+    JbpmConfiguration.instances.clear();
   }
-  
-  protected void tearDown() throws Exception 
-  {
-    JbpmConfiguration.instances = new HashMap();
-    JbpmConfiguration.defaultObjectFactory = null;
-    JbpmConfiguration.jbpmConfigurationsStacks =  new ThreadLocal();
-    JbpmContext.currentContextsStack = new ThreadLocal();
-    super.tearDown();
-  }
-  
+
   public void testSingleton() {
     JbpmConfiguration.defaultObjectFactory = new ObjectFactoryImpl(null, null);
     JbpmConfiguration instance = JbpmConfiguration.getInstance();
@@ -61,35 +47,32 @@
   }
 
   public void testDefaultContextCreation() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='"+JbpmContext.DEFAULT_JBPM_CONTEXT_NAME+"' />" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='"
+        + JbpmContext.DEFAULT_JBPM_CONTEXT_NAME
+        + "' />"
+        + "</jbpm-configuration>");
     assertNotNull(jbpmConfiguration);
     assertNotNull(jbpmConfiguration.createJbpmContext());
   }
 
   public void testNonExistingContext() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration />"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration />");
     assertNotNull(jbpmConfiguration);
     try {
       jbpmConfiguration.createJbpmContext("non-existing-context");
       fail("expected exception");
-    } catch (ConfigurationException e) {
+    }
+    catch (ConfigurationException e) {
       //OK
     }
   }
 
   public void testParseXmlStringConfiguration() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a' />" +
-      "  <jbpm-context name='b' />" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a' />"
+        + "  <jbpm-context name='b' />"
+        + "</jbpm-configuration>");
     assertNotNull(jbpmConfiguration);
     JbpmContext a = jbpmConfiguration.createJbpmContext("a");
     assertNotNull(a);
@@ -99,11 +82,9 @@
   }
 
   public void testNonSingletonContextCreation() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a' />" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a' />"
+        + "</jbpm-configuration>");
     assertNotNull(jbpmConfiguration);
     JbpmContext a = jbpmConfiguration.createJbpmContext("a");
     assertNotNull(a);
@@ -116,7 +97,8 @@
     try {
       JbpmConfiguration.parseXmlString("<  problematic //   <</>  <x>M/L");
       fail("expected exception");
-    } catch (XmlException e) {
+    }
+    catch (XmlException e) {
       // OK
     }
   }
@@ -132,18 +114,16 @@
     // 'jbpm.cfg.xml' or the static method JbpmConfiguration.Configs.setDefaultObjectFactory
     // to specify the configuration information.
 
-    JbpmConfiguration.Configs.setDefaultObjectFactory(
-      ObjectFactoryParser.parseXmlString(
-        "<jbpm-configuration>" +
-        "  <string name='myproperty'>myvalue</string>" +
-        "</jbpm-configuration>"
-      )
-    );
+    JbpmConfiguration.Configs.setDefaultObjectFactory(ObjectFactoryParser.parseXmlString("<jbpm-configuration>"
+        + "  <string name='myproperty'>myvalue</string>"
+        + "</jbpm-configuration>"));
     assertEquals("myvalue", JbpmConfiguration.Configs.getString("myproperty"));
   }
 
   public static class CustomObjectFactory implements ObjectFactory {
+
     private static final long serialVersionUID = 1L;
+
     public Object createObject(String name) {
       Object o = null;
       if ("myproperty".equals(name)) {
@@ -151,48 +131,42 @@
       }
       return o;
     }
+
     public boolean hasObject(String name) {
       return "myproperty".equals(name);
     }
   }
 
   public void testDomainModelConfigsWithCustomObjectFactory() {
-    JbpmConfiguration.Configs.setDefaultObjectFactory(
-      new CustomObjectFactory()
-    );
+    JbpmConfiguration.Configs.setDefaultObjectFactory(new CustomObjectFactory());
     assertEquals("mycustomfactoriedvalue", JbpmConfiguration.Configs.getString("myproperty"));
   }
 
   public void testDomainModelConfigsWithJbpmContext() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='default.jbpm.context' />" +
-      "  <string name='myproperty'>myvalueinacontext</string>" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='default.jbpm.context' />"
+        + "  <string name='myproperty'>myvalueinacontext</string>"
+        + "</jbpm-configuration>");
 
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
     try {
       assertEquals("myvalueinacontext", JbpmConfiguration.Configs.getString("myproperty"));
-    } finally {
+    }
+    finally {
       jbpmContext.close();
     }
   }
 
   public void testDomainModelConfigsWithNestedJbpmContext() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='default.jbpm.context' />" +
-      "  <string name='myproperty'>myvalueinacontext</string>" +
-      "</jbpm-configuration>"
-    );
-    JbpmConfiguration nestedJbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='default.jbpm.context' />" +
-      "  <string name='myproperty'>myvalueinanestedcontext</string>" +
-      "</jbpm-configuration>"
-    );          
-    
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='default.jbpm.context' />"
+        + "  <string name='myproperty'>myvalueinacontext</string>"
+        + "</jbpm-configuration>");
+    JbpmConfiguration nestedJbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='default.jbpm.context' />"
+        + "  <string name='myproperty'>myvalueinanestedcontext</string>"
+        + "</jbpm-configuration>");
+
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
     try {
       assertEquals("myvalueinacontext", JbpmConfiguration.Configs.getString("myproperty"));
@@ -200,12 +174,14 @@
       JbpmContext nestedJbpmContext = nestedJbpmConfiguration.createJbpmContext();
       try {
         assertEquals("myvalueinanestedcontext", JbpmConfiguration.Configs.getString("myproperty"));
-      } finally {
+      }
+      finally {
         nestedJbpmContext.close();
       }
-      
+
       assertEquals("myvalueinacontext", JbpmConfiguration.Configs.getString("myproperty"));
-    } finally {
+    }
+    finally {
       jbpmContext.close();
     }
   }
@@ -213,15 +189,15 @@
   public void testJbpmConfigurationClose() {
     JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+    SessionFactory sessionFactory;
     try {
-      jbpmContext.getSession();
-    } finally {
+      sessionFactory = jbpmContext.getSessionFactory();
+    }
+    finally {
       jbpmContext.close();
     }
-    
     jbpmConfiguration.close();
-    
-    DbPersistenceServiceFactory dbPersistenceServiceFactory = (DbPersistenceServiceFactory) jbpmConfiguration.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
-    assertTrue(dbPersistenceServiceFactory.getSessionFactory().isClosed());
+
+    assertTrue("expected " + sessionFactory + " to be closed", sessionFactory.isClosed());
   }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmContextTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmContextTest.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/JbpmContextTest.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -21,8 +21,6 @@
  */
 package org.jbpm;
 
-import java.util.HashMap;
-
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.logging.LoggingService;
 import org.jbpm.logging.log.MessageLog;
@@ -33,29 +31,17 @@
 import org.jbpm.svc.save.SaveOperation;
 
 public class JbpmContextTest extends AbstractJbpmTestCase {
-  
-  protected void setUp() throws Exception
-  {
+
+  protected void setUp() throws Exception {
     super.setUp();
-    JbpmConfiguration.instances = new HashMap();
+    JbpmConfiguration.instances.clear();
     JbpmConfiguration.defaultObjectFactory = null;
-    JbpmContext.currentContextsStack = new ThreadLocal();
   }
 
-  protected void tearDown() throws Exception
-  {
-    JbpmConfiguration.instances = new HashMap();
-    JbpmConfiguration.defaultObjectFactory = null;
-    JbpmContext.currentContextsStack = new ThreadLocal();
-    super.tearDown();
-  }
-  
   public void testServices() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a' />" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a' />"
+        + "</jbpm-configuration>");
     assertNotNull(jbpmConfiguration);
     Services s = jbpmConfiguration.createJbpmContext("a").getServices();
     assertNotNull(s);
@@ -65,11 +51,9 @@
   }
 
   public void testJbpmContext() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a' />" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a' />"
+        + "</jbpm-configuration>");
     JbpmContext one = jbpmConfiguration.createJbpmContext("a");
     assertNotNull(one);
     JbpmContext two = jbpmConfiguration.createJbpmContext("a");
@@ -78,58 +62,57 @@
   }
 
   public static class TestServiceFactory implements ServiceFactory {
+
     private static final long serialVersionUID = 1L;
+
     public Service openService() {
       return new TestService();
     }
+
     public void close() {
     }
   }
 
   public static class TestService implements Service {
+
     private static final long serialVersionUID = 1L;
+
     public void close() {
     }
   }
 
   public void testCustomService() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a'>" +
-      "    <service name='test' factory='org.jbpm.JbpmContextTest$TestServiceFactory' />" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a'>"
+        + "    <service name='test' factory='org.jbpm.JbpmContextTest$TestServiceFactory' />"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
     Object service = jbpmConfiguration.createJbpmContext("a").getServices().getService("test");
     assertNotNull(service);
     assertEquals(TestService.class, service.getClass());
   }
-  
+
   public void testServiceInFactoryElement() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a'>" +
-      "    <service name='test'>" +
-      "      <factory>" +
-      "        <bean class='org.jbpm.JbpmContextTest$TestServiceFactory' />" +
-      "      </factory>" +
-      "    </service>" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a'>"
+        + "    <service name='test'>"
+        + "      <factory>"
+        + "        <bean class='org.jbpm.JbpmContextTest$TestServiceFactory' />"
+        + "      </factory>"
+        + "    </service>"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
     Object service = jbpmConfiguration.createJbpmContext("a").getServices().getService("test");
     assertNotNull(service);
     assertEquals(TestService.class, service.getClass());
   }
-  
+
   public void testServiceCaching() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a'>" +
-      "    <service name='test' factory='org.jbpm.JbpmContextTest$TestServiceFactory' />" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    );
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a'>"
+        + "    <service name='test' factory='org.jbpm.JbpmContextTest$TestServiceFactory' />"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext("a");
     TestService serviceOne = (TestService) jbpmContext.getServices().getService("test");
     assertNotNull(serviceOne);
@@ -139,22 +122,28 @@
     jbpmContext = jbpmConfiguration.createJbpmContext("a");
     assertNotSame(serviceOne, jbpmContext.getServices().getService("test"));
   }
-  
+
   public static class CustomLoggingServiceFactory implements ServiceFactory {
+
     private static final long serialVersionUID = 1L;
+
     public Service openService() {
       return new CustomLoggingService();
     }
+
     public void close() {
     }
   }
 
   public static class CustomLoggingService implements LoggingService {
+
     private static final long serialVersionUID = 1L;
     ProcessLog processLog;
     int invocationCount = 0;
+
     public void close() {
     }
+
     public void log(ProcessLog processLog) {
       this.processLog = processLog;
       this.invocationCount++;
@@ -162,17 +151,15 @@
   }
 
   public void testCustomLoggingService() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='a'>" +
-      "    <service name='logging' factory='org.jbpm.JbpmContextTest$CustomLoggingServiceFactory' />" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    );
-    
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='a'>"
+        + "    <service name='logging' factory='org.jbpm.JbpmContextTest$CustomLoggingServiceFactory' />"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
+
     CustomLoggingService customLoggingService = null;
     MessageLog messageLog = null;
-    
+
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext("a");
     try {
       customLoggingService = (CustomLoggingService) jbpmContext.getServices().getLoggingService();
@@ -181,70 +168,70 @@
       processInstance.getLoggingInstance().addLog(messageLog);
       jbpmContext.save(processInstance);
 
-    } finally {
+    }
+    finally {
       jbpmContext.close();
     }
     assertEquals(messageLog, customLoggingService.processLog);
     assertEquals(1, customLoggingService.invocationCount);
   }
-  
-  
+
   public static class TestSaveOperation implements SaveOperation {
+
     static int invocationCount = 0;
     private static final long serialVersionUID = 1L;
+
     public void save(ProcessInstance processInstance, JbpmContext jbpmContext) {
       invocationCount++;
     }
   }
 
   public void testSaveOperation() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='default.jbpm.context'>" +
-      "    <save-operations>" +
-      "      <save-operation class='org.jbpm.JbpmContextTest$TestSaveOperation' />" +
-      "    </save-operations>" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    ); 
-    
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='default.jbpm.context'>"
+        + "    <save-operations>"
+        + "      <save-operation class='org.jbpm.JbpmContextTest$TestSaveOperation' />"
+        + "    </save-operations>"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
+
     TestSaveOperation.invocationCount = 0;
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-    
+
     try {
-      
+
       assertEquals(0, TestSaveOperation.invocationCount);
       jbpmContext.save(new ProcessInstance());
       assertEquals(1, TestSaveOperation.invocationCount);
-      
-    } finally {
+
+    }
+    finally {
       jbpmContext.close();
     }
   }
 
   public void testSaveOperationInBeanElement() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-      "<jbpm-configuration>" +
-      "  <jbpm-context name='default.jbpm.context'>" +
-      "    <save-operations>" +
-      "      <save-operation>" +
-      "        <bean class='org.jbpm.JbpmContextTest$TestSaveOperation' />" +
-      "      </save-operation>" +
-      "    </save-operations>" +
-      "  </jbpm-context>" +
-      "</jbpm-configuration>"
-    ); 
-    
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <jbpm-context name='default.jbpm.context'>"
+        + "    <save-operations>"
+        + "      <save-operation>"
+        + "        <bean class='org.jbpm.JbpmContextTest$TestSaveOperation' />"
+        + "      </save-operation>"
+        + "    </save-operations>"
+        + "  </jbpm-context>"
+        + "</jbpm-configuration>");
+
     TestSaveOperation.invocationCount = 0;
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-    
+
     try {
-      
+
       assertEquals(0, TestSaveOperation.invocationCount);
       jbpmContext.save(new ProcessInstance());
       assertEquals(1, TestSaveOperation.invocationCount);
-      
-    } finally {
+
+    }
+    finally {
       jbpmContext.close();
     }
   }

Copied: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassLoadersTest.java (from rev 4689, jbpm3/trunk/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassLoadersTest.java)
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassLoadersTest.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassLoadersTest.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -0,0 +1,143 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.instantiation;
+
+import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
+import org.jbpm.JbpmException;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.util.ClassLoaderUtil;
+
+/**
+ * {@link ProcessClassLoaderFactory} and class loader can be configured via
+ * {@link JbpmConfiguration} / jbpm.cfg.xml. Test if that works. Introduced with
+ * https://jira.jboss.org/jira/browse/JBPM-1148
+ * 
+ * @author bernd.ruecker at camunda.com
+ */
+public class ConfigurableClassLoadersTest extends AbstractJbpmTestCase {
+
+  private ProcessDefinition processDefinition = new ProcessDefinition();
+
+  public void testDefaultProcessClassLoaderFactory() {
+    ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(processDefinition);
+    assertSame(ProcessClassLoader.class, processClassLoader.getClass());
+  }
+
+  public void testCustomProcessClassLoaderFactory() {
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <bean name='process.class.loader.factory' class='"
+        + CustomProcessClassLoaderFactory.class.getName()
+        + "' singleton='true' />"
+        + "</jbpm-configuration>");
+    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+
+    ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(processDefinition);
+    assertSame(CustomClassLoader.class, processClassLoader.getClass());
+
+    jbpmContext.close();
+    jbpmConfiguration.close();
+  }
+
+  public static class CustomProcessClassLoaderFactory implements ProcessClassLoaderFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
+      return new CustomClassLoader();
+    }
+  }
+
+  public void testDefaultClassLoader() {
+    ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
+    assertSame(ClassLoaderUtil.class.getClassLoader(), classLoader);
+  }
+
+  public void testJbpmClassLoader() {
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <string name='jbpm.class.loader' value='jbpm' /> "
+        + "</jbpm-configuration>");
+    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+
+    ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
+    assertSame(ClassLoaderUtil.class.getClassLoader(), classLoader);
+
+    jbpmContext.close();
+    jbpmConfiguration.close();
+  }
+
+  public void testContextClassLoader() {
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <string name='jbpm.class.loader' value='context' /> "
+        + "</jbpm-configuration>");
+    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+
+    ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
+    assertSame(Thread.currentThread().getContextClassLoader(), classLoader);
+
+    jbpmContext.close();
+    jbpmConfiguration.close();
+  }
+
+  public void testNonExistentClassLoader() {
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <string name='jbpm.class.loader' value='absent' /> "
+        + "</jbpm-configuration>");
+    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+
+    try {
+      ClassLoaderUtil.getClassLoader();
+      fail("expected " + JbpmException.class.getName());
+    }
+    catch (JbpmException ex) {
+      // fine, exception was expected
+    }
+
+    jbpmContext.close();
+    jbpmConfiguration.close();
+  }
+
+  public void testCustomClassLoader() {
+    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
+        + "  <string name='jbpm.class.loader' value='custom.class.loader' />"
+        + "  <bean name='custom.class.loader' class='"
+        + CustomClassLoader.class.getName()
+        + "' /> "
+        + "</jbpm-configuration>");
+    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+
+    ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
+    assertSame(CustomClassLoader.class, classLoader.getClass());
+
+    jbpmContext.close();
+    jbpmConfiguration.close();
+  }
+
+  public static class CustomClassLoader extends ClassLoader {
+
+    public CustomClassLoader() {
+      super(Thread.currentThread().getContextClassLoader());
+    }
+  }
+
+}

Deleted: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -1,136 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.instantiation;
-
-import org.jbpm.AbstractJbpmTestCase;
-import org.jbpm.JbpmConfiguration;
-import org.jbpm.JbpmConfigurationTestHelper;
-import org.jbpm.JbpmContext;
-import org.jbpm.graph.def.ProcessDefinition;
-
-/**
- * {@link ProcessClassLoaderFactory} and class loader can be configured 
- * via {@link JbpmConfiguration} / jbpm.cfg.xml. Test if that works.
- * 
- * Introduced with https://jira.jboss.org/jira/browse/JBPM-1148
- * 
- * @author bernd.ruecker at camunda.com
- */
-public class ConfigurableClassloadersTest extends AbstractJbpmTestCase {
-  
-  public void testDefaultBehavior() {
-    JbpmConfiguration.getInstance();
-    ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(null);
-    
-    assertNotNull(processClassLoader);
-    assertEquals(ProcessClassLoader.class, processClassLoader.getClass());
-  }
-
-  public static class MyClassLoader extends ClassLoader {
-    public MyClassLoader() {      
-    }
-    public MyClassLoader(ClassLoader parent) {
-      super(parent);
-    }    
-  }
-  
-  public static class TestProcessClassLoaderFactory implements ProcessClassLoaderFactory {
-    public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
-      return new MyClassLoader(Thread.currentThread().getContextClassLoader());
-    }   
-  }
-
-  public void testOwnProcessFactory() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-            "<jbpm-configuration>" +
-            "  <jbpm-context>" +
-            "  </jbpm-context>" +
-            "  <string name='jbpm.classLoader' value='jbpm' /> " +
-            "  <bean name='jbpm.processClassLoader' class='org.jbpm.instantiation.ConfigurableClassloadersTest$TestProcessClassLoaderFactory' singelton='true' />" +
-            "</jbpm-configuration>"
-    );
-    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-    
-    ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(null);    
-    assertNotNull(processClassLoader);
-    assertEquals(MyClassLoader.class, processClassLoader.getClass());
-    
-    jbpmContext.close();
-    jbpmConfiguration.close();
-  }
-  
-  public void testContextClassloaderFactory() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-            "<jbpm-configuration>" +
-            "  <jbpm-context>" +
-            "  </jbpm-context>" +
-            "  <string name='jbpm.classLoader' value='context' /> " +
-            "</jbpm-configuration>"
-    );
-    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-
-    assertNotNull(jbpmContext);
-    
-    jbpmContext.close();
-    jbpmConfiguration.close();
-  }
-
-  public void testCustomClassloaderFactoryWithoutClassname() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-            "<jbpm-configuration>" +
-            "  <jbpm-context>" +
-            "  </jbpm-context>" +
-            "  <string name='jbpm.classLoader' value='custom' /> " +
-            "</jbpm-configuration>"
-    );
-    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-    try {
-      ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(null);    
-      fail("we should get an exception because custom class loader class not specified");
-    }
-    catch (Exception ex) {}
-    
-    jbpmContext.close();
-    jbpmConfiguration.close();
-  }
-  
-  public void testCustomClassloaderFactory() {
-    JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(
-            "<jbpm-configuration>" +
-            "  <jbpm-context>" +
-            "  </jbpm-context>" +
-            "  <string name='jbpm.classLoader' value='custom' /> " +
-            "  <string name='jbpm.customClassLoader.className' value='org.jbpm.instantiation.ConfigurableClassloadersTest$MyClassLoader' />" +
-            "</jbpm-configuration>"
-    );
-    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-    
-    ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(null);    
-    assertNotNull(processClassLoader);
-    // not configured, must be default
-    assertEquals(ProcessClassLoader.class, processClassLoader.getClass());
-    
-    jbpmContext.close();
-    jbpmConfiguration.close();
-  }
-  
-}

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java	2009-05-07 10:14:21 UTC (rev 4758)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java	2009-05-07 13:21:23 UTC (rev 4759)
@@ -7,16 +7,15 @@
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.graph.exe.ExecutionContext;
 import org.jbpm.graph.exe.ProcessInstance;
-import org.jbpm.instantiation.ConfigurableClassloadersTest;
+import org.jbpm.instantiation.ConfigurableClassLoadersTest;
 import org.jbpm.instantiation.ProcessClassLoader;
 import org.jbpm.util.ClassLoaderUtil;
 
 /**
  * Test case for ProcessClassLoader hierarchy and setting the ContextClassLoader correctly. Relates
- * to {@link ConfigurableClassloadersTest}.
+ * to {@link ConfigurableClassLoadersTest}.
  * 
- * @author Tom Baeyens
- * @author bernd.ruecker at camunda.com
+ * @author Tom Baeyens, bernd.ruecker at camunda.com
  */
 public class ProcessClassLoaderTest extends AbstractJbpmTestCase {
 
@@ -26,14 +25,17 @@
       super(parent);
     }
 
+    protected synchronized Class loadClass(String name, boolean resolve)
+        throws ClassNotFoundException {
+      return super.loadClass(name, resolve);
+    }
+
+    public Class loadClass(String name) throws ClassNotFoundException {
+      return super.loadClass(name);
+    }
+
     protected Class findClass(String name) throws ClassNotFoundException {
-      if ("TestContextClassLoader-knows-where-to-find-ContextLoadedAction".equals(name)) {
-        return getParent().loadClass(ContextLoadedAction.class.getName());
-      }
-      else if ("TestContextClassLoader-knows-where-to-find-ContextLoadedExceptionAction".equals(name)) {
-        return getParent().loadClass(ContextLoadedExceptionAction.class.getName());
-      }
-      return null;
+      return super.findClass(name);
     }
   }
 
@@ -61,7 +63,7 @@
     }
   }
 
-  /**
+  /*
    * DOES NOT configure usage of the context classloader. So this tests the default (backwards
    * compatible) behaviour. so the classloading hierarchy of DefaultLoadedAction should be
    * ProcessClassloader -> jbpm-lib classloader
@@ -70,7 +72,9 @@
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<process-definition>"
         + "  <start-state name='start'>"
         + "    <transition to='state'>"
-        + "      <action class='org.jbpm.jpdl.par.ProcessClassLoaderTest$DefaultLoadedAction' />"
+        + "      <action class='"
+        + DefaultLoadedAction.class.getName()
+        + "' />"
         + "    </transition>"
         + "  </start-state>"
         + "  <state name='state'>"
@@ -102,12 +106,13 @@
     }
   }
 
-  /**
+  /*
    * configures usage of the context classloader so the classloading hierarchy of
    * ContextLoadedAction should be ProcessClassloader -> TestContextClassLoader ->
    * Thread.currentContextClassLoader
    */
   public void testContextClassLoader() {
+
     JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
         + "  <string name='jbpm.classLoader' value='context' />"
         + "</jbpm-configuration>");
@@ -121,7 +126,9 @@
       ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<process-definition>"
           + "  <start-state name='start'>"
           + "    <transition to='state'>"
-          + "      <action class='TestContextClassLoader-knows-where-to-find-ContextLoadedAction' />"
+          + "      <action class='"
+          + ContextLoadedAction.class.getName()
+          + "' />"
           + "    </transition>"
           + "  </start-state>"
           + "  <state name='state'>"
@@ -135,6 +142,7 @@
 
       assertEquals(1, contextLoadedActionInvocations);
       assertSame(testContextClassLoader, Thread.currentThread().getContextClassLoader());
+
     }
     finally {
       Thread.currentThread().setContextClassLoader(originalClassLoader);
@@ -142,7 +150,7 @@
     }
   }
 
-  /**
+  /*
    * a third test should set the testcontextClassLoader in the test and then let the action throw an
    * exception. Then it should be verified that the original classloader is still restored
    * correctly. Easiest is to start from a copy of the testContextClassLoader
@@ -179,7 +187,9 @@
       ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<process-definition>"
           + "  <start-state name='start'>"
           + "    <transition to='state'>"
-          + "      <action class='TestContextClassLoader-knows-where-to-find-ContextLoadedExceptionAction' />"
+          + "      <action class='"
+          + ContextLoadedExceptionAction.class.getName()
+          + "' />"
           + "    </transition>"
           + "  </start-state>"
           + "  <state name='state'>"
@@ -190,11 +200,13 @@
       // create the process instance
       ProcessInstance processInstance = new ProcessInstance(processDefinition);
       processInstance.signal();
+
     }
     catch (Exception ex) {
       assertEquals(1, contextLoadedActionInvocations);
       assertEquals("simulate exception", ex.getMessage());
       assertSame(testContextClassLoader, Thread.currentThread().getContextClassLoader());
+
     }
     finally {
       Thread.currentThread().setContextClassLoader(originalClassLoader);




More information about the jbpm-commits mailing list