[jbpm-commits] JBoss JBPM SVN: r2498 - in jbpm3/trunk/modules/core/src: main/java/org/jbpm/configuration and 10 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Oct 7 10:02:31 EDT 2008


Author: camunda
Date: 2008-10-07 10:02:30 -0400 (Tue, 07 Oct 2008)
New Revision: 2498

Added:
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java
   jbpm3/trunk/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java
Modified:
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryParser.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/context/exe/converter/SerializableToByteArrayConverter.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/Action.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/Delegation.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/mail/Mail.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/def/TaskController.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/XmlUtil.java
   jbpm3/trunk/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
Log:
JBPM-1148
Made classloader configurable in jbpm.cfg.xml
Introduced getJbpmConfigurationStream as special method to load the "jbpm.cfg.xml" (NOT with the configured classloader, otherwise we get an endless loop)
Introduced ProcessClassLoaderFactory, configurable in jbpm.cfg.xml
(see https://jira.jboss.org/jira/browse/JBPM-1148)

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -36,6 +36,10 @@
 import org.jbpm.configuration.ObjectFactoryParser;
 import org.jbpm.configuration.ObjectInfo;
 import org.jbpm.configuration.ValueInfo;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.instantiation.DefaultProcessClassLoaderFactory;
+import org.jbpm.instantiation.ProcessClassLoader;
+import org.jbpm.instantiation.ProcessClassLoaderFactory;
 import org.jbpm.job.executor.JobExecutor;
 import org.jbpm.persistence.db.DbPersistenceServiceFactory;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
@@ -292,7 +296,7 @@
           try
           {
             log.info("using jbpm configuration resource '" + resource + "'");
-            InputStream jbpmCfgXmlStream = ClassLoaderUtil.getStream(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
@@ -412,7 +416,7 @@
     log.debug("creating jbpm configuration from resource '" + resource + "'");
     if (resource != null)
     {
-      inputStream = ClassLoaderUtil.getStream(resource);
+      inputStream = ClassLoaderUtil.getJbpmConfigurationStream(resource);
     }
     ObjectFactory objectFactory = parseObjectFactory(inputStream);
     return createJbpmConfiguration(objectFactory);
@@ -450,7 +454,19 @@
     }
     return serviceFactory;
   }
+  
+  public static ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
+    ProcessClassLoaderFactory factory = null;
+    if (Configs.hasObject("jbpm.processClassLoader")) {
+     factory = (ProcessClassLoaderFactory) Configs.getObject("jbpm.processClassLoader");
+    }
+    else {
+      factory = new DefaultProcessClassLoaderFactory();
+    }
+    return factory.getProcessClassLoader(processDefinition);
+  }  
 
+
   /**
    * gives the jbpm domain model access to configuration information via the current JbpmContext.
    */

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryImpl.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -37,7 +37,7 @@
   
   private static final long serialVersionUID = 1L;
 
-  ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
+  ClassLoader classLoader = null; // lazy load it later! See below..
   List objectInfos = null;
   Map namedObjectInfos = null;
   Map singletons = new HashMap();
@@ -158,6 +158,12 @@
   }
 
   Class loadClass(String className) {
+    // "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.
+    if (classLoader==null) {
+      classLoader = ClassLoaderUtil.getClassLoader();
+    }    
     try {
       return classLoader.loadClass(className);
     } catch (ClassNotFoundException e) {

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryParser.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryParser.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/configuration/ObjectFactoryParser.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -84,7 +84,7 @@
   }
 
   public static ObjectFactoryImpl parseResource(String resource) {
-    Element rootElement = XmlUtil.parseXmlResource(resource).getDocumentElement();
+    Element rootElement = XmlUtil.parseXmlResource(resource, true).getDocumentElement();
     return createObjectFactory(rootElement);
   }
   
@@ -101,7 +101,7 @@
   }
 
   public void parseElementsFromResource(String resource, ObjectFactoryImpl objectFactoryImpl) {
-    Element rootElement = XmlUtil.parseXmlResource(resource).getDocumentElement();
+    Element rootElement = XmlUtil.parseXmlResource(resource, true).getDocumentElement();
     parseElements(rootElement, objectFactoryImpl);
   }
 

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/context/exe/converter/SerializableToByteArrayConverter.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/context/exe/converter/SerializableToByteArrayConverter.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/context/exe/converter/SerializableToByteArrayConverter.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -29,6 +29,7 @@
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmException;
 import org.jbpm.bytes.ByteArray;
 import org.jbpm.context.exe.Converter;
@@ -80,7 +81,7 @@
 		ByteArray byteArray = (ByteArray) o;
 		InputStream memoryStream = new ByteArrayInputStream(byteArray.getBytes());
 		try {
-		  ObjectInputStream objectStream = new CustomLoaderObjectInputStream(memoryStream, ClassLoaderUtil.getProcessClassLoader(processDefinition));
+		  ObjectInputStream objectStream = new CustomLoaderObjectInputStream(memoryStream, JbpmConfiguration.getProcessClassLoader(processDefinition));
 			return objectStream.readObject();
 		}
 		catch(IOException ex) {

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/Action.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/Action.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/Action.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -25,6 +25,7 @@
 import java.util.Map;
 
 import org.dom4j.Element;
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.graph.exe.ExecutionContext;
 import org.jbpm.instantiation.Delegation;
 import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
@@ -115,7 +116,7 @@
     ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
     try {
       // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448) 
-      Thread.currentThread().setContextClassLoader(ClassLoaderUtil.getProcessClassLoader(processDefinition));
+      Thread.currentThread().setContextClassLoader(JbpmConfiguration.getProcessClassLoader(processDefinition));
 
       if (referencedAction != null) {
         referencedAction.execute(executionContext);

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -27,6 +27,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.dom4j.Element;
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmException;
 import org.jbpm.graph.def.Node;
 import org.jbpm.graph.def.Transition;
@@ -76,7 +77,7 @@
     ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
     try {
       // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448) 
-      Thread.currentThread().setContextClassLoader(ClassLoaderUtil.getProcessClassLoader(processDefinition));
+      Thread.currentThread().setContextClassLoader(JbpmConfiguration.getProcessClassLoader(processDefinition));
 
       try {
         if (decisionDelegation != null) {

Added: jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java	                        (rev 0)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/DefaultProcessClassLoaderFactory.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -0,0 +1,21 @@
+package org.jbpm.instantiation;
+
+import java.io.Serializable;
+
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.util.ClassLoaderUtil;
+
+/**
+ * Default implementation of {@link ProcessClassLoaderFactory}.
+ * 
+ * @author bernd.ruecker at camunda.com
+ */
+public class DefaultProcessClassLoaderFactory implements ProcessClassLoaderFactory, Serializable {
+  
+  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/trunk/modules/core/src/main/java/org/jbpm/instantiation/Delegation.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/Delegation.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/Delegation.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -37,6 +37,7 @@
 import org.dom4j.Node;
 import org.dom4j.io.OutputFormat;
 import org.dom4j.io.XMLWriter;
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmException;
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.jpdl.xml.JpdlXmlReader;
@@ -132,7 +133,7 @@
     Object newInstance = null; 
 
     // find the classloader to use
-    ClassLoader classLoader = ClassLoaderUtil.getProcessClassLoader(processDefinition);
+    ClassLoader classLoader = JbpmConfiguration.getProcessClassLoader(processDefinition);
     
     // load the class that needs to be instantiated
     Class clazz = null;

Added: jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java	                        (rev 0)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/instantiation/ProcessClassLoaderFactory.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -0,0 +1,21 @@
+package org.jbpm.instantiation;
+
+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.
+ * 
+ * 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 ClassLoader getProcessClassLoader(ProcessDefinition processDefinition);
+  
+}
\ No newline at end of file

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/mail/Mail.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/mail/Mail.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/mail/Mail.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -273,7 +273,7 @@
     if (templates==null) {
       templates = new HashMap();
       String mailTemplatesResource = JbpmConfiguration.Configs.getString("resource.mail.templates");
-      org.w3c.dom.Element mailTemplatesElement = XmlUtil.parseXmlResource(mailTemplatesResource).getDocumentElement();
+      org.w3c.dom.Element mailTemplatesElement = XmlUtil.parseXmlResource(mailTemplatesResource, false).getDocumentElement();
       List mailTemplateElements = XmlUtil.elements(mailTemplatesElement, "mail-template");
       Iterator iter = mailTemplateElements.iterator();
       while (iter.hasNext()) {

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/def/TaskController.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/def/TaskController.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/def/TaskController.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -27,11 +27,13 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.context.def.VariableAccess;
 import org.jbpm.context.exe.ContextInstance;
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.graph.exe.Token;
 import org.jbpm.instantiation.Delegation;
+import org.jbpm.instantiation.ProcessClassLoaderFactory;
 import org.jbpm.instantiation.UserCodeInterceptorConfig;
 import org.jbpm.taskmgmt.exe.TaskInstance;
 import org.jbpm.util.ClassLoaderUtil;
@@ -73,8 +75,8 @@
   public void initializeVariables(TaskInstance taskInstance) {
     ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
     try {
-      // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448) 
-      Thread.currentThread().setContextClassLoader(ClassLoaderUtil.getProcessClassLoader(taskInstance.getTask().getProcessDefinition()));
+      // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448)      
+      Thread.currentThread().setContextClassLoader(JbpmConfiguration.getProcessClassLoader(taskInstance.getTask().getProcessDefinition()));
 
       if (taskControllerDelegation != null) {
         TaskControllerHandler taskControllerHandler = (TaskControllerHandler) taskControllerDelegation.instantiate();
@@ -122,7 +124,7 @@
     ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
     try {
       // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448) 
-      Thread.currentThread().setContextClassLoader(ClassLoaderUtil.getProcessClassLoader(taskInstance.getTask().getProcessDefinition()));
+      Thread.currentThread().setContextClassLoader(JbpmConfiguration.getProcessClassLoader(taskInstance.getTask().getProcessDefinition()));
 
       if (taskControllerDelegation != null) {
         TaskControllerHandler taskControllerHandler = (TaskControllerHandler) taskControllerDelegation.instantiate();

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -268,7 +268,7 @@
     ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
     try {
       // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448) 
-      Thread.currentThread().setContextClassLoader(ClassLoaderUtil.getProcessClassLoader(executionContext.getProcessDefinition()));
+      Thread.currentThread().setContextClassLoader(JbpmConfiguration.getProcessClassLoader(executionContext.getProcessDefinition()));
 
       // instantiate the assignment handler
       AssignmentHandler assignmentHandler = (AssignmentHandler) assignmentDelegation.instantiate();

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -25,9 +25,11 @@
 import java.io.InputStream;
 import java.util.Properties;
 
+import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmException;
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.instantiation.ProcessClassLoader;
+import org.jbpm.instantiation.ProcessClassLoaderFactory;
 
 /**
  * provides centralized classloader lookup. 
@@ -45,56 +47,90 @@
       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 ClassLoader getClassLoader() {
-    // if this is made configurable, make sure it's done with the
-    // jvm system properties
-    // System.getProperty("jbpm.classloader")
-    //  - 'jbpm'
-    //  - 'context'
-    // 
-    // or something like Thread.currentThread().getContextClassLoader();
-    return ClassLoaderUtil.class.getClassLoader();
+    if (JbpmConfiguration.Configs.hasObject("jbpm.classLoader")) {
+      String jbpmClassloader = JbpmConfiguration.Configs.getString("jbpm.classLoader");
+
+      if (jbpmClassloader.equals("jbpm")) {
+        return ClassLoaderUtil.class.getClassLoader();
+      } else if (jbpmClassloader.equals("context")) {
+        return Thread.currentThread().getContextClassLoader();
+      } else if (jbpmClassloader.equals("custom")) {
+        String jbpmClassloaderClassname = JbpmConfiguration.Configs.getString("jbpm.customClassLoader.className");
+        try {
+          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);
+        }
+      } else {
+        throw new JbpmException("'jbpm.classloader' property set to '" + jbpmClassloader + "' but only the values 'jbpm'/'context'/'custom' are supported!");
+      }
+    } else {
+      // default behavior like before https://jira.jboss.org/jira/browse/JBPM-1148    
+      return ClassLoaderUtil.class.getClassLoader();
+    }
   }
   
   public static InputStream getStream(String resource) {
-    return getClassLoader().getResourceAsStream(resource);
+    return  getClassLoader().getResourceAsStream(resource);
   }
-
-  public static Properties getProperties(String resource) {
-    Properties properties = new Properties();
-    try {
-      properties.load(getStream(resource));
-    } catch (IOException e) {
-      throw new JbpmException("couldn't load properties file '"+resource+"'", e);
-    }
-    return properties;
-  }
-
+  
   /**
-   * searches the given resource, first on the root of the classpath and if not 
-   * not found there, in the given directory.
-  public static InputStream getStream(String resource, String directory) {
-    InputStream is = getClassLoader().getResourceAsStream(resource);
-    if (is==null) {
-      is = getClassLoader().getResourceAsStream(directory+"/"+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. 
+   */
+  public static InputStream getJbpmConfigurationStream(String resource) {
+    InputStream jbpmCfgStream = ClassLoaderUtil.class.getClassLoader().getResourceAsStream(resource);
+    if (jbpmCfgStream==null) {
+      jbpmCfgStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
     }
-    return is;
+    return jbpmCfgStream;
   }
-
-  public static Properties getProperties(String resource, String directory) {
+  
+  public static Properties getProperties(String resource) {
     Properties properties = new Properties();
     try {
-      properties.load(getStream(resource, directory));
+      properties.load(getStream(resource));
     } catch (IOException e) {
       throw new JbpmException("couldn't load properties file '"+resource+"'", e);
     }
     return properties;
   }
-  */
-
-  public static ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
-    return new ProcessClassLoader(ClassLoaderUtil.class.getClassLoader(), processDefinition);
-  }
-
 }

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/XmlUtil.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/XmlUtil.java	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/util/XmlUtil.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -58,8 +58,19 @@
     return parseXmlInputSource(new InputSource(bais));
   }
 
-  public static Document parseXmlResource(String resource) {
-    InputStream inputStream = ClassLoaderUtil.getStream(resource);
+  /**
+   * @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) {    
+    // 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);
+    else
+      inputStream = ClassLoaderUtil.getStream(resource);
+    
     if (inputStream == null)
     	throw new IllegalArgumentException("Cannot load resource: " + resource);
     InputSource inputSource = new InputSource(inputStream);

Modified: jbpm3/trunk/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
===================================================================
--- jbpm3/trunk/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2008-10-07 11:37:40 UTC (rev 2497)
+++ jbpm3/trunk/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2008-10-07 14:02:30 UTC (rev 2498)
@@ -30,6 +30,11 @@
   <string name="resource.varmapping" value="org/jbpm/context/exe/jbpm.varmapping.xml" />
   <string name="resource.mail.templates" value="jbpm.mail.templates.xml" />
 
+  <!-- class loading -->
+  <!-- <string name="jbpm.classLoader" value="jbpm" />
+       <string name="jbpm.customClassLoader.className" value="com...MyClassLoaderUtil" /> 
+       <bean name="jbpm.processClassLoader" class="org.jbpm.instantiation.DefaultProcessClassLoaderFactory" singelton="true" />-->
+
   <!-- make sure the block size matches the length in ByteArray.hbm.xml -->
   <int    name="jbpm.byte.block.size" value="1024" singleton="true" />
   <bean   name="jbpm.task.instance.factory" class="org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl" singleton="true" />

Added: jbpm3/trunk/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java
===================================================================
--- jbpm3/trunk/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java	                        (rev 0)
+++ jbpm3/trunk/modules/core/src/test/java/org/jbpm/instantiation/ConfigurableClassloadersTest.java	2008-10-07 14:02:30 UTC (rev 2498)
@@ -0,0 +1,133 @@
+/*
+ * 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.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.ProcessClassLoaderFactoryTest$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) {}
+    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.ProcessClassLoaderFactoryTest$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();
+  }
+  
+}




More information about the jbpm-commits mailing list