[jbpm-commits] JBoss JBPM SVN: r6171 - in jbpm3/branches/jbpm-3.2-soa/modules: core/src/main/java/org/jbpm/context/exe and 9 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Feb 16 14:01:52 EST 2010


Author: alex.guizar at jboss.com
Date: 2010-02-16 14:01:50 -0500 (Tue, 16 Feb 2010)
New Revision: 6171

Modified:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableInstance.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Action.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/exe/Token.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Join.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/TaskNode.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/xml/JpdlXmlReader.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/scheduler/def/CreateTimerAction.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2094/JBPM2094Test.java
   jbpm3/branches/jbpm-3.2-soa/modules/simulation/src/main/java/org/jbpm/sim/exe/ExperimentReader.java
Log:
JBPM-2790: limit SOSE occurrences in join node

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/JbpmConfiguration.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -336,30 +336,28 @@
   protected static JbpmConfiguration createJbpmConfiguration(
       ObjectFactory objectFactory) {
     JbpmConfiguration jbpmConfiguration = new JbpmConfiguration(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)) {
-        StaleObjectLogConfigurer.hideStaleObjectExceptions();
-      }
     }
-
+    // honor hide stale state exceptions setting
+    if (getHideStaleObjectExceptions(objectFactory)) {
+      StaleObjectLogConfigurer.hideStaleObjectExceptions();
+    }
     return jbpmConfiguration;
   }
 
   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;
+    if (objectFactory.hasObject("jbpm.hide.stale.object.exceptions")) {
+      Object hide =
+          objectFactory.createObject("jbpm.hide.stale.object.exceptions");
+      if (Boolean.FALSE.equals(hide)) return false;
+    }
+    return true;
   }
 
   public static JbpmConfiguration parseInputStream(InputStream inputStream) {

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -15,37 +15,37 @@
 import org.jbpm.graph.exe.Token;
 
 public abstract class VariableContainer implements Serializable {
-  
+
   private static final long serialVersionUID = 520258491083406913L;
-  protected Map variableInstances = null;
+  protected Map variableInstances;
 
   protected abstract VariableContainer getParentVariableContainer();
+
   public abstract Token getToken();
-  
+
   // variables ////////////////////////////////////////////////////////////////
-  
+
   public Object getVariable(String name) {
     Object value = null;
     if (hasVariableLocally(name)) {
       value = getVariableLocally(name);
-    } else {
+    }
+    else {
       VariableContainer parent = getParentVariableContainer();
-      if (parent!=null) {
+      if (parent != null) {
         // check upwards in the token hierarchy
         value = parent.getVariable(name);
       }
-    } 
+    }
     return value;
   }
-  
+
   public void setVariable(String name, Object value) {
     VariableContainer parent = getParentVariableContainer();
-    if ( hasVariableLocally(name)
-         || parent==null 
-       ) {
+    if (hasVariableLocally(name) || parent == null) {
       setVariableLocally(name, value);
-
-    } else { 
+    }
+    else {
       // so let's action to the parent token's TokenVariableMap
       parent.setVariable(name, value);
     }
@@ -57,10 +57,10 @@
     // if the variable is present in the variable instances
     if (hasVariableLocally(name)) {
       hasVariable = true;
-
-    } else {
+    }
+    else {
       VariableContainer parent = getParentVariableContainer();
-      if (parent!=null) {
+      if (parent != null) {
         hasVariable = parent.hasVariable(name);
       }
     }
@@ -69,7 +69,7 @@
   }
 
   public void deleteVariable(String name) {
-    if (name==null) {
+    if (name == null) {
       throw new JbpmException("name is null");
     }
     if (hasVariableLocally(name)) {
@@ -78,25 +78,23 @@
   }
 
   /**
-   * adds all the given variables to this variable container.
-   * The method {@link #setVariables(Map)} is the same as this method, but 
-   * it was added for naming consitency.
+   * adds all the given variables to this variable container. The method
+   * {@link #setVariables(Map)} is the same as this method, but it was added for
+   * naming consistency.
    */
   public void addVariables(Map variables) {
     setVariables(variables);
   }
 
   /**
-   * adds all the given variables to this variable container.  It doesn't 
-   * remove any existing variables unless they are overwritten by the given 
-   * variables.
-   * This method is the same as {@link #addVariables(Map)} and this method 
-   * was added for naming consistency. 
+   * adds all the given variables to this variable container. It doesn't remove
+   * any existing variables unless they are overwritten by the given variables.
+   * This method is the same as {@link #addVariables(Map)} and this method was
+   * added for naming consistency.
    */
   public void setVariables(Map variables) {
-    if (variables!=null) {
-      Iterator iter = variables.entrySet().iterator();
-      while (iter.hasNext()) {
+    if (variables != null) {
+      for (Iterator iter = variables.entrySet().iterator(); iter.hasNext();) {
         Map.Entry entry = (Map.Entry) iter.next();
         setVariable((String) entry.getKey(), entry.getValue());
       }
@@ -106,7 +104,7 @@
   public Map getVariables() {
     Map variables = getVariablesLocally();
     VariableContainer parent = getParentVariableContainer();
-    if (parent!=null) {
+    if (parent != null) {
       Map parentVariables = parent.getVariablesLocally();
       parentVariables.putAll(variables);
       variables = parentVariables;
@@ -116,9 +114,8 @@
 
   public Map getVariablesLocally() {
     Map variables = new HashMap();
-    if (variableInstances!=null) {
-      Iterator iter = variableInstances.entrySet().iterator();
-      while (iter.hasNext()) {
+    if (variableInstances != null) {
+      for (Iterator iter = variableInstances.entrySet().iterator(); iter.hasNext();) {
         Map.Entry entry = (Map.Entry) iter.next();
         String name = (String) entry.getKey();
         VariableInstance variableInstance = (VariableInstance) entry.getValue();
@@ -133,14 +130,12 @@
   // local variable methods ///////////////////////////////////////////////////
 
   public boolean hasVariableLocally(String name) {
-    return ( (variableInstances!=null)
-             && (variableInstances.containsKey(name))
-           );
+    return variableInstances != null && variableInstances.containsKey(name);
   }
 
   public Object getVariableLocally(String name) {
     Object value = null;
-    
+
     // if the variable is present in the variable instances
     if (hasVariableLocally(name)) {
       value = getVariableInstance(name).getValue();
@@ -154,27 +149,31 @@
   }
 
   public void setVariableLocally(String name, Object value) {
-    if (name==null) {
+    if (name == null) {
       throw new JbpmException("name is null");
     }
-    
+
     VariableInstance variableInstance = getVariableInstance(name);
-    // if there is already a variable instance and it doesn't support the current type...
-    if ( (variableInstance!=null) 
-         && (!variableInstance.supports(value))
-       ) {
+    // if there is already a variable instance
+    // and it doesn't support the current value
+    if (variableInstance != null && !variableInstance.supports(value)) {
       // delete the old variable instance
-      log.debug("variable type change. deleting '"+name+"' from '"+this+"'");
+      log.debug("variable type change, deleting '" + name + "' from "
+        + getToken());
       deleteVariableInstance(name);
       variableInstance = null;
     }
 
-    if (variableInstance==null) {
-      log.debug("create variable '"+name+"' in '"+this+"' with value '"+value+"'");
-      variableInstance = VariableInstance.create(getToken(), name, value);
+    if (variableInstance == null) {
+      Token token = getToken();
+      log.debug("create variable '" + name + "' for " + token + " with value: "
+        + value);
+      variableInstance = VariableInstance.create(token, name, value);
       addVariableInstance(variableInstance);
-    } else {
-      log.debug("update variable '"+name+"' in '"+this+"' to value '"+value+"'");
+    }
+    else {
+      log.debug("update variable '" + name + "' for "
+        + variableInstance.getToken() + " to value: " + value);
       variableInstance.setValue(value);
     }
   }
@@ -182,53 +181,57 @@
   // local variable instances /////////////////////////////////////////////////
 
   public VariableInstance getVariableInstance(String name) {
-    return (variableInstances!=null ? (VariableInstance) variableInstances.get(name) : null);
+    return variableInstances != null ? (VariableInstance) variableInstances.get(name)
+        : null;
   }
-  
+
   public Map getVariableInstances() {
     return variableInstances;
   }
 
   public void addVariableInstance(VariableInstance variableInstance) {
-    if (variableInstances==null) {
-      variableInstances = new HashMap();
-    }
+    if (variableInstances == null) variableInstances = new HashMap();
     variableInstances.put(variableInstance.getName(), variableInstance);
-    // only additions are registered in the updated variable containers 
-    // because it is only used in the save operation to check wether there 
+    // only additions are registered in the updated variable containers
+    // because it is only used in the save operation to check whether there
     // are unpersistable variables added
     addUpdatedVariableContainer();
   }
 
   public void deleteVariableInstance(String name) {
-    if (variableInstances!=null) {
-      VariableInstance variableInstance = (VariableInstance) variableInstances.remove(name);
-      if (variableInstance!=null) {
+    if (variableInstances != null) {
+      VariableInstance variableInstance =
+          (VariableInstance) variableInstances.remove(name);
+      if (variableInstance != null) {
         getToken().addLog(new VariableDeleteLog(variableInstance));
         variableInstance.removeReferences();
       }
     }
   }
 
-  void addUpdatedVariableContainer(){
+  void addUpdatedVariableContainer() {
     ContextInstance contextInstance = getContextInstance();
-    if (contextInstance!=null) {
-      if (contextInstance.updatedVariableContainers==null) {
+    if (contextInstance != null) {
+      if (contextInstance.updatedVariableContainers == null) {
         contextInstance.updatedVariableContainers = new ArrayList();
       }
       contextInstance.updatedVariableContainers.add(this);
     }
   }
-  
+
   public ContextInstance getContextInstance() {
     Token token = getToken();
-    ProcessInstance processInstance = (token!=null ? token.getProcessInstance() : null);
-    return (processInstance!=null ? processInstance.getContextInstance() : null);
+    if (token != null) {
+      ProcessInstance processInstance = token.getProcessInstance();
+      if (processInstance != null) return processInstance.getContextInstance();
+    }
+    return null;
   }
-  
-  public static Collection getUpdatedVariableContainers(ProcessInstance processInstance) {
+
+  public static Collection getUpdatedVariableContainers(
+      ProcessInstance processInstance) {
     return processInstance.getContextInstance().updatedVariableContainers;
   }
-  
+
   private static Log log = LogFactory.getLog(VariableContainer.class);
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableInstance.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableInstance.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableInstance.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -38,162 +38,163 @@
  */
 public abstract class VariableInstance implements Serializable {
 
-	private static final long serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
-	long id = 0;
-	int version = 0;
-	protected String name = null;
-	protected Token token = null;
-	protected TokenVariableMap tokenVariableMap = null;
-	protected ProcessInstance processInstance = null;
-	protected Converter converter = null;
-	protected Object valueCache = null;
-	protected boolean isValueCached = false;
+  long id;
+  int version;
+  protected String name;
+  protected Token token;
+  protected TokenVariableMap tokenVariableMap;
+  protected ProcessInstance processInstance;
+  protected Converter converter;
+  protected Object valueCache;
+  protected boolean isValueCached;
 
-	// constructors /////////////////////////////////////////////////////////////
+  // constructors /////////////////////////////////////////////////////////////
 
-	public VariableInstance() {}
+  public VariableInstance() {
+  }
 
-	public static VariableInstance create(Token token, String name, Object value) {
+  public static VariableInstance create(Token token, String name, Object value) {
 
-		VariableInstance variableInstance = null;
-		if(value == null) {
-			variableInstance = new NullInstance();
-		}
-		else {
-			variableInstance = createVariableInstance(value);
-		}
+    VariableInstance variableInstance = null;
+    if (value == null) {
+      variableInstance = new NullInstance();
+    }
+    else {
+      variableInstance = createVariableInstance(value);
+    }
 
-		variableInstance.token = token;
-		variableInstance.name = name;
-		variableInstance.processInstance = (token != null ? token
-				.getProcessInstance() : null);
-		if(token != null) {
-			token.addLog(new VariableCreateLog(variableInstance));
-		}
-		variableInstance.setValue(value);
-		return variableInstance;
-	}
+    variableInstance.token = token;
+    variableInstance.name = name;
+    variableInstance.processInstance =
+        (token != null ? token.getProcessInstance() : null);
+    if (token != null) {
+      token.addLog(new VariableCreateLog(variableInstance));
+    }
+    variableInstance.setValue(value);
+    return variableInstance;
+  }
 
-	public static VariableInstance createVariableInstance(Object value) {
-		VariableInstance variableInstance = null;
+  public static VariableInstance createVariableInstance(Object value) {
+    VariableInstance variableInstance = null;
 
-		Iterator iter = JbpmType.getJbpmTypes().iterator();
-		while((iter.hasNext()) && (variableInstance == null)) {
-			JbpmType jbpmType = (JbpmType) iter.next();
+    Iterator iter = JbpmType.getJbpmTypes().iterator();
+    while ((iter.hasNext()) && (variableInstance == null)) {
+      JbpmType jbpmType = (JbpmType) iter.next();
 
-			if(jbpmType.matches(value)) {
-				variableInstance = jbpmType.newVariableInstance();
-			}
-		}
+      if (jbpmType.matches(value)) {
+        variableInstance = jbpmType.newVariableInstance();
+      }
+    }
 
-		if(variableInstance == null) {
-			variableInstance = new UnpersistableInstance();
-		}
+    if (variableInstance == null) {
+      variableInstance = new UnpersistableInstance();
+    }
 
-		return variableInstance;
-	}
+    return variableInstance;
+  }
 
-	// abstract methods /////////////////////////////////////////////////////////
+  // abstract methods /////////////////////////////////////////////////////////
 
-	/**
-	 * is true if this variable-instance supports the given value, false
-	 * otherwise.
-	 */
-	public abstract boolean isStorable(Object value);
+  /**
+   * is true if this variable-instance supports the given value, false
+   * otherwise.
+   */
+  public abstract boolean isStorable(Object value);
 
-	/**
-	 * is the value, stored by this variable instance.
-	 */
-	protected abstract Object getObject();
+  /**
+   * is the value, stored by this variable instance.
+   */
+  protected abstract Object getObject();
 
-	/**
-	 * stores the value in this variable instance.
-	 */
-	protected abstract void setObject(Object value);
+  /**
+   * stores the value in this variable instance.
+   */
+  protected abstract void setObject(Object value);
 
-	// variable management //////////////////////////////////////////////////////
+  // variable management //////////////////////////////////////////////////////
 
-	public boolean supports(Object value) {
-		if(converter != null) {
-			return converter.supports(value);
-		}
-		return isStorable(value);
-	}
+  public boolean supports(Object value) {
+    if (converter != null) {
+      return converter.supports(value);
+    }
+    return isStorable(value);
+  }
 
-	public void setValue(Object value) {
-		valueCache = value;
-		isValueCached = true;
+  public void setValue(Object value) {
+    valueCache = value;
+    isValueCached = true;
 
-		if(converter != null) {
-			if(!converter.supports(value)) {
-				throw new JbpmException(
-						"the converter '"
-								+ converter.getClass().getName()
-								+ "' in variable instance '"
-								+ this.getClass().getName()
-								+ "' does not support values of type '"
-								+ value.getClass().getName()
-								+ "'.  to change the type of a variable, you have to delete it first");
-			}
-			value = converter.convert(value);
-		}
-		if((value != null) && (!this.isStorable(value))) {
-			throw new JbpmException("variable instance '" + this.getClass().getName()
-					+ "' does not support values of type '" + value.getClass().getName()
-					+ "'.  to change the type of a variable, you have to delete it first");
-		}
-		setObject(value);
-	}
+    if (converter != null) {
+      if (!converter.supports(value)) {
+        throw new JbpmException("the converter '"
+          + converter.getClass().getName() + "' in variable instance '"
+          + this.getClass().getName() + "' does not support values of type '"
+          + value.getClass().getName()
+          + "'.  to change the type of a variable, you have to delete it first");
+      }
+      value = converter.convert(value);
+    }
+    if ((value != null) && (!this.isStorable(value))) {
+      throw new JbpmException("variable instance '" + this.getClass().getName()
+        + "' does not support values of type '" + value.getClass().getName()
+        + "'.  to change the type of a variable, you have to delete it first");
+    }
+    setObject(value);
+  }
 
-	public Object getValue() {
-		if(isValueCached) {
-			return valueCache;
-		}
-		Object value = getObject();
-		if((value != null) && (converter != null)) {
-			if(converter instanceof SerializableToByteArrayConverter && processInstance != null) {
-				SerializableToByteArrayConverter s2bConverter = (SerializableToByteArrayConverter) converter;
-			  value = s2bConverter.revert(value, processInstance.getProcessDefinition());
-			}
-			else {
-				value = converter.revert(value);
-			}
-			valueCache = value;
-			isValueCached = true;
-		}
-		return value;
-	}
+  public Object getValue() {
+    if (isValueCached) {
+      return valueCache;
+    }
+    Object value = getObject();
+    if ((value != null) && (converter != null)) {
+      if (converter instanceof SerializableToByteArrayConverter
+        && processInstance != null) {
+        SerializableToByteArrayConverter s2bConverter =
+            (SerializableToByteArrayConverter) converter;
+        value =
+            s2bConverter.revert(value, processInstance.getProcessDefinition());
+      }
+      else {
+        value = converter.revert(value);
+      }
+      valueCache = value;
+      isValueCached = true;
+    }
+    return value;
+  }
 
-	public void removeReferences() {
-		tokenVariableMap = null;
-		token = null;
-		processInstance = null;
-	}
+  public void removeReferences() {
+    tokenVariableMap = null;
+    token = null;
+    processInstance = null;
+  }
 
-	// utility methods /////////////////////////////////////////////////////////
+  // utility methods /////////////////////////////////////////////////////////
 
-	public String toString() {
-		return "${" + name + "}";
-	}
+  public String toString() {
+    return "${" + name + "}";
+  }
 
-	// getters and setters //////////////////////////////////////////////////////
+  // getters and setters //////////////////////////////////////////////////////
 
-	public String getName() {
-		return name;
-	}
+  public String getName() {
+    return name;
+  }
 
-	public ProcessInstance getProcessInstance() {
-		return processInstance;
-	}
+  public ProcessInstance getProcessInstance() {
+    return processInstance;
+  }
 
-	public Token getToken() {
-		return token;
-	}
+  public Token getToken() {
+    return token;
+  }
 
-	public void setTokenVariableMap(TokenVariableMap tokenVariableMap) {
-		this.tokenVariableMap = tokenVariableMap;
-	}
+  public void setTokenVariableMap(TokenVariableMap tokenVariableMap) {
+    this.tokenVariableMap = tokenVariableMap;
+  }
 
-	// private static Log log = LogFactory.getLog(VariableInstance.class);
+  // private static Log log = LogFactory.getLog(VariableInstance.class);
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Action.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Action.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Action.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -91,11 +91,7 @@
 
     String acceptPropagatedEvents =
         actionElement.attributeValue("accept-propagated-events");
-    if ("false".equalsIgnoreCase(acceptPropagatedEvents)
-      || "no".equalsIgnoreCase(acceptPropagatedEvents)
-      || "off".equalsIgnoreCase(acceptPropagatedEvents)) {
-      isPropagationAllowed = false;
-    }
+    isPropagationAllowed = jpdlReader.readBoolean(acceptPropagatedEvents, true);
 
     String asyncText = actionElement.attributeValue("async");
     if ("true".equalsIgnoreCase(asyncText)) {

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -44,7 +44,6 @@
 import org.jbpm.job.ExecuteNodeJob;
 import org.jbpm.jpdl.xml.JpdlXmlReader;
 import org.jbpm.jpdl.xml.Parsable;
-import org.jbpm.msg.MessageService;
 import org.jbpm.util.Clock;
 
 public class Node extends GraphElement implements Parsable {
@@ -82,34 +81,39 @@
 
     private Object readResolve() throws ObjectStreamException {
       NodeType nodeType = valueOf(name);
-      if (nodeType == null) throw new InvalidObjectException("invalid node type: " + name);
+      if (nodeType == null) {
+        throw new InvalidObjectException("invalid node type: " + name);
+      }
       return nodeType;
     }
   };
 
-  protected List leavingTransitions = null;
-  transient Map leavingTransitionMap = null;
-  protected Set arrivingTransitions = null;
-  protected Action action = null;
-  protected SuperState superState = null;
-  protected boolean isAsync = false;
-  protected boolean isAsyncExclusive = false;
+  protected List leavingTransitions;
+  transient Map leavingTransitionMap;
+  protected Set arrivingTransitions;
+  protected Action action;
+  protected SuperState superState;
+  protected boolean isAsync;
+  protected boolean isAsyncExclusive;
 
   public NodeType getNodeType() {
     return NodeType.Node;
   }
 
+  /** @deprecated not in use */
   public String getNameExt() {
     String name = super.getName();
     if (name == null) name = "#anonymous" + getNodeType();
-
     return name;
   }
 
   // event types //////////////////////////////////////////////////////////////
 
-  public static final String[] supportedEventTypes = new String[] { Event.EVENTTYPE_NODE_ENTER,
-      Event.EVENTTYPE_NODE_LEAVE, Event.EVENTTYPE_BEFORE_SIGNAL, Event.EVENTTYPE_AFTER_SIGNAL };
+  public static final String[] supportedEventTypes =
+    { Event.EVENTTYPE_NODE_ENTER,
+      Event.EVENTTYPE_NODE_LEAVE,
+      Event.EVENTTYPE_BEFORE_SIGNAL,
+      Event.EVENTTYPE_AFTER_SIGNAL };
 
   public String[] getSupportedEventTypes() {
     return supportedEventTypes;
@@ -153,13 +157,14 @@
   }
 
   /**
-   * are the leaving {@link Transition}s, mapped by their name (java.lang.String).
+   * are the leaving {@link Transition}s, mapped by their name (String).
    */
   public Map getLeavingTransitionsMap() {
     if (leavingTransitionMap == null && leavingTransitions != null) {
       // initialize the cached leaving transition map
       leavingTransitionMap = new HashMap();
-      ListIterator iter = leavingTransitions.listIterator(leavingTransitions.size());
+      ListIterator iter =
+        leavingTransitions.listIterator(leavingTransitions.size());
       while (iter.hasPrevious()) {
         Transition leavingTransition = (Transition) iter.previous();
         leavingTransitionMap.put(leavingTransition.getName(), leavingTransition);
@@ -169,14 +174,15 @@
   }
 
   /**
-   * creates a bidirection relation between this node and the given leaving transition.
+   * creates a bidirection relation between this node and the given leaving
+   * transition.
    * 
    * @throws IllegalArgumentException if leavingTransition is null.
    */
   public Transition addLeavingTransition(Transition leavingTransition) {
-    if (leavingTransition == null)
+    if (leavingTransition == null) {
       throw new IllegalArgumentException("leaving transition is null");
-
+    }
     if (leavingTransitions == null) leavingTransitions = new ArrayList();
     leavingTransition.from = this;
     leavingTransitions.add(leavingTransition);
@@ -185,15 +191,17 @@
   }
 
   /**
-   * removes the bidirection relation between this node and the given leaving transition.
+   * removes the bidirection relation between this node and the given leaving
+   * transition.
    * 
    * @throws IllegalArgumentException if leavingTransition is null.
    */
   public void removeLeavingTransition(Transition leavingTransition) {
-    if (leavingTransition == null)
+    if (leavingTransition == null) {
       throw new IllegalArgumentException("leaving transition is null");
-
-    if (leavingTransitions != null && leavingTransitions.remove(leavingTransition)) {
+    }
+    if (leavingTransitions != null
+      && leavingTransitions.remove(leavingTransition)) {
       leavingTransition.from = null;
       leavingTransitionMap = null;
     }
@@ -202,16 +210,22 @@
   /**
    * checks for the presence of a leaving transition with the given name.
    * 
-   * @return true if this node has a leaving transition with the given name, false otherwise.
+   * @return true if this node has a leaving transition with the given name,
+   * false otherwise.
    */
   public boolean hasLeavingTransition(String transitionName) {
-    if (leavingTransitions == null) return false;
-    return getLeavingTransitionsMap().containsKey(transitionName);
+    if (leavingTransitions != null) {
+      for (Iterator i = leavingTransitions.iterator(); i.hasNext();) {
+        Transition transition = (Transition) i.next();
+        if (transitionName.equals(transition.getName())) return true;
+      }
+    }
+    return false;
   }
 
   /**
-   * retrieves a leaving transition by name. note that also the leaving transitions of the supernode
-   * are taken into account.
+   * retrieves a leaving transition by name. note that also the leaving
+   * transitions of the supernode are taken into account.
    */
   public Transition getLeavingTransition(String transitionName) {
     Transition transition = null;
@@ -228,12 +242,13 @@
    * true if this transition has leaving transitions.
    */
   public boolean hasNoLeavingTransitions() {
-    return (leavingTransitions == null || leavingTransitions.size() == 0) &&
-        (superState == null || superState.hasNoLeavingTransitions());
+    return (leavingTransitions == null || leavingTransitions.size() == 0)
+      && (superState == null || superState.hasNoLeavingTransitions());
   }
 
   /**
-   * generates a new name for a transition that will be added as a leaving transition.
+   * generates a new name for a transition that will be added as a leaving
+   * transition.
    */
   public String generateNextLeavingTransitionName() {
     String name = null;
@@ -249,8 +264,8 @@
   boolean containsName(List leavingTransitions, String name) {
     for (Iterator iter = leavingTransitions.iterator(); iter.hasNext();) {
       Transition transition = (Transition) iter.next();
-      if (name != null ? name.equals(transition.getName()) : transition.getName() == null)
-        return true;
+      if (name != null ? name.equals(transition.getName())
+        : transition.getName() == null) return true;
     }
     return false;
   }
@@ -279,12 +294,12 @@
   }
 
   /**
-   * moves one leaving transition from the oldIndex and inserts it at the newIndex.
+   * moves one leaving transition from the oldIndex and inserts it at the
+   * newIndex.
    */
   public void reorderLeavingTransition(int oldIndex, int newIndex) {
-    if (leavingTransitions != null &&
-        Math.min(oldIndex, newIndex) >= 0 &&
-        Math.max(oldIndex, newIndex) < leavingTransitions.size()) {
+    if (leavingTransitions != null && Math.min(oldIndex, newIndex) >= 0
+      && Math.max(oldIndex, newIndex) < leavingTransitions.size()) {
       Object transition = leavingTransitions.remove(oldIndex);
       leavingTransitions.add(newIndex, transition);
     }
@@ -300,14 +315,15 @@
   }
 
   /**
-   * add a bidirection relation between this node and the given arriving transition.
+   * add a bidirection relation between this node and the given arriving
+   * transition.
    * 
    * @throws IllegalArgumentException if t is null.
    */
   public Transition addArrivingTransition(Transition arrivingTransition) {
-    if (arrivingTransition == null)
+    if (arrivingTransition == null) {
       throw new IllegalArgumentException("arriving transition is null");
-
+    }
     if (arrivingTransitions == null) arrivingTransitions = new HashSet();
     arrivingTransition.to = this;
     arrivingTransitions.add(arrivingTransition);
@@ -315,15 +331,17 @@
   }
 
   /**
-   * removes the bidirection relation between this node and the given arriving transition.
+   * removes the bidirection relation between this node and the given arriving
+   * transition.
    * 
    * @throws IllegalArgumentException if t is null.
    */
   public void removeArrivingTransition(Transition arrivingTransition) {
-    if (arrivingTransition == null)
+    if (arrivingTransition == null) {
       throw new IllegalArgumentException("arriving transition is null");
-
-    if (arrivingTransitions != null && arrivingTransitions.remove(arrivingTransition)) {
+    }
+    if (arrivingTransitions != null
+      && arrivingTransitions.remove(arrivingTransition)) {
       arrivingTransition.to = null;
     }
   }
@@ -331,7 +349,8 @@
   // various //////////////////////////////////////////////////////////////////
 
   /**
-   * is the {@link SuperState} or the {@link ProcessDefinition} in which this node is contained.
+   * is the {@link SuperState} or the {@link ProcessDefinition} in which this
+   * node is contained.
    */
   public GraphElement getParent() {
     GraphElement parent;
@@ -353,12 +372,12 @@
     // update the runtime context information
     token.setNode(this);
 
+    // register entrance time so that a node-log can be generated upon leaving
+    token.setNodeEnter(Clock.getCurrentTime());
+
     // fire the leave-node event for this node
     fireEvent(Event.EVENTTYPE_NODE_ENTER, executionContext);
 
-    // register entrance time so that a node-log can be generated upon leaving
-    token.setNodeEnter(Clock.getCurrentTime());
-
     // remove the transition references from the runtime context
     executionContext.setTransition(null);
     executionContext.setTransitionSource(null);
@@ -366,8 +385,10 @@
     // execute the node
     if (isAsync) {
       ExecuteNodeJob job = createAsyncContinuationJob(token);
-      MessageService messageService = executionContext.getJbpmContext().getServices().getMessageService();
-      messageService.send(job);
+      executionContext.getJbpmContext()
+        .getServices()
+        .getMessageService()
+        .send(job);
       token.lock(job.toString());
     }
     else {
@@ -408,14 +429,16 @@
   }
 
   /**
-   * called by the implementation of this node to continue execution over the default transition.
+   * called by the implementation of this node to continue execution over the
+   * default transition.
    */
   public void leave(ExecutionContext executionContext) {
     leave(executionContext, getDefaultLeavingTransition());
   }
 
   /**
-   * called by the implementation of this node to continue execution over the specified transition.
+   * called by the implementation of this node to continue execution over the
+   * specified transition.
    */
   public void leave(ExecutionContext executionContext, String transitionName) {
     Transition transition = getLeavingTransition(transitionName);
@@ -426,11 +449,11 @@
   }
 
   /**
-   * called by the implementation of this node to continue execution over the given transition.
+   * called by the implementation of this node to continue execution over the
+   * given transition.
    */
   public void leave(ExecutionContext executionContext, Transition transition) {
-    if (transition == null)
-      throw new JbpmException("transition is null");
+    if (transition == null) throw new JbpmException("transition is null");
 
     Token token = executionContext.getToken();
     token.setNode(this);
@@ -459,7 +482,8 @@
   // ///////////////////////////////////////////////////////////////////////////
 
   public ProcessDefinition getProcessDefinition() {
-    return superState != null ? superState.getProcessDefinition() : processDefinition;
+    return superState != null ? superState.getProcessDefinition()
+      : processDefinition;
   }
 
   // change the name of a node ////////////////////////////////////////////////
@@ -471,11 +495,8 @@
       String oldName = this.name;
       if (superState != null) {
         if (superState.hasNode(name)) {
-          throw new IllegalArgumentException("cannot rename " +
-              this +
-              " to '" +
-              name +
-              "'; superstate has a child node with the same name");
+          throw new IllegalArgumentException("cannot rename " + this
+            + ", superstate already has a node named " + name);
         }
         Map nodes = superState.getNodesMap();
         nodes.remove(oldName);
@@ -483,11 +504,8 @@
       }
       else if (processDefinition != null) {
         if (processDefinition.hasNode(name)) {
-          throw new IllegalArgumentException("cannot rename " +
-              this +
-              " to '" +
-              name +
-              "'; process definition has a child node with the same name");
+          throw new IllegalArgumentException("cannot rename " + this
+            + ", process definition already has a node named " + name);
         }
         Map nodeMap = processDefinition.getNodesMap();
         nodeMap.remove(oldName);
@@ -505,7 +523,8 @@
    * the slash separated name that includes all the superstate names.
    */
   public String getFullyQualifiedName() {
-    return superState != null ? superState.getFullyQualifiedName() + '/' + name : name;
+    return superState != null ? superState.getFullyQualifiedName() + '/' + name
+      : name;
   }
 
   /** indicates wether this node is a superstate. */

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/exe/Token.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/exe/Token.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/exe/Token.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -282,43 +282,47 @@
    * ended as well and the verification will continue to propagate.
    */
   public void end(boolean verifyParentTermination) {
-    // if not already ended
-    if (end == null) {
-      // ended tokens cannot reactivate parents
-      isAbleToReactivateParent = false;
+    // if already ended, do nothing
+    if (end != null) {
+      log.warn(this + " has ended already");
+      return;
+    }
 
-      // set the end date
-      // the end date also indicates that this token has ended
-      this.end = Clock.getCurrentTime();
+    // ended tokens cannot reactivate parents
+    isAbleToReactivateParent = false;
 
-      // end all this token's children
-      if (children != null) {
-        for (Iterator iter = children.values().iterator(); iter.hasNext();) {
-          Token child = (Token) iter.next();
-          if (!child.hasEnded()) child.end();
-        }
-      }
+    // set the end date
+    // the end date also indicates that this token has ended
+    end = Clock.getCurrentTime();
 
-      if (subProcessInstance != null) {
-        subProcessInstance.end();
+    // end all this token's children
+    if (children != null) {
+      for (Iterator iter = children.values().iterator(); iter.hasNext();) {
+        Token child = (Token) iter.next();
+        if (!child.hasEnded()) child.end();
       }
+    }
 
-      // only log child-token ends
-      // process instance logs replace root token logs
-      if (parent != null) {
-        parent.addLog(new TokenEndLog(this));
-      }
+    // end the subprocess instance, if any
+    if (subProcessInstance != null) {
+      subProcessInstance.end();
+    }
 
-      // if there are tasks associated to this token,
-      // remove signaling capabilities
-      TaskMgmtInstance taskMgmtInstance = processInstance.getTaskMgmtInstance();
-      if (taskMgmtInstance != null) taskMgmtInstance.removeSignalling(this);
+    // only log child-token ends
+    // process instance logs replace root token logs
+    if (parent != null) {
+      parent.addLog(new TokenEndLog(this));
+    }
 
-      if (verifyParentTermination) {
-        // if this is the last active token of the parent,
-        // the parent needs to be ended as well
-        notifyParentOfTokenEnd();
-      }
+    // if there are tasks associated to this token,
+    // remove signaling capabilities
+    TaskMgmtInstance taskMgmtInstance = processInstance.getTaskMgmtInstance();
+    if (taskMgmtInstance != null) taskMgmtInstance.removeSignalling(this);
+
+    if (verifyParentTermination) {
+      // if this is the last active token of the parent,
+      // the parent needs to be ended as well
+      notifyParentOfTokenEnd();
     }
   }
 

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Join.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Join.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Join.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -22,6 +22,7 @@
 package org.jbpm.graph.node;
 
 import java.util.Collection;
+import java.util.Date;
 import java.util.Iterator;
 
 import org.apache.commons.logging.Log;
@@ -43,14 +44,14 @@
   private static final long serialVersionUID = 1L;
 
   /**
-   * specifies what type of hibernate lock should be acquired. null value defaults to
-   * LockMode.UPGRADE
+   * specifies what type of hibernate lock should be acquired. null value
+   * defaults to LockMode.UPGRADE
    */
   String parentLockMode;
 
   /**
-   * specifies if this join is a discriminator. a descriminator reactivates the parent when the
-   * first concurrent token enters the join.
+   * specifies if this join is a discriminator. a descriminator reactivates the
+   * parent when the first concurrent token enters the join.
    */
   boolean isDiscriminator;
 
@@ -93,121 +94,140 @@
     }
   }
 
-  public void execute(ExecutionContext executionContext) {
+  public void enter(ExecutionContext executionContext) {
     Token token = executionContext.getToken();
-    boolean isAbleToReactivateParent = token.isAbleToReactivateParent();
+    token.end(false);
+    super.enter(executionContext);
+  }
 
-    if (!token.hasEnded()) {
-      token.end(false);
-    }
+  public void execute(ExecutionContext executionContext) {
+    Token arrivingToken = executionContext.getToken();
+    Token parentToken = arrivingToken.getParent();
+    if (parentToken != null) {
+      JbpmContext jbpmContext = executionContext.getJbpmContext();
+      Session session;
+      if (jbpmContext != null && (session = jbpmContext.getSession()) != null) {
+        // obtain update lock by default (LockMode.UPGRADE)
+        LockMode lockMode = parentLockMode != null ? LockMode.parse(parentLockMode)
+          : LockMode.UPGRADE;
+        // load() hits the database as required, no need to flush() here
+        parentToken = (Token) session.load(Token.class,
+          new Long(parentToken.getId()), lockMode);
+        log.debug("acquired " + lockMode + " lock on " + parentToken);
+      }
 
-    // if this token is not able to reactivate the parent,
-    // we don't need to check anything
-    if (isAbleToReactivateParent) {
-      // the token arrived in the join and can only reactivate
-      // the parent once
-      token.setAbleToReactivateParent(false);
+      boolean reactivateParent;
 
-      Token parentToken = token.getParent();
-      if (parentToken != null) {
-        JbpmContext jbpmContext = executionContext.getJbpmContext();
-        Session session;
-        if (jbpmContext != null && (session = jbpmContext.getSession()) != null) {
-          // obtain update lock by default (LockMode.UPGRADE)
-          LockMode lockMode = parentLockMode != null ? LockMode.parse(parentLockMode)
-              : LockMode.UPGRADE;
-          // load() hits the database as required, no need to flush() here
-          parentToken = (Token) session.load(Token.class, new Long(parentToken.getId()), lockMode);
-          log.debug("acquired " + lockMode + " lock on " + parentToken);
+      // if this is a discriminator
+      if (isDiscriminator) {
+        // reactivate the parent when the first token arrives in the join
+        reactivateParent = true;
+      }
+      // if a fixed set of tokenNames is specified at design time...
+      else if (tokenNames != null) {
+        // check reactivation on the basis of those tokenNames
+        reactivateParent = mustParentBeReactivated(parentToken, tokenNames)
+          && isLastToArrive(arrivingToken, tokenNames);
+      }
+      // if a script is specified
+      else if (script != null) {
+        // check if the script returns a collection or a boolean
+        Object result = null;
+        try {
+          result = script.eval(arrivingToken);
         }
-
-        boolean reactivateParent;
-
-        // if this is a discriminator
-        if (isDiscriminator) {
-          // reactivate the parent when the first token arrives in the join.
-          // this must be the first token arriving, otherwise isAbleToReactivateParent()
-          // should have been false above.
-          reactivateParent = true;
+        catch (Exception e) {
+          raiseException(e, executionContext);
         }
-        // if a fixed set of tokenNames is specified at design time...
-        else if (tokenNames != null) {
-          // check reactivation on the basis of those tokenNames
-          reactivateParent = mustParentBeReactivated(parentToken, tokenNames.iterator());
+        // if the result is a collection
+        if (result instanceof Collection) {
+          // interpret as a collection of token names
+          Collection tokenNames = (Collection) result;
+          reactivateParent = mustParentBeReactivated(parentToken, tokenNames)
+            && isLastToArrive(arrivingToken, tokenNames);
         }
-        // if a script is specified
-        else if (script != null) {
-          // check if the script returns a collection or a boolean
-          Object result = null;
-          try {
-            result = script.eval(token);
-          }
-          catch (Exception e) {
-            raiseException(e, executionContext);
-          }
-          // if the result is a collection
-          if (result instanceof Collection) {
-            // interpret as a collection of token names
-            Collection runtimeTokenNames = (Collection) result;
-            reactivateParent = mustParentBeReactivated(parentToken, runtimeTokenNames.iterator());
-          }
-          // if it is a boolean...
-          else if (result instanceof Boolean) {
-            // the boolean specifies if the parent needs to be reactivated
-            reactivateParent = ((Boolean) result).booleanValue();
-          }
-          // any other object
-          else {
-            // non-null result means the parent needs to be reactivated
-            reactivateParent = result != null;
-          }
+        // if it is a boolean...
+        else if (result instanceof Boolean) {
+          // the boolean specifies if the parent needs to be reactivated
+          reactivateParent = ((Boolean) result).booleanValue();
         }
-        // if a nOutOfM is specified
-        else if (nOutOfM != -1) {
-          int n = 0;
-          // check how many tokens already arrived in the join
-          for (Iterator iter = parentToken.getChildren().values().iterator(); iter.hasNext();) {
-            Token concurrentToken = (Token) iter.next();
-            if (equals(concurrentToken.getNode())) n++;
-          }
-          reactivateParent = n >= nOutOfM;
-        }
-        // if no configuration is specified..
+        // any other object
         else {
-          // the default behaviour is to check all concurrent tokens and reactivate
-          // the parent if the last token arrives in the join
-          reactivateParent = mustParentBeReactivated(parentToken, parentToken.getChildren()
-              .keySet()
-              .iterator());
+          // non-null result means the parent needs to be reactivated
+          reactivateParent = result != null;
         }
+      }
+      // if a nOutOfM is specified
+      else if (nOutOfM != -1) {
+        int n = 0;
+        // check how many tokens already arrived in the join
+        for (Iterator iter = parentToken.getChildren().values().iterator(); iter.hasNext();) {
+          Token concurrentToken = (Token) iter.next();
+          if (equals(concurrentToken.getNode())) n++;
+        }
+        reactivateParent = n >= nOutOfM;
+      }
+      // if no configuration is specified
+      else {
+        // check all concurrent tokens and reactivate the parent
+        // when the last token arrives in the join
+        Collection tokenNames = parentToken.getChildren().keySet();
+        reactivateParent = mustParentBeReactivated(parentToken, tokenNames)
+          && isLastToArrive(arrivingToken, tokenNames);
+      }
 
-        // if the parent token needs to be reactivated from this join node
-        if (reactivateParent) {
-          // write to all child tokens that the parent is already reactivated
-          for (Iterator iter = parentToken.getChildren().values().iterator(); iter.hasNext();) {
-            Token concurrentToken = (Token) iter.next();
-            concurrentToken.setAbleToReactivateParent(false);
-          }
-          // write to all child tokens that the parent is already reactivated
-          ExecutionContext parentContext = new ExecutionContext(parentToken);
-          leave(parentContext);
+      // if the parent token needs to be reactivated from this join node
+      if (reactivateParent) {
+        // write to all child tokens that the parent is already reactivated
+        for (Iterator iter = parentToken.getChildren().values().iterator(); iter.hasNext();) {
+          Token concurrentToken = (Token) iter.next();
+          concurrentToken.setAbleToReactivateParent(false);
         }
+        // leave the join node
+        leave(new ExecutionContext(parentToken));
       }
     }
   }
 
-  public boolean mustParentBeReactivated(Token parentToken, Iterator concurrentTokenNames) {
-    while (concurrentTokenNames.hasNext()) {
-      String concurrentTokenName = (String) concurrentTokenNames.next();
-      Token concurrentToken = parentToken.getChild(concurrentTokenName);
-      if (concurrentToken.isAbleToReactivateParent()) {
-        log.debug("join will not reactivate parent yet, found concurrent " + concurrentToken);
+  private boolean mustParentBeReactivated(Token parentToken,
+    Collection childTokenNames) {
+    return mustParentBeReactivated(parentToken, childTokenNames.iterator());
+  }
+
+  public boolean mustParentBeReactivated(Token parentToken,
+    Iterator childTokenNames) {
+    while (childTokenNames.hasNext()) {
+      String childTokenName = (String) childTokenNames.next();
+      Token childToken = parentToken.getChild(childTokenName);
+      if (childToken.isAbleToReactivateParent()) {
+        log.debug(parentToken + " will not leave " + this + ", " + childToken
+          + " can still reactivate parent");
         return false;
       }
     }
     return true;
   }
 
+  private boolean isLastToArrive(Token arrivingToken,
+    Collection concurrentTokenNames) {
+    Date enterDate = arrivingToken.getNodeEnter();
+    Token parentToken = arrivingToken.getParent();
+    for (Iterator i = concurrentTokenNames.iterator(); i.hasNext();) {
+      String concurrentTokenName = (String) i.next();
+      Token concurrentToken = (Token) parentToken.getChild(concurrentTokenName);
+      if (arrivingToken.equals(concurrentToken)
+        || !equals(concurrentToken.getNode())) continue;
+
+      Date concurrentEnterDate = concurrentToken.getNodeEnter();
+      if (enterDate.before(concurrentEnterDate)) {
+        log.debug(parentToken + " will not leave " + this + ", "
+          + arrivingToken + " was not the last to arrive");
+        return false;
+      }
+    }
+    return true;
+  }
+
   public String getParentLockMode() {
     return parentLockMode;
   }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/TaskNode.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/TaskNode.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/TaskNode.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -42,39 +42,43 @@
 import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
 
 /**
- * is a node that relates to one or more tasks. Property <code>signal</code> specifies how task
- * completion triggers continuation of execution.
+ * is a node that relates to one or more tasks. Property <code>signal</code>
+ * specifies how task completion triggers continuation of execution.
  */
 public class TaskNode extends Node implements Parsable {
 
   private static final long serialVersionUID = 1L;
 
   /**
-   * execution always continues, regardless whether tasks are created or still unfinished.
+   * execution always continues, regardless whether tasks are created or still
+   * unfinished.
    */
   public static final int SIGNAL_UNSYNCHRONIZED = 0;
   /**
-   * execution never continues, regardless whether tasks are created or still unfinished.
+   * execution never continues, regardless whether tasks are created or still
+   * unfinished.
    */
   public static final int SIGNAL_NEVER = 1;
   /**
-   * proceeds execution when the first task instance is completed. when no tasks are created on
-   * entrance of this node, execution is continued.
+   * proceeds execution when the first task instance is completed. when no tasks
+   * are created on entrance of this node, execution is continued.
    */
   public static final int SIGNAL_FIRST = 2;
   /**
-   * proceeds execution when the first task instance is completed. when no tasks are created on
-   * entrance of this node, execution waits in the task node till tasks are created.
+   * proceeds execution when the first task instance is completed. when no tasks
+   * are created on entrance of this node, execution waits in the task node till
+   * tasks are created.
    */
   public static final int SIGNAL_FIRST_WAIT = 3;
   /**
-   * proceeds execution when the last task instance is completed. when no tasks are created on
-   * entrance of this node, execution is continued.
+   * proceeds execution when the last task instance is completed. when no tasks
+   * are created on entrance of this node, execution is continued.
    */
   public static final int SIGNAL_LAST = 4;
   /**
-   * proceeds execution when the last task instance is completed. when no tasks are created on
-   * entrance of this node, execution waits in the task node till tasks are created.
+   * proceeds execution when the last task instance is completed. when no tasks
+   * are created on entrance of this node, execution waits in the task node till
+   * tasks are created.
    */
   public static final int SIGNAL_LAST_WAIT = 5;
 
@@ -123,10 +127,10 @@
     }
   }
 
-  Set tasks = null;
+  Set tasks;
   int signal = SIGNAL_LAST;
   boolean createTasks = true;
-  boolean endTasks = false;
+  boolean endTasks;
 
   public TaskNode() {
   }
@@ -148,19 +152,11 @@
 
     // create tasks
     String createTasksText = element.attributeValue("create-tasks");
-    if (createTasksText != null) {
-      if (("no".equalsIgnoreCase(createTasksText)) || ("false".equalsIgnoreCase(createTasksText))) {
-        createTasks = false;
-      }
-    }
+    createTasks = jpdlReader.readBoolean(createTasksText, true);
 
     // create tasks
     String removeTasksText = element.attributeValue("end-tasks");
-    if (removeTasksText != null) {
-      if (("yes".equalsIgnoreCase(removeTasksText)) || ("true".equalsIgnoreCase(removeTasksText))) {
-        endTasks = true;
-      }
-    }
+    endTasks = jpdlReader.readBoolean(removeTasksText, false);
 
     // parse the tasks
     jpdlReader.readTasks(element, this);
@@ -173,16 +169,15 @@
   }
 
   // node behaviour methods
-  /////////////////////////////////////////////////////////////////////////////
+  // ///////////////////////////////////////////////////////////////////////////
 
   public void execute(ExecutionContext executionContext) {
 
     TaskMgmtInstance tmi = getTaskMgmtInstance(executionContext.getToken());
 
     // if this tasknode should create instances
-    if ((createTasks) && (tasks != null)) {
-      Iterator iter = tasks.iterator();
-      while (iter.hasNext()) {
+    if (createTasks && tasks != null) {
+      for (Iterator iter = tasks.iterator(); iter.hasNext();) {
         Task task = (Task) iter.next();
         executionContext.setTask(task);
         if (evaluateTaskCondition(task.getCondition(), executionContext)) {
@@ -210,26 +205,26 @@
     }
   }
 
-  boolean evaluateTaskCondition(String condition, ExecutionContext executionContext) {
+  boolean evaluateTaskCondition(String condition,
+    ExecutionContext executionContext) {
     if (condition == null) return true;
-    Object result = JbpmExpressionEvaluator.evaluate(condition, executionContext);
-    if (Boolean.TRUE.equals(result)) {
-      return true;
-    }
-    return false;
+
+    Object result = JbpmExpressionEvaluator.evaluate(condition,
+      executionContext);
+    return Boolean.TRUE.equals(result);
   }
 
   public void leave(ExecutionContext executionContext, Transition transition) {
     TaskMgmtInstance tmi = getTaskMgmtInstance(executionContext.getToken());
     if (tmi.hasBlockingTaskInstances(executionContext.getToken())) {
-      throw new IllegalStateException("task-node '" + name + "' still has blocking tasks");
+      throw new IllegalStateException(this + " still has blocking tasks");
     }
     removeTaskInstanceSynchronization(executionContext.getToken());
     super.leave(executionContext, transition);
   }
 
   // task behaviour methods
-  /////////////////////////////////////////////////////////////////////////////
+  // ///////////////////////////////////////////////////////////////////////////
 
   public boolean completionTriggersSignal(TaskInstance taskInstance) {
     boolean completionTriggersSignal;
@@ -253,14 +248,12 @@
     TaskMgmtInstance tmi = getTaskMgmtInstance(token);
 
     boolean isLastToComplete = true;
-    Iterator iter = tmi.getTaskInstances().iterator();
-    while (iter.hasNext() && (isLastToComplete)) {
+    for (Iterator iter = tmi.getTaskInstances().iterator(); iter.hasNext()
+      && isLastToComplete;) {
       TaskInstance other = (TaskInstance) iter.next();
-      if ((token != null)
-          && (token.equals(other.getToken()))
-          && (!other.equals(taskInstance))
-          && (other.isSignalling())
-          && (!other.hasEnded())) {
+      if (token != null && token.equals(other.getToken())
+        && !other.equals(taskInstance) && other.isSignalling()
+        && !other.hasEnded()) {
         isLastToComplete = false;
       }
     }
@@ -272,8 +265,7 @@
     TaskMgmtInstance tmi = getTaskMgmtInstance(token);
     Collection taskInstances = tmi.getTaskInstances();
     if (taskInstances != null) {
-      Iterator iter = taskInstances.iterator();
-      while (iter.hasNext()) {
+      for (Iterator iter = taskInstances.iterator(); iter.hasNext();) {
         TaskInstance taskInstance = (TaskInstance) iter.next();
         if (token.equals(taskInstance.getToken())) {
           // remove signalling
@@ -286,11 +278,10 @@
           }
           // if this is a non-finished task and all those
           // tasks should be finished
-          if ((!taskInstance.hasEnded()) && (endTasks)) {
-            if (tasks.contains(taskInstance.getTask())) {
-              // end this task
-              taskInstance.end();
-            }
+          if (!taskInstance.hasEnded() && endTasks
+            && tasks.contains(taskInstance.getTask())) {
+            // end this task
+            taskInstance.end();
           }
         }
       }
@@ -298,21 +289,21 @@
   }
 
   TaskMgmtInstance getTaskMgmtInstance(Token token) {
-    return (TaskMgmtInstance) token.getProcessInstance().getInstance(TaskMgmtInstance.class);
+    return (TaskMgmtInstance) token.getProcessInstance()
+      .getInstance(TaskMgmtInstance.class);
   }
 
   // getters and setters
-  /////////////////////////////////////////////////////////////////////////////
+  // ///////////////////////////////////////////////////////////////////////////
 
   /**
-   * is a Map with the tasks, keyed by task-name or an empty map in case no tasks are present in
-   * this task-node.
+   * is a Map with the tasks, keyed by task-name or an empty map in case no
+   * tasks are present in this task-node.
    */
   public Map getTasksMap() {
     Map tasksMap = new HashMap();
     if (tasks != null) {
-      Iterator iter = tasks.iterator();
-      while (iter.hasNext()) {
+      for (Iterator iter = tasks.iterator(); iter.hasNext();) {
         Task task = (Task) iter.next();
         tasksMap.put(task.getName(), task);
       }
@@ -321,8 +312,8 @@
   }
 
   /**
-   * is the task in this task-node with the given name or null if the given task does not exist in
-   * this node.
+   * is the task in this task-node with the given name or null if the given task
+   * does not exist in this node.
    */
   public Task getTask(String taskName) {
     return (Task) getTasksMap().get(taskName);

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -6,7 +6,7 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
-import java.util.List;
+import java.util.Random;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -18,7 +18,6 @@
 import org.jbpm.job.Job;
 import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
-import org.jbpm.util.ClassUtil;
 
 public class JobExecutorThread extends Thread {
 
@@ -29,6 +28,7 @@
   final long maxLockTime;
 
   volatile boolean isActive = true;
+  private final Random random = new Random();
 
   public JobExecutorThread(String name, JobExecutor jobExecutor) {
     super(jobExecutor.getThreadGroup(), name);
@@ -44,8 +44,8 @@
    * @deprecated use {@link #JobExecutorThread(String, JobExecutor)} instead
    */
   public JobExecutorThread(String name, JobExecutor jobExecutor,
-      JbpmConfiguration jbpmConfiguration, int idleInterval,
-      int maxIdleInterval, long maxLockTime, int maxHistory) {
+    JbpmConfiguration jbpmConfiguration, int idleInterval, int maxIdleInterval,
+    long maxLockTime, int maxHistory) {
     super(jobExecutor.getThreadGroup(), name);
     this.jobExecutor = jobExecutor;
 
@@ -67,6 +67,7 @@
           }
           catch (Exception e) {
             saveJobException(job, e);
+            throw e;
           }
         }
         if (isActive) {
@@ -80,73 +81,84 @@
         // no exception, reset current idle interval
         currentIdleInterval = idleInterval;
       }
-      catch (RuntimeException e) {
+      catch (InterruptedException e) {
+        if (log.isDebugEnabled()) log.debug(getName() + " got interrupted");
+      }
+      catch (Exception e) {
+        // if this is a locking exception, keep it quiet
+        if (DbPersistenceService.isLockingException(e)) {
+          StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
+            .error("job execution failure", e);
+        }
+        else {
+          log.error("job execution failure", e);
+        }
+        // wait after error
         if (isActive) {
-          log.error("exception in " + getName() + ", waiting "
-            + currentIdleInterval + " ms", e);
+          // wait a random period, at least half the current idle interval
+          int waitPeriod = currentIdleInterval / 2;
+          waitPeriod = random.nextInt(waitPeriod) + waitPeriod;
           try {
-            synchronized (jobExecutor) {
-              jobExecutor.wait(currentIdleInterval);
-            }
+            // sleep instead of waiting on jobExecutor to prevent
+            // DbMessageService from waking up this thread
+            sleep(waitPeriod);
             // after an exception, double the current idle interval to avoid
             // throwing exceptions continuously during anomalous conditions
             currentIdleInterval *= 2;
-            if (currentIdleInterval > maxIdleInterval
-              || currentIdleInterval < 0) {
+            if (currentIdleInterval > maxIdleInterval || currentIdleInterval < 0) {
               currentIdleInterval = maxIdleInterval;
             }
           }
           catch (InterruptedException ie) {
-            log.debug(getName() + " got interrupted");
+            if (log.isDebugEnabled()) log.debug(getName() + " got interrupted");
           }
         }
       }
-      catch (InterruptedException e) {
-        log.debug(getName() + " got interrupted");
-      }
     }
     log.info(getName() + " leaves cyberspace");
   }
 
   protected Collection acquireJobs() {
-    Collection acquiredJobs;
-
+    boolean debug = log.isDebugEnabled();
+    Collection jobs;
+    // acquire monitor before creating context and allocating resources
     synchronized (jobExecutor) {
-      List jobsToLock = Collections.EMPTY_LIST;
-
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       try {
-        JobSession jobSession = jbpmContext.getJobSession();
-
         String lockOwner = getName();
-        Job job = jobSession.getFirstAcquirableJob(lockOwner);
-        if (job != null) {
-          if (job.isExclusive()) {
-            ProcessInstance processInstance = job.getProcessInstance();
-            log.debug("finding exclusive jobs for " + processInstance);
-            jobsToLock =
-                jobSession.findExclusiveJobs(lockOwner, processInstance);
-            log.debug("acquiring " + jobsToLock + " for " + processInstance);
+        JobSession jobSession = jbpmContext.getJobSession();
+        Job firstJob = jobSession.getFirstAcquirableJob(lockOwner);
+        if (firstJob != null) {
+          if (firstJob.isExclusive()) {
+            ProcessInstance processInstance = firstJob.getProcessInstance();
+            jobs = jobSession.findExclusiveJobs(lockOwner, processInstance);
+            if (debug) log.debug("acquiring " + jobs + " for " + processInstance);
           }
           else {
-            log.debug("acquiring " + job);
-            jobsToLock = Collections.singletonList(job);
+            jobs = Collections.singletonList(firstJob);
+            if (debug) log.debug("acquiring " + firstJob);
           }
 
           Date lockTime = new Date();
           int retries = jobExecutor.getRetries();
-          for (Iterator i = jobsToLock.iterator(); i.hasNext();) {
-            job = (Job) i.next();
+          for (Iterator i = jobs.iterator(); i.hasNext();) {
+            Job job = (Job) i.next();
             job.setLockOwner(lockOwner);
             job.setLockTime(lockTime);
-            // if job has not failed already
+            // if job has not failed already, give it the configured retries
             if (job.getException() == null) job.setRetries(retries);
           }
+          if (debug) log.debug("acquired " + jobs);
         }
+        else {
+          jobs = Collections.EMPTY_LIST;
+          if (debug) log.debug("no acquirable job found");
+        }
       }
       catch (RuntimeException e) {
         jbpmContext.setRollbackOnly();
-        throw e;
+        jobs = Collections.EMPTY_LIST;
+        if (debug) log.debug("failed to acquire jobs", e);
       }
       catch (Error e) {
         jbpmContext.setRollbackOnly();
@@ -155,19 +167,14 @@
       finally {
         try {
           jbpmContext.close();
-          acquiredJobs = jobsToLock;
-          log.debug("acquired lock on jobs: " + acquiredJobs);
         }
         catch (RuntimeException e) {
-          if (!DbPersistenceService.isLockingException(e)) throw e;
-          // keep locking exception quiet
-          StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
-              .error("failed to acquire lock on jobs " + jobsToLock, e);
-          acquiredJobs = Collections.EMPTY_LIST;
+          jobs = Collections.EMPTY_LIST;
+          if (debug) log.debug("failed to acquire jobs", e);
         }
       }
     }
-    return acquiredJobs;
+    return jobs;
   }
 
   protected void executeJob(Job job) throws Exception {
@@ -180,7 +187,7 @@
       // see https://jira.jboss.org/jira/browse/JBPM-1015
       jbpmContext.addAutoSaveProcessInstance(job.getProcessInstance());
 
-      log.debug("executing " + job);
+      if (log.isDebugEnabled()) log.debug("executing " + job);
       try {
         if (job.execute(jbpmContext)) {
           jobSession.deleteJob(job);
@@ -189,11 +196,7 @@
       catch (Exception e) {
         // prevent unsafe use of the session after an exception occurs
         jbpmContext.setRollbackOnly();
-
-        if (!DbPersistenceService.isLockingException(e)) throw e;
-        // keep locking exception quiet
-        StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
-            .error("failed to complete " + job, e);
+        throw e;
       }
       catch (Error e) {
         jbpmContext.setRollbackOnly();
@@ -201,70 +204,60 @@
       }
 
       // if this job is locked too long
-      long totalLockTimeInMillis =
-          System.currentTimeMillis() - job.getLockTime().getTime();
+      long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
       if (totalLockTimeInMillis > maxLockTime) {
         jbpmContext.setRollbackOnly();
       }
     }
     finally {
-      try {
-        jbpmContext.close();
-      }
-      catch (RuntimeException e) {
-        if (!DbPersistenceService.isLockingException(e)) throw e;
-        // if this is a locking exception, keep it quiet
-        StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
-            .error("failed to complete " + job);
-      }
+      jbpmContext.close();
     }
   }
 
   private void saveJobException(Job job, Exception exception) {
+    boolean debug = log.isDebugEnabled();
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
     try {
-      log.debug("saving " + ClassUtil.getSimpleName(exception.getClass())
-        + " thrown by " + job);
+      if (debug) log.debug("saving exception thrown by " + job);
+      // do not reattach existing job, it may contain undesired updates
       JobSession jobSession = jbpmContext.getJobSession();
-      // not reattaching existing job as it may contain updates
       job = jobSession.loadJob(job.getId());
 
+      // print and save exception
       StringWriter out = new StringWriter();
       exception.printStackTrace(new PrintWriter(out));
       job.setException(out.toString());
+
+      // decrease retry count
       int retries = job.getRetries() - 1;
       job.setRetries(retries);
-      log.debug(job + " has " + retries + " retries remaining");
+      if (debug) log.debug(job + " has " + retries + " retries remaining");
     }
     catch (RuntimeException e) {
       jbpmContext.setRollbackOnly();
-      log.error("failed to save job exception", exception);
-      throw e;
+      if (debug) log.debug("failed to save job exception", e);
     }
     catch (Error e) {
       jbpmContext.setRollbackOnly();
-      log.error("failed to save job exception", exception);
       throw e;
     }
     finally {
-      jbpmContext.close();
+      try {
+        jbpmContext.close();
+      }
+      catch (RuntimeException e) {
+        if (debug) log.debug("failed to save job exception", e);
+      }
     }
   }
 
   protected long getWaitPeriod(int currentIdleInterval) {
-    long waitPeriod = currentIdleInterval;
-
     Date nextDueDate = getNextDueDate();
     if (nextDueDate != null) {
-      long nextDueTime = nextDueDate.getTime();
-      long currentTime = System.currentTimeMillis();
-
-      if (nextDueTime < currentTime + currentIdleInterval) {
-        waitPeriod = nextDueTime - currentTime;
-        if (waitPeriod < 0) waitPeriod = 0;
-      }
+      long waitPeriod = nextDueDate.getTime() - System.currentTimeMillis();
+      if (waitPeriod < currentIdleInterval) return waitPeriod;
     }
-    return waitPeriod;
+    return currentIdleInterval;
   }
 
   protected Date getNextDueDate() {
@@ -296,7 +289,7 @@
         if (!DbPersistenceService.isLockingException(e)) throw e;
         // keep locking exception quiet
         StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
-            .error("failed to determine next due date", e);
+          .error("failed to determine next due date", e);
         nextDueDate = null;
       }
     }
@@ -311,8 +304,7 @@
   }
 
   /**
-   * Indicates that this thread should stop running. Execution will cease
-   * shortly afterwards.
+   * Indicates that this thread should stop running. Execution will cease shortly afterwards.
    */
   public void deactivate() {
     if (isActive) {

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/xml/JpdlXmlReader.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/xml/JpdlXmlReader.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/xml/JpdlXmlReader.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -177,8 +177,7 @@
   }
 
   protected void readSwimlanes(Element processDefinitionElement) {
-    TaskMgmtDefinition taskMgmtDefinition =
-        processDefinition.getTaskMgmtDefinition();
+    TaskMgmtDefinition taskMgmtDefinition = processDefinition.getTaskMgmtDefinition();
     for (Iterator iter = processDefinitionElement.elementIterator("swimlane"); iter.hasNext();) {
       Element swimlaneElement = (Element) iter.next();
       String swimlaneName = swimlaneElement.attributeValue("name");
@@ -196,8 +195,7 @@
             swimlane.setPooledActorsExpression(assignmentElement.attributeValue("pooled-actors"));
           }
           else {
-            Delegation assignmentDelegation =
-                readAssignmentDelegation(assignmentElement);
+            Delegation assignmentDelegation = readAssignmentDelegation(assignmentElement);
             swimlane.setAssignmentDelegation(assignmentDelegation);
           }
         }
@@ -250,8 +248,7 @@
 
   public void readTasks(Element element, TaskNode taskNode) {
     List elements = element.elements("task");
-    TaskMgmtDefinition tmd =
-        (TaskMgmtDefinition) processDefinition.getDefinition(TaskMgmtDefinition.class);
+    TaskMgmtDefinition tmd = (TaskMgmtDefinition) processDefinition.getDefinition(TaskMgmtDefinition.class);
     if (elements.size() > 0) {
       if (tmd == null) {
         tmd = new TaskMgmtDefinition();
@@ -266,7 +263,7 @@
   }
 
   public Task readTask(Element taskElement,
-      TaskMgmtDefinition taskMgmtDefinition, TaskNode taskNode) {
+    TaskMgmtDefinition taskMgmtDefinition, TaskNode taskNode) {
     Task task = new Task();
     task.setProcessDefinition(processDefinition);
 
@@ -321,19 +318,11 @@
 
     // blocking
     String blockingText = taskElement.attributeValue("blocking");
-    if (blockingText != null
-      && ("true".equalsIgnoreCase(blockingText)
-        || "yes".equalsIgnoreCase(blockingText) || "on".equalsIgnoreCase(blockingText))) {
-      task.setBlocking(true);
-    }
+    task.setBlocking(readBoolean(blockingText, false));
 
     // signalling
     String signallingText = taskElement.attributeValue("signalling");
-    if (signallingText != null
-      && ("false".equalsIgnoreCase(signallingText)
-        || "no".equalsIgnoreCase(signallingText) || "off".equalsIgnoreCase(signallingText))) {
-      task.setSignalling(false);
-    }
+    task.setSignalling(readBoolean(signallingText, true));
 
     // assignment
     String swimlaneName = taskElement.attributeValue("swimlane");
@@ -343,8 +332,7 @@
     if (swimlaneName != null) {
       Swimlane swimlane = taskMgmtDefinition.getSwimlane(swimlaneName);
       if (swimlane == null) {
-        addWarning("task references unknown swimlane: "
-          + taskElement.getPath());
+        addWarning("task references unknown swimlane: " + taskElement.getPath());
       }
       else {
         task.setSwimlane(swimlane);
@@ -358,8 +346,7 @@
         task.setPooledActorsExpression(assignmentElement.attributeValue("pooled-actors"));
       }
       else {
-        Delegation assignmentDelegation =
-            readAssignmentDelegation(assignmentElement);
+        Delegation assignmentDelegation = readAssignmentDelegation(assignmentElement);
         task.setAssignmentDelegation(assignmentDelegation);
       }
     }
@@ -367,22 +354,23 @@
     else {
       // user has to manage assignment manually, so better inform him/her
       addProblem(new Problem(Problem.LEVEL_INFO,
-          "no assignment specified for task: " + taskElement.getPath()));
+        "no assignment specified for task: " + taskElement.getPath()));
     }
 
     // notify
     String notificationsText = taskElement.attributeValue("notify");
-    if (notificationsText != null
-      && ("true".equalsIgnoreCase(notificationsText)
-        || "on".equalsIgnoreCase(notificationsText) || "yes".equalsIgnoreCase(notificationsText))) {
+    if (readBoolean(notificationsText, false)) {
       String notificationEvent = Event.EVENTTYPE_TASK_ASSIGN;
       Event event = task.getEvent(notificationEvent);
       if (event == null) {
         event = new Event(notificationEvent);
         task.addEvent(event);
       }
-      Delegation delegation =
-          createMailDelegation(notificationEvent, null, null, null, null);
+      Delegation delegation = createMailDelegation(notificationEvent,
+        null,
+        null,
+        null,
+        null);
       Action action = new Action(delegation);
       action.setProcessDefinition(processDefinition);
       action.setName(task.getName());
@@ -398,6 +386,15 @@
     return task;
   }
 
+  public boolean readBoolean(String text, boolean defaultValue) {
+    if (text == null) return defaultValue;
+    if ("true".equalsIgnoreCase(text) || "yes".equalsIgnoreCase(text)
+      || "on".equalsIgnoreCase(text)) return true;
+    if ("false".equalsIgnoreCase(text) || "no".equalsIgnoreCase(text)
+      || "off".equalsIgnoreCase(text)) return false;
+    return defaultValue;
+  }
+
   protected Delegation readAssignmentDelegation(Element assignmentElement) {
     Delegation assignmentDelegation = new Delegation();
     String expression = assignmentElement.attributeValue("expression");
@@ -453,8 +450,7 @@
 
       String variableName = variableElement.attributeValue("name");
       if (variableName == null) {
-        addWarning("variable name not specified: "
-          + variableElement.getPath());
+        addWarning("variable name not specified: " + variableElement.getPath());
       }
       String access = variableElement.attributeValue("access", "read,write");
       String mappedName = variableElement.attributeValue("mapped-name");
@@ -465,8 +461,7 @@
   }
 
   public void readStartStateTask(Element startTaskElement, StartState startState) {
-    TaskMgmtDefinition taskMgmtDefinition =
-        processDefinition.getTaskMgmtDefinition();
+    TaskMgmtDefinition taskMgmtDefinition = processDefinition.getTaskMgmtDefinition();
     Task startTask = readTask(startTaskElement, taskMgmtDefinition, null);
     startTask.setStartState(startState);
     if (startTask.getName() == null) {
@@ -476,7 +471,7 @@
   }
 
   public void readNode(Element nodeElement, Node node,
-      NodeCollection nodeCollection) {
+    NodeCollection nodeCollection) {
 
     // first put the node in its collection. this is done so that the
     // setName later on will be able to differentiate between nodes contained in
@@ -567,8 +562,11 @@
       action = readSingleAction(timerElement);
     }
     else {
-      Delegation delegation =
-          createMailDelegation("task-reminder", null, null, null, null);
+      Delegation delegation = createMailDelegation("task-reminder",
+        null,
+        null,
+        null,
+        null);
       action = new Action(delegation);
     }
     createTimerAction.setTimerAction(action);
@@ -610,7 +608,7 @@
   }
 
   public void readActions(Element eventElement, GraphElement graphElement,
-      String eventType) {
+    String eventType) {
     // for all the elements in the event element
     for (Iterator iter = eventElement.elementIterator(); iter.hasNext();) {
       Element actionElement = (Element) iter.next();
@@ -626,7 +624,7 @@
   }
 
   protected void addAction(GraphElement graphElement, String eventType,
-      Action action) {
+    Action action) {
     Event event = graphElement.getEvent(eventType);
     if (event == null) {
       event = new Event(eventType);
@@ -679,7 +677,7 @@
   }
 
   protected void readExceptionHandlers(Element graphDomElement,
-      GraphElement graphElement) {
+    GraphElement graphElement) {
     for (Iterator iter = graphDomElement.elementIterator("exception-handler"); iter.hasNext();) {
       Element exceptionHandlerElement = (Element) iter.next();
       readExceptionHandler(exceptionHandlerElement, graphElement);
@@ -687,7 +685,7 @@
   }
 
   protected void readExceptionHandler(Element exceptionHandlerElement,
-      GraphElement graphElement) {
+    GraphElement graphElement) {
     // create the exception handler
     ExceptionHandler exceptionHandler = new ExceptionHandler();
     exceptionHandler.setExceptionClassName(exceptionHandlerElement.attributeValue("exception-class"));
@@ -734,7 +732,7 @@
    * configuration properties)
    */
   public Transition resolveTransitionDestination(Element transitionElement,
-      Node node) {
+    Node node) {
     Transition transition = new Transition();
     transition.setProcessDefinition(processDefinition);
 
@@ -792,11 +790,9 @@
       Element actionElement = (Element) unresolvedActionReference[0];
       Action action = (Action) unresolvedActionReference[1];
       String referencedActionName = actionElement.attributeValue("ref-name");
-      Action referencedAction =
-          processDefinition.getAction(referencedActionName);
+      Action referencedAction = processDefinition.getAction(referencedActionName);
       if (referencedAction == null) {
-        addWarning("referenced action not found: "
-          + actionElement.getPath());
+        addWarning("referenced action not found: " + actionElement.getPath());
       }
       action.setReferencedAction(referencedAction);
     }
@@ -804,8 +800,7 @@
 
   // verify swimlane assignments in second pass ///////////////////////////////
   public void verifySwimlaneAssignments() {
-    TaskMgmtDefinition taskMgmtDefinition =
-        processDefinition.getTaskMgmtDefinition();
+    TaskMgmtDefinition taskMgmtDefinition = processDefinition.getTaskMgmtDefinition();
     Map swimlanes;
     if (taskMgmtDefinition != null
       && (swimlanes = taskMgmtDefinition.getSwimlanes()) != null) {
@@ -813,8 +808,8 @@
         Swimlane swimlane = (Swimlane) iter.next();
 
         Task startTask = taskMgmtDefinition.getStartTask();
-        Swimlane startTaskSwimlane =
-            startTask != null ? startTask.getSwimlane() : null;
+        Swimlane startTaskSwimlane = startTask != null ? startTask.getSwimlane()
+          : null;
 
         if (swimlane.getAssignmentDelegation() == null
           && swimlane != startTaskSwimlane) {
@@ -828,7 +823,7 @@
   // mail delegations /////////////////////////////////////////////////////////
 
   public Delegation createMailDelegation(String template, String actors,
-      String to, String subject, String text) {
+    String to, String subject, String text) {
     StringBuffer config = new StringBuffer();
     if (template != null) {
       config.append("<template>");
@@ -858,8 +853,7 @@
 
     String mailClassName = Mail.class.getName();
     if (JbpmConfiguration.Configs.hasObject("jbpm.mail.class.name")) {
-      mailClassName =
-          JbpmConfiguration.Configs.getString("jbpm.mail.class.name");
+      mailClassName = JbpmConfiguration.Configs.getString("jbpm.mail.class.name");
     }
     else if (JbpmConfiguration.Configs.hasObject("mail.class.name")) {
       mailClassName = JbpmConfiguration.Configs.getString("mail.class.name");

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -28,8 +28,11 @@
 
 public class StaleObjectLogConfigurer {
 
-  private static final Log log = LogFactory.getLog(StaleObjectLogConfigurer.class);
-  private static Log staleObjectExceptionsLog = LogFactory.getLog(StaleObjectLogConfigurer.class.getName()+".staleObjectExceptions");
+  private static final Log log =
+      LogFactory.getLog(StaleObjectLogConfigurer.class);
+  private static Log staleObjectExceptionsLog =
+      LogFactory.getLog(StaleObjectLogConfigurer.class.getName()
+        + ".staleObjectExceptions");
 
   private StaleObjectLogConfigurer() {
     // hide default constructor to prevent instantiation
@@ -41,65 +44,80 @@
 
   public static void hideStaleObjectExceptions() {
     if (staleObjectExceptionsLog instanceof LogWrapper) {
-      log.debug("stale object exceptions are already hidden from logging");
+      log.debug("stale object exceptions already hidden from logging");
       return;
     }
 
-    try {
-      staleObjectExceptionsLog = new LogWrapper(staleObjectExceptionsLog);
-      log.info("stale object exceptions will be hidden from logging");
-    } catch (Exception e) {
-      log.info("couldn't hide stale object exceptions from logging");
-    }
+    log.info("stale object exceptions will be hidden from logging");
+    staleObjectExceptionsLog = new LogWrapper(staleObjectExceptionsLog);
   }
 
   static class LogWrapper implements Log, Serializable {
     Log delegate;
     private static final long serialVersionUID = 1L;
+
     LogWrapper(Log delegate) {
       this.delegate = delegate;
     }
+
     public void debug(Object arg0, Throwable arg1) {
     }
+
     public void debug(Object arg0) {
     }
+
     public void error(Object arg0, Throwable arg1) {
     }
+
     public void error(Object arg0) {
     }
+
     public void info(Object arg0, Throwable arg1) {
     }
+
     public void info(Object arg0) {
     }
+
     public void trace(Object arg0, Throwable arg1) {
     }
+
     public void trace(Object arg0) {
     }
+
     public void warn(Object arg0, Throwable arg1) {
     }
+
     public void warn(Object arg0) {
     }
+
     public void fatal(Object arg0, Throwable arg1) {
       delegate.fatal(arg0, arg1);
     }
+
     public void fatal(Object arg0) {
       delegate.fatal(arg0);
     }
+
     public boolean isDebugEnabled() {
       return delegate.isDebugEnabled();
     }
+
     public boolean isErrorEnabled() {
       return false;
     }
+
     public boolean isFatalEnabled() {
       return delegate.isFatalEnabled();
     }
+
     public boolean isInfoEnabled() {
       return false;
     }
+
     public boolean isTraceEnabled() {
       return false;
     }
+
     public boolean isWarnEnabled() {
       return false;
     }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/scheduler/def/CreateTimerAction.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/scheduler/def/CreateTimerAction.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/scheduler/def/CreateTimerAction.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -60,7 +60,7 @@
         + actionElement.getPath());
     }
     repeat = actionElement.attributeValue("repeat");
-    if ("true".equalsIgnoreCase(repeat) || "yes".equalsIgnoreCase(repeat)) {
+    if (jpdlReader.readBoolean(repeat, false)) {
       repeat = dueDate;
     }
     transitionName = actionElement.attributeValue("transition");

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2094/JBPM2094Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2094/JBPM2094Test.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2094/JBPM2094Test.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -36,7 +36,7 @@
   private ProcessDefinition processDefinition;
 
   private static final int TIMEOUT = 60 * 1000;
-  private static final int INSTANCE_COUNT = 5;
+  private static final int INSTANCE_COUNT = 10;
 
   protected void setUp() throws Exception {
     super.setUp();

Modified: jbpm3/branches/jbpm-3.2-soa/modules/simulation/src/main/java/org/jbpm/sim/exe/ExperimentReader.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/simulation/src/main/java/org/jbpm/sim/exe/ExperimentReader.java	2010-02-15 10:24:13 UTC (rev 6170)
+++ jbpm3/branches/jbpm-3.2-soa/modules/simulation/src/main/java/org/jbpm/sim/exe/ExperimentReader.java	2010-02-16 19:01:50 UTC (rev 6171)
@@ -200,7 +200,7 @@
     JbpmSimulationScenario scenario = new JbpmSimulationScenario(name);
 
     String execute = scenarioElement.attributeValue("execute");
-    if (execute!=null && ("FALSE".equals(execute.toUpperCase()) || "NO".equals(execute.toUpperCase())))
+    if ("false".equalsIgnoreCase(execute)|| "no".equalsIgnoreCase(execute))
         scenario.setExecute(false);
     
     beforeScenarioRead(scenario, scenarioElement, baseScenarioElement);



More information about the jbpm-commits mailing list