[jboss-svn-commits] JBL Code SVN: r25916 - in labs/jbosstm/workspace/adinn/orchestration: src/org/jboss/jbossts/orchestration/agent and 21 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Apr 2 06:13:57 EDT 2009


Author: adinn
Date: 2009-04-02 06:13:56 -0400 (Thu, 02 Apr 2009)
New Revision: 25916

Added:
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckMethodAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleMethodAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerMethodAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/tests/
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestCall.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestEntry.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestExit.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestReadWrite.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestSynch.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestThrow.txt
   labs/jbosstm/workspace/adinn/orchestration/tests/src/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/Test.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestCallThrowSynchAuxiliary.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliary.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliarySub.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestReadWriteAuxiliary.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/helpers/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/helpers/Default.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestCall.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestEntry.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestExit.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestReadWrite.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestSynch.java
   labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestThrow.java
Modified:
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowCheckAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowTriggerAdapter.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeGroup.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java
Log:
added support for local variable references in rules and added initial set of unit tests which check that location specifiers work oky -- all tests pass except the one for AT THROW which fails because of an error in counting throws added due to the presence of synchronized blocks

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -54,7 +54,7 @@
      * matches this location
      * @return the required adapter
      */
-    public abstract RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod);
+    public abstract RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod);
 
     /**
      * return an adapter which can be used to insert a trigger call in a method containing a trigger point whose
@@ -96,10 +96,10 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
             // a line check adapter with line -1 will do the job
 
-            return new LineCheckAdapter(cv, targetClass, targetMethod, -1);
+            return new LineCheckAdapter(cv, rule, targetClass, targetMethod, -1);
         }
 
         /**
@@ -157,8 +157,8 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-            return new LineCheckAdapter(cv, targetClass, targetMethod, targetLine);
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new LineCheckAdapter(cv, rule, targetClass, targetMethod, targetLine);
         }
 
         /**
@@ -254,6 +254,10 @@
             } else {
                 count = 1;
             }
+            if (text.equals("")) {
+                return null;
+            }
+            
             // check for leading type name
             if (text.contains(".")) {
                 int dotIdx = text.lastIndexOf(".");
@@ -273,8 +277,8 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-            return new AccessCheckAdapter(cv, targetClass, targetMethod, typeName, fieldName, flags, count);
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new AccessCheckAdapter(cv, rule, targetClass, targetMethod, typeName, fieldName, flags, count);
         }
 
         /**
@@ -428,8 +432,8 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-            return new InvokeCheckAdapter(cv, targetClass, targetMethod, typeName, methodName, signature, count);
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new InvokeCheckAdapter(cv, rule, targetClass, targetMethod, typeName, methodName, signature, count);
         }
 
         /**
@@ -527,8 +531,8 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-            return new SynchronizeCheckAdapter(cv, targetClass, targetMethod, count);
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new SynchronizeCheckAdapter(cv, rule, targetClass, targetMethod, count);
         }
 
         /**
@@ -631,8 +635,8 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-            return new ThrowCheckAdapter(cv, targetClass, targetMethod, typeName, count);
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new ThrowCheckAdapter(cv, rule, targetClass, targetMethod, typeName, count);
         }
 
         /**
@@ -677,10 +681,10 @@
          * matches this location
          * @return the required adapter
          */
-        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
             // a line check adapter with line -1 will do the job
 
-            return new ExitCheckAdapter(cv, targetClass, targetMethod);
+            return new ExitCheckAdapter(cv, rule, targetClass, targetMethod);
         }
 
         /**

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -340,7 +340,7 @@
     /**
      * prefix for orchestration test package
      */
-    private static final String ORCHESTRATION_TEST_PACKAGE_PREFIX = "org.jboss.jbossts.orchestration.test.";
+    private static final String ORCHESTRATION_TEST_PACKAGE_PREFIX = "org.jboss.jbossts.orchestration.tests.";
 
     /**
      * prefix for com.arjuna package
@@ -428,9 +428,9 @@
         // execute the rule when we hit the relevant line
 
         ClassReader cr = new ClassReader(targetClassBytes);
-        // ClassWriter cw = new ClassWriter(0);
-        ClassVisitor empty = new EmptyVisitor();
-        RuleCheckAdapter checkAdapter = handlerLocation.getRuleCheckAdapter(empty, className, handlerMethod);
+        // need to provide a real writer here so that labels get resolved
+        ClassWriter dummy = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        RuleCheckAdapter checkAdapter = handlerLocation.getRuleCheckAdapter(dummy, rule, className, handlerMethod);
         // PrintWriter pw = new PrintWriter(System.out);
         // ClassVisitor traceAdapter = new TraceClassVisitor(cw, pw);
         // RuleCheckAdapter adapter = handlerLocation.getRuleCheckAdapter(traceAdapter, rule, className, handlerMethod);

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -25,16 +25,20 @@
 
 import org.objectweb.asm.*;
 import org.jboss.jbossts.orchestration.agent.Location;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class AccessCheckAdapter extends RuleCheckAdapter
 {
-     public AccessCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, String ownerClass,
+     public AccessCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, String ownerClass,
                        String fieldName,  int flags, int count)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.ownerClass = ownerClass;
         this.fieldName = fieldName;
         this.flags = flags;
@@ -51,7 +55,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new AccessCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new AccessCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -61,7 +65,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class AccessCheckMethodAdapter extends MethodAdapter
+    private class AccessCheckMethodAdapter extends RuleCheckMethodAdapter
     {
         private int access;
         private String name;
@@ -70,9 +74,9 @@
         private String[] exceptions;
         private boolean visited;
 
-        AccessCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        AccessCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -91,13 +95,20 @@
                 // a relevant invocation occurs in the called method
                 visitedCount++;
                 if (visitedCount == count) {
-                    // and we have enough occurences to match the count
-                    setVisitOk();
+                    setTriggerPoint();
                 }
             }
             super.visitFieldInsn(opcode, owner, name, desc);
         }
 
+        public void visitEnd()
+        {
+            if (checkBindings()) {
+                setVisitOk();
+            }
+            super.visitEnd();
+        }
+
         private boolean matchCall(int opcode, String owner, String name, String desc)
         {
             if (!fieldName.equals(name)) {

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -28,7 +28,6 @@
 import org.jboss.jbossts.orchestration.agent.Location;
 import org.jboss.jbossts.orchestration.agent.Transformer;
 import org.objectweb.asm.*;
-import org.objectweb.asm.commons.GeneratorAdapter;
 import org.objectweb.asm.commons.Method;
 
 /**
@@ -58,9 +57,9 @@
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
             if (name.equals("<init>")) {
-                return new AccessTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+                return new AccessTriggerConstructorAdapter(mv, rule, access, name, desc, signature, exceptions);
             } else {
-                return new AccessTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+                return new AccessTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
             }
         }
         return mv;
@@ -70,7 +69,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class AccessTriggerMethodAdapter extends GeneratorAdapter
+    private class AccessTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         /**
          * flag used by subclass to avoid inserting trigger until after super constructor has been called
@@ -84,9 +83,9 @@
         private Label startLabel;
         private Label endLabel;
 
-        AccessTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        AccessTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -132,7 +131,7 @@
                     } else {
                         super.push((Type)null);
                     }
-                    super.loadArgArray();
+                    doArgLoad();
                     super.invokeStatic(ruleType, method);
                     super.visitLabel(endLabel);
                 }
@@ -248,9 +247,9 @@
 
     private class AccessTriggerConstructorAdapter extends AccessTriggerMethodAdapter
     {
-        AccessTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        AccessTriggerConstructorAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor, signature, exceptions);
+            super(mv, rule, access, name, descriptor, signature, exceptions);
             // ensure we don't transform calls before the super constructor is called
             latched = true;
         }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -1,15 +1,146 @@
 package org.jboss.jbossts.orchestration.agent.adapter;
 
 import org.objectweb.asm.*;
+import org.objectweb.asm.commons.Method;
+import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.agent.Transformer;
 
+import java.util.Vector;
+
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class ExitCheckAdapter extends RuleCheckAdapter
 {
-    public ExitCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
-        super(cv, targetClass, targetMethod);
-        // all methods return at some point so we always insert a trigger somewhere
-        setVisitOk();
+    public ExitCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+        super(cv, rule, targetClass, targetMethod);
+        this.earlyReturnHandlers = new Vector<Label>();
     }
+    /**
+     * table used to track which returns have been added because of exception handling code
+     */
+
+    private Vector<Label> earlyReturnHandlers;
+
+    public MethodVisitor visitMethod(
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final String[] exceptions)
+    {
+        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+        if (matchTargetMethod(name, desc)) {
+            return new ExitCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
+        }
+
+        return mv;
+    }
+
+    /**
+     * a method visitor used to add a rule event trigger call to a method
+     */
+
+    private class ExitCheckMethodAdapter extends RuleCheckMethodAdapter
+    {
+        private int access;
+        private String name;
+        private String descriptor;
+        private String signature;
+        private String[] exceptions;
+        private Vector<Label> startLabels;
+        private Vector<Label> endLabels;
+
+        ExitCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
+        {
+            super(mv, rule, access, name, descriptor);
+            this.access = access;
+            this.name = name;
+            this.descriptor = descriptor;
+            this.signature = signature;
+            this.exceptions = exceptions;
+            startLabels = new Vector<Label>();
+            endLabels = new Vector<Label>();
+        }
+
+        /**
+         * Visits a try catch block and records the label of the handler start if the
+         * exception type EarlyReturnException so we can later avoid inserting a rule
+         * trigger.
+         *
+         * @param start beginning of the exception handler's scope (inclusive).
+         * @param end end of the exception handler's scope (exclusive).
+         * @param handler beginning of the exception handler's code.
+         * @param type internal name of the type of exceptions handled by the
+         *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
+         *        blocks).
+         * @throws IllegalArgumentException if one of the labels has already been
+         *         visited by this visitor (by the {@link #visitLabel visitLabel}
+         *         method).
+         */
+        public void visitTryCatchBlock(Label start, Label end, Label handler, String type)
+        {
+            // check whether type is one of ours and if so add the labels to the
+            // return table
+
+            if (type.equals("org/jboss/jbossts/orchestration/rule/exception/EarlyReturnException")) {
+                earlyReturnHandlers.add(handler);
+            }
+            super.visitTryCatchBlock(start, end, handler, type);
+        }
+
+        /**
+         * each time we visit a label we set or clear flag inhibit depending upon whether the label
+         * identifies an EarlyReturnException block or not in order to avoid inserting triggers
+         * for returns added by our own exception handling code
+         *
+         * @param label
+         */
+        public void visitLabel(Label label)
+        {
+            if (earlyReturnHandlers.contains(label)) {
+                inhibit = true;
+            } else {
+                inhibit = false;
+            }
+
+            super.visitLabel(label);
+        }
+
+        /**
+         * we need to identify return instructions which are inserted because of other rules
+         *
+         * @param opcode
+         */
+        public void visitInsn(final int opcode) {
+            switch (opcode) {
+                case Opcodes.RETURN: // empty stack
+                case Opcodes.IRETURN: // 1 before n/a after
+                case Opcodes.FRETURN: // 1 before n/a after
+                case Opcodes.ARETURN: // 1 before n/a after
+                case Opcodes.LRETURN: // 2 before n/a after
+                case Opcodes.DRETURN: // 2 before n/a after
+                {
+                    if (!inhibit) {
+                        // ok this is not one of our inserted return instructions so record this as a trigger point
+                        setTriggerPoint();
+                    }
+                }
+                break;
+            }
+
+            super.visitInsn(opcode);
+        }
+
+        public void visitEnd()
+        {
+            if (checkBindings()) {
+                setVisitOk();
+            }
+            super.visitEnd();
+        }
+
+        private boolean inhibit;
+    }
 }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ExitTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -34,7 +34,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new ExitTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new ExitTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -44,7 +44,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class ExitTriggerMethodAdapter extends GeneratorAdapter
+    private class ExitTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         private int access;
         private String name;
@@ -54,9 +54,9 @@
         private Vector<Label> startLabels;
         private Vector<Label> endLabels;
 
-        ExitTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        ExitTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -132,7 +132,7 @@
                         Method method = Method.getMethod("void execute(String, Object, Object[])");
                         // we are at the relevant line in the method -- so add a trigger call here
                         if (Transformer.isVerbose()) {
-                            System.out.println("ThrowTriggerMethodAdapter.visitInsn : inserting trigger for " + rule.getName());
+                            System.out.println("ExitTriggerMethodAdapter.visitInsn : inserting trigger for " + rule.getName());
                         }
                         Label startLabel = super.newLabel();
                         Label endLabel = super.newLabel();
@@ -145,7 +145,7 @@
                         } else {
                             super.push((Type)null);
                         }
-                        super.loadArgArray();
+                        doArgLoad();
                         super.invokeStatic(ruleType, method);
                         super.visitLabel(endLabel);
                     }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -25,16 +25,20 @@
 
 import org.objectweb.asm.*;
 import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
+import java.util.List;
+import java.util.ArrayList;
+
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class InvokeCheckAdapter extends RuleCheckAdapter
 {
-     public InvokeCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, String calledClass,
-                       String calledMethodName, String calledMethodDescriptor, int count)
+     public InvokeCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod,
+                               String calledClass, String calledMethodName,String calledMethodDescriptor, int count)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule,  targetClass, targetMethod);
         this.calledClass = calledClass;
         this.calledMethodName = calledMethodName;
         this.calledMethodDescriptor = calledMethodDescriptor;
@@ -51,7 +55,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new InvokeCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new InvokeCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -61,7 +65,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class InvokeCheckMethodAdapter extends MethodAdapter
+    private class InvokeCheckMethodAdapter extends RuleCheckMethodAdapter
     {
         private int access;
         private String name;
@@ -70,9 +74,9 @@
         private String[] exceptions;
         private boolean visited;
 
-        InvokeCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        InvokeCheckMethodAdapter(MethodVisitor mv, Rule rule,  int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -91,13 +95,20 @@
                 // a relevant invocation occurs in the called method
                 visitedCount++;
                 if (visitedCount == count) {
-                    // and we have enough occurences to match the count
-                    setVisitOk();
+                    setTriggerPoint();
                 }
             }
             super.visitMethodInsn(opcode, owner, name, desc);
         }
 
+        public void visitEnd()
+        {
+            if (checkBindings()) {
+                setVisitOk();
+            }
+            super.visitEnd();
+        }
+
         private boolean matchCall(String owner, String name, String desc)
         {
             if (!calledMethodName.equals(name)) {

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -57,9 +57,9 @@
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
             if (name.equals("<init>")) {
-                return new InvokeTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+                return new InvokeTriggerConstructorAdapter(mv, rule, access, name, desc, signature, exceptions);
             } else {
-                return new InvokeTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+                return new InvokeTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
             }
         }
         return mv;
@@ -69,7 +69,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class InvokeTriggerMethodAdapter extends GeneratorAdapter
+    private class InvokeTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         /**
          * flag used by subclass to avoid inserting trigger until after super constructor has been called
@@ -83,9 +83,9 @@
         private Label startLabel;
         private Label endLabel;
 
-        InvokeTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        InvokeTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -131,7 +131,7 @@
                     } else {
                         super.push((Type)null);
                     }
-                    super.loadArgArray();
+                    doArgLoad();
                     super.invokeStatic(ruleType, method);
                     super.visitLabel(endLabel);
                 }
@@ -233,9 +233,9 @@
 
     private class InvokeTriggerConstructorAdapter extends InvokeTriggerMethodAdapter
     {
-        InvokeTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        InvokeTriggerConstructorAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor, signature, exceptions);
+            super(mv, rule, access, name, descriptor, signature, exceptions);
             // ensure we don't transform calls before the super constructor is called
             latched = true;
         }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -24,15 +24,16 @@
 package org.jboss.jbossts.orchestration.agent.adapter;
 
 import org.objectweb.asm.*;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class LineCheckAdapter extends RuleCheckAdapter
 {
-    public LineCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, int targetLine)
+    public LineCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, int targetLine)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.targetLine = targetLine;
     }
 
@@ -45,7 +46,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new LineCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new LineCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -55,7 +56,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class LineCheckMethodAdapter extends MethodAdapter
+    private class LineCheckMethodAdapter extends RuleCheckMethodAdapter
     {
         private int access;
         private String name;
@@ -64,9 +65,9 @@
         private String[] exceptions;
         private boolean visited;
 
-        LineCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        LineCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -79,15 +80,18 @@
             if (!visited && (targetLine <= line)) {
                 // the relevant line occurs in the called method
                 visited = true;
+                setTriggerPoint();
+            }
+            super.visitLineNumber(line, start);
+        }
+
+        public void visitEnd()
+        {
+            if (checkBindings()) {
                 setVisitOk();
-                String name = targetClass + "." + targetMethodName + targetDescriptor;
-                if (targetLine >= 0) {
-                    name += targetLine;
-                }
             }
-            mv.visitLineNumber(line, start);
+            super.visitEnd();
         }
-
     }
 
     private int targetLine;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -52,9 +52,9 @@
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
             if (name.equals("<init>")) {
-                return new LineTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+                return new LineTriggerConstructorAdapter(mv, rule, access, name, desc, signature, exceptions);
             } else {
-                return new LineTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+                return new LineTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
             }
         }
         return mv;
@@ -64,7 +64,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class LineTriggerMethodAdapter extends GeneratorAdapter
+    private class LineTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         private int access;
         private String name;
@@ -75,9 +75,9 @@
         private Label endLabel;
         protected boolean unlatched;
 
-        LineTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        LineTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -110,7 +110,7 @@
                 } else {
                     super.push((Type)null);
                 }
-                super.loadArgArray();
+                doArgLoad();
                 super.invokeStatic(ruleType, method);
                 super.visitLabel(endLabel);
                 visitedLine = true;
@@ -190,9 +190,9 @@
 
     private class LineTriggerConstructorAdapter extends LineTriggerMethodAdapter
     {
-        LineTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        LineTriggerConstructorAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor, signature, exceptions);
+            super(mv, rule, access, name, descriptor, signature, exceptions);
             this.unlatched = false;
         }
 

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -24,6 +24,7 @@
 package org.jboss.jbossts.orchestration.agent.adapter;
 
 import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.rule.Rule;
 import org.objectweb.asm.*;
 
 /**
@@ -32,14 +33,16 @@
  */
 public class RuleAdapter extends ClassAdapter
 {
-    protected RuleAdapter(ClassVisitor cv, String targetClass, String targetMethod)
+    protected RuleAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod)
     {
         super(cv);
+        this.rule = rule;
         this.targetClass = targetClass;
         this.targetMethodName = TypeHelper.parseMethodName(targetMethod);
         this.targetDescriptor = TypeHelper.parseMethodDescriptor(targetMethod);
     }
 
+    protected Rule rule;
     protected String targetClass;
     protected String targetMethodName;
     protected String targetDescriptor;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -24,15 +24,16 @@
 package org.jboss.jbossts.orchestration.agent.adapter;
 
 import org.objectweb.asm.*;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class RuleCheckAdapter extends RuleAdapter
 {
-    protected RuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod)
+    protected RuleCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.visitOk = false;
     }
 

Added: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckMethodAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckMethodAdapter.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckMethodAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,134 @@
+package org.jboss.jbossts.orchestration.agent.adapter;
+
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.type.Type;
+import org.jboss.jbossts.orchestration.rule.binding.Bindings;
+import org.jboss.jbossts.orchestration.rule.binding.Binding;
+import org.jboss.jbossts.orchestration.agent.Transformer;
+
+import java.util.*;
+
+/**
+ * class which provides base functionality extended by all the location-specific method check adapters
+ */
+public class RuleCheckMethodAdapter extends RuleMethodAdapter {
+    RuleCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor)
+    {
+        super(mv, rule, access, name, descriptor);
+        this.access = access;
+        this.descriptor = descriptor;
+        this.triggerPoints = null;
+    }
+
+    protected void setTriggerPoint()
+    {
+        if (triggerPoints == null) {
+            triggerPoints = new ArrayList<Label>();
+        }
+        Label triggerLabel = new Label();
+        triggerPoints.add(triggerLabel);
+        this.visitLabel(triggerLabel);
+    }
+    boolean isTriggerPoint()
+    {
+        return (triggerPoints != null);
+    }
+
+    protected boolean checkBindings()
+    {
+        if (!isTriggerPoint()) {
+            return false;
+        }
+        
+        Bindings bindings = rule.getBindings();
+        Iterator<Binding> bindingIter = bindings.iterator();
+        List<String> parameterTypenames = Type.parseMethodDescriptor(descriptor, true);
+        int parameterCount = parameterTypenames.size() - 1; // allows for return type
+
+        // make sure all entries are valid
+        while (bindingIter.hasNext()) {
+            Binding binding = bindingIter.next();
+            if (binding.isRecipient()) {
+                if ((access & Opcodes.ACC_STATIC) != 0) {
+                    if (Transformer.isVerbose()) {
+                        System.out.println("RuleCheckMethodAdapter.checkBindings : found invalid recipient binding " + binding + " checking static method " + name + descriptor);
+                    }
+                    return false;
+                }
+            } else if (binding.isParam()) {
+                int idx = binding.getIndex();
+                if (idx > parameterCount) {
+                    // parameter out of range
+                    if (Transformer.isVerbose()) {
+                        System.out.println("RuleCheckMethodAdapter.checkBindings : found out of range parameter binding " + binding + " checking method " + name + descriptor);
+                    }
+                    return false;
+                } else {
+                    binding.setDescriptor(parameterTypenames.get(idx - 1));
+                }
+            } else if (binding.isReturn()) {
+                // at some point we will allow reference to the current return value so we need
+                // to be sure that the methdo has a non-void return type bit for now we do nothing
+            } else if (binding.isLocalVar()){
+                // make sure we have a local variable with the correct name
+                String localVarName = binding.getName().substring(1);
+                List<LocalVar> localVars = lookup(localVarName);
+
+                if (localVars == null || localVars.isEmpty()) {
+                    if (Transformer.isVerbose()) {
+                        System.out.println("RuleCheckMethodAdapter.checkBindings : unknown local variable binding " + binding + " checking method " + name + descriptor);
+                    }
+                    return false;
+                } else {
+                    String descriptor = null;
+                    int index = -1;
+                    Iterator<Label> labelIter = triggerPoints.iterator();
+                    while (labelIter.hasNext()) {
+                        int triggerPos = labelIter.next().getOffset();
+                        boolean found = false;
+                        Iterator<LocalVar> localVarIter = localVars.iterator();
+                        while (localVarIter.hasNext()) {
+                            LocalVar localVar = localVarIter.next();
+                            int start = localVar.start.getOffset();
+                            int end = localVar.end.getOffset();
+                            if (start <= triggerPos && triggerPos < end) {
+                                // only accept if the descriptor and index are the same or are not yet set
+                                if (descriptor == null && index == -1) {
+                                    descriptor = localVar.desc;
+                                    index = localVar.index;
+                                    found = true;
+                                } else if (descriptor.equals(localVar.desc) && index == localVar.index) {
+                                    found = true;
+                                }
+                                // terminate the loop here
+                                break;
+                            }
+                        }
+                        // if there was no variable for this trigger point then fail
+                        if (!found) {
+                            if (Transformer.isVerbose()) {
+                                System.out.println("RuleCheckMethodAdapter.checkBindings : invalid local variable binding " + binding + " checking method " + name + descriptor);
+                            }
+                            return false;
+                        }
+                    }
+                    // if we got here then we have a unique local var descriptor and index for
+                    // all trigger points so update the binding
+
+                    binding.setDescriptor(Type.parseFieldDescriptor(descriptor));
+                    binding.setLocalIndex(index);
+                }
+            }
+        }
+        // ok all local vars and params are accounted for so return true
+
+        return true;
+    }
+
+    private int access;
+    private String descriptor;
+    private List<Label> triggerPoints;
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleMethodAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleMethodAdapter.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleMethodAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,80 @@
+package org.jboss.jbossts.orchestration.agent.adapter;
+
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Label;
+import org.jboss.jbossts.orchestration.rule.Rule;
+
+import java.util.LinkedList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * generic rule method adapter which extends GeneratorAdpater and adds the ability to track in-scope
+ * local variables
+ */
+
+public class RuleMethodAdapter extends GeneratorAdapter {
+    public RuleMethodAdapter(final MethodVisitor mv, final Rule rule, final int access, final String name, final String desc) {
+        super(mv, access, name, desc);
+        this.name = name;
+        this.rule = rule;
+    }
+
+    public void visitLocalVariable(
+        final String name,
+        final String desc,
+        final String signature,
+        final Label start,
+        final Label end,
+        final int index)
+    {
+        // first, let the parent class do its stuff
+        super.visitLocalVariable(name, desc, signature, start, end, index);
+
+        // keep track of all local variables and their labels
+        LocalVar localVar = new LocalVar(name, desc, signature, start, end, index);
+        LinkedList<LocalVar> locals = localVarsByName.get(name);
+        if (locals == null) {
+            locals = new LinkedList<LocalVar>();
+            localVarsByName.put(name, locals);
+        }
+        locals.addFirst(localVar);
+    }
+
+    protected List<LocalVar> lookup(String name)
+    {
+        return localVarsByName.get(name);
+    }
+
+    /**
+     * a hashmap mapping local variable names to all in-scope variables with that name. the list of local
+     * variables operates like a stack with the current in-scope binding at the top and each successive
+     * entry representing an outer binding shadowed by its predecessors
+     */
+
+    HashMap<String, LinkedList<LocalVar>> localVarsByName = new HashMap<String, LinkedList<LocalVar>>();
+
+    protected static class LocalVar
+    {
+        public String name;
+        public String desc;
+        public String signature;
+        public Label start;
+        public Label end;
+        public int index;
+
+        public LocalVar(String name, String desc, String signature, Label start, Label end, int index)
+        {
+            this.name = name;
+            this.desc = desc;
+            this.signature = signature;
+            this.start = start;
+            this.end = end;
+            this.index = index;
+        }
+    }
+
+    protected Rule rule;
+    protected String name;
+}

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -33,7 +33,7 @@
 {
     protected RuleTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.rule = rule;
     }
 

Added: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerMethodAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerMethodAdapter.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerMethodAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,123 @@
+package org.jboss.jbossts.orchestration.agent.adapter;
+
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.binding.Bindings;
+import org.jboss.jbossts.orchestration.rule.binding.Binding;
+
+import java.util.*;
+
+/**
+ * class which provides base functionality extended by all the location-specific method trigger adapters
+ */
+public class RuleTriggerMethodAdapter extends RuleMethodAdapter
+{
+    RuleTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor)
+    {
+        super(mv, rule, access, name, descriptor);
+        this.access = access;
+        this.descriptor = descriptor;
+        this.paramBindings = new ArrayList<Binding>();
+        this.returnType = Type.getReturnType(descriptor);
+        this.argumentTypes = Type.getArgumentTypes(descriptor);
+        this.bindingsDone = false;
+    }
+
+    private void setBindingIndices()
+    {
+        Bindings bindings = rule.getBindings();
+        Iterator<Binding> iterator = bindings.iterator();
+
+        // make sure all entries are valid
+        while (iterator.hasNext()) {
+            Binding binding = iterator.next();
+            if (binding.isParam()) {
+                paramBindings.add(binding);
+            } else if (binding.isReturn()) {
+                // at some point we will allow reference to the current return value so we need
+                // to be sure that the method has a non-void return type bit for now we do nothing
+            } else if (binding.isLocalVar()){
+                paramBindings.add(binding);
+            }
+        }
+        // we don't have to do this but it makes debgging easier
+        
+        if (true) {
+            // ok now sort the paramBindings for later use
+
+            Comparator<Binding> comparator = new Comparator<Binding>() {
+                public int compare(Binding b1, Binding b2)
+                {
+                    if (b1.isParam()) {
+                        if (b2.isParam()) {
+                            int i1 = b1.getIndex();
+                            int i2 = b2.getIndex();
+                            return (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+                        } else {
+                            return -1;
+                        }
+                    } else {
+                        if (b2.isParam()) {
+                            return 1;
+                        } else {
+                            int i1 = b1.getLocalIndex();
+                            int i2 = b2.getLocalIndex();
+                            return (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+                        }
+                    }
+                }
+            };
+
+            Collections.sort(paramBindings, comparator);
+        }
+
+        // now give each binding a unique index in the object array
+        int n = paramBindings.size();
+        for (int i = 0; i < n; i++) {
+            paramBindings.get(i).setObjectArrayIndex(i);
+        }
+    }
+
+    public void doArgLoad()
+    {
+        if (!bindingsDone) {
+            setBindingIndices();
+            bindingsDone = true;
+        }
+        
+        if (paramBindings.size() ==  0) {
+            super.push((org.objectweb.asm.Type)null);
+            return;
+        }
+
+        int arraySize = paramBindings.size();
+
+        push(arraySize);
+        Type objectType = Type.getType(Object.class);
+        newArray(objectType);
+
+        for (int i = 0; i < arraySize; i++) {
+            Binding binding = paramBindings.get(i);
+            dup();
+            push(i);
+            if (binding.isParam()) {
+                int idx = binding.getIndex() - 1;
+                loadArg(idx);
+                box(argumentTypes[idx]);
+            } else {
+                int idx = binding.getLocalIndex();
+                loadLocal(idx);
+                box(getLocalType(idx));
+            }
+            arrayStore(objectType);
+        }
+    }
+
+    private int access;
+    private String descriptor;
+    private Type returnType;
+    private Type[] argumentTypes;
+    private List<Binding> paramBindings;
+    private boolean bindingsDone;
+}

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -25,15 +25,19 @@
 
 import org.objectweb.asm.*;
 import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
+import java.util.List;
+import java.util.ArrayList;
+
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class SynchronizeCheckAdapter extends RuleCheckAdapter
 {
-     public SynchronizeCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, int count)
+     public SynchronizeCheckAdapter(ClassVisitor cv, Rule rule,  String targetClass, String targetMethod, int count)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.count = count;
         this.visitedCount = 0;
     }
@@ -47,7 +51,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new SynchronizeCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new SynchronizeCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -57,7 +61,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class SynchronizeCheckMethodAdapter extends MethodAdapter
+    private class SynchronizeCheckMethodAdapter extends RuleCheckMethodAdapter
     {
         private int access;
         private String name;
@@ -66,9 +70,9 @@
         private String[] exceptions;
         private boolean visited;
 
-        SynchronizeCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        SynchronizeCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -84,11 +88,19 @@
                 visitedCount++;
                 if (visitedCount == count) {
                     // and we have enough occurences to match the count
-                    setVisitOk();
+                    setTriggerPoint();
                 }
             }
             super.visitInsn(opcode);
         }
+
+        public void visitEnd()
+        {
+            if (checkBindings()) {
+                setVisitOk();
+            }
+            super.visitEnd();
+        }
    }
 
     private int count;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -56,7 +56,7 @@
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         // we can use the same adapter for methods and constructors
         if (matchTargetMethod(name, desc)) {
-            return new SynchronizeTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new SynchronizeTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
         return mv;
     }
@@ -65,7 +65,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class SynchronizeTriggerMethodAdapter extends GeneratorAdapter
+    private class SynchronizeTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         private int access;
         private String name;
@@ -75,9 +75,9 @@
         private Label startLabel;
         private Label endLabel;
 
-        SynchronizeTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        SynchronizeTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -117,7 +117,7 @@
                     } else {
                         super.push((Type)null);
                     }
-                    super.loadArgArray();
+                    doArgLoad();
                     super.invokeStatic(ruleType, method);
                     super.visitLabel(endLabel);
                 }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowCheckAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowCheckAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -25,15 +25,19 @@
 
 import org.objectweb.asm.*;
 import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.rule.Rule;
 
+import java.util.List;
+import java.util.ArrayList;
+
 /**
  * asm Adapter class used to check that the target method for a rule exists in a class
  */
 public class ThrowCheckAdapter extends RuleCheckAdapter
 {
-     public ThrowCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, String exceptionClass, int count)
+     public ThrowCheckAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, String exceptionClass, int count)
     {
-        super(cv, targetClass, targetMethod);
+        super(cv, rule, targetClass, targetMethod);
         this.exceptionClass = exceptionClass;
         this.count = count;
         this.visitedCount = 0;
@@ -48,7 +52,7 @@
     {
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
-            return new ThrowCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+            return new ThrowCheckMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
         }
 
         return mv;
@@ -58,7 +62,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class ThrowCheckMethodAdapter extends MethodAdapter
+    private class ThrowCheckMethodAdapter extends RuleCheckMethodAdapter
     {
         private int access;
         private String name;
@@ -67,9 +71,9 @@
         private String[] exceptions;
         private boolean visited;
 
-        ThrowCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        ThrowCheckMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -86,13 +90,21 @@
                     visitedCount++;
                     if (visitedCount == count) {
                         // and we have enough occurences to match the count
-                        setVisitOk();
+                        setTriggerPoint();
                     }
                 }
             }
 
-            mv.visitInsn(opcode);
+            super.visitInsn(opcode);
         }
+
+        public void visitEnd()
+        {
+            if (checkBindings()) {
+                setVisitOk();
+            }
+            super.visitEnd();
+        }
     }
 
     private String exceptionClass;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowTriggerAdapter.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowTriggerAdapter.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -29,7 +29,12 @@
 import org.objectweb.asm.*;
 import org.objectweb.asm.commons.GeneratorAdapter;
 import org.objectweb.asm.commons.Method;
+import com.sun.org.apache.bcel.internal.generic.MONITOREXIT;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.LinkedList;
+
 /**
  * asm Adapter class used to add a rule event trigger call to a method of some given class
  */
@@ -53,9 +58,9 @@
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
         if (matchTargetMethod(name, desc)) {
             if (name.equals("<init>")) {
-                return new ThrowTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+                return new ThrowTriggerConstructorAdapter(mv, rule, access, name, desc, signature, exceptions);
             } else {
-                return new ThrowTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+                return new ThrowTriggerMethodAdapter(mv, rule, access, name, desc, signature, exceptions);
             }
         }
         return mv;
@@ -65,7 +70,7 @@
      * a method visitor used to add a rule event trigger call to a method
      */
 
-    private class ThrowTriggerMethodAdapter extends GeneratorAdapter
+    private class ThrowTriggerMethodAdapter extends RuleTriggerMethodAdapter
     {
         /**
          * flag used by subclass to avoid inserting trigger until after super constructor has been called
@@ -79,9 +84,9 @@
         private Label startLabel;
         private Label endLabel;
 
-        ThrowTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        ThrowTriggerMethodAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor);
+            super(mv, rule, access, name, descriptor);
             this.access = access;
             this.name = name;
             this.descriptor = descriptor;
@@ -95,6 +100,11 @@
 
         public void visitInsn(final int opcode) {
             if (opcode == Opcodes.ATHROW) {
+                // TODO -- this fails if exceptions or throws can occur inside monitor blocks
+                // TODO -- because they get caught and rethrown at the end of the monitor block
+                // TODO -- which means the wrong throws get counted
+                // TODO -- so we need to track throw catch blocks and monitor enter/exits properly
+
                 // ok, we have hit a throw -- for now we just count any throw
                 // later we will try to match the exception class
                 if (visitedCount < count) {
@@ -118,7 +128,7 @@
                         } else {
                             super.push((Type)null);
                         }
-                        super.loadArgArray();
+                        doArgLoad();
                         super.invokeStatic(ruleType, method);
                         super.visitLabel(endLabel);
                     }
@@ -200,9 +210,9 @@
 
     private class ThrowTriggerConstructorAdapter extends ThrowTriggerMethodAdapter
     {
-        ThrowTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        ThrowTriggerConstructorAdapter(MethodVisitor mv, Rule rule, int access, String name, String descriptor, String signature, String[] exceptions)
         {
-            super(mv, access, name, descriptor, signature, exceptions);
+            super(mv, rule, access, name, descriptor, signature, exceptions);
             // ensure we don't transform calls before the super constructor is called
             latched = true;
         }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -75,7 +75,7 @@
             Action action = new Action(rule, actionTree);
             return action;
         } catch (Exception e) {
-            throw new ParseException("org.jboss.jbossts.orchestration.rule.Action : error parsing action " + text);
+            throw new ParseException("org.jboss.jbossts.orchestration.rule.Action : error parsing action\n" + text);
         }
     }
     protected Action(Rule rule, ParseNode actionTree) throws TypeException
@@ -85,6 +85,11 @@
             this.action = new ArrayList<Expression>();
         } else {
             this.action = ExpressionHelper.createExpressionList(rule, this.getBindings(), actionTree, Type.VOID);
+            for (Expression expr : action) {
+                if (!expr.bind()) {
+                    throw new TypeException("ExpressionHelper.createExpression : unknown reference in expression" + expr.getPos());
+                }
+            }
         }
     }
 

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -68,7 +68,7 @@
             Condition condition = new Condition(rule, conditionTree);
             return condition;
         } catch (Exception e) {
-            throw new ParseException("org.jboss.jbossts.orchestration.rule.Condition : error parsing condition " + text, e);
+            throw new ParseException("org.jboss.jbossts.orchestration.rule.Condition : error parsing condition\n" + text, e);
         }
     }
 
@@ -77,7 +77,10 @@
     {
         super(rule);
         int tag = conditionTree.getTag();
-        this.condition = ExpressionHelper.createExpression(rule, rule.getBindings(), conditionTree, Type.BOOLEAN);
+        condition = ExpressionHelper.createExpression(rule, rule.getBindings(), conditionTree, Type.BOOLEAN);
+        if (!condition.bind()) {
+            throw new TypeException("ExpressionHelper.createExpression : unknown reference in expression" + condition.getPos());
+        }
     }
     
     protected Condition(Rule rule)

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -80,7 +80,7 @@
             Event event = new Event(rule, eventTree);
             return event;
         } catch (Exception e) {
-            throw new ParseException("org.jboss.jbossts.orchestration.rule.Event : error parsing event " + text, e);
+            throw new ParseException("org.jboss.jbossts.orchestration.rule.Event : error parsing event\n" + text, e);
         }
     }
 
@@ -200,6 +200,10 @@
         Expression expr;
 
         expr = ExpressionHelper.createExpression(rule, bindings, exprTree, binding.getType());
+        if (!expr.bind()) {
+            throw new TypeException("ExpressionHelper.createExpression : unknown reference in expression" + expr.getPos());
+        }
+
         String name = binding.getName();
 
         if (bindings.lookup(name) != null) {

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -157,7 +157,7 @@
                 Symbol parse = (debugParse ? parser.debug_parse() : parser.parse());
                 ruleTree = (ParseNode) parse.value;
             } catch (Exception e) {
-                throw new ParseException("org.jboss.jbossts.orchestration.rule.Rule : error parsing rule " + ruleSpec, e);
+                throw new ParseException("org.jboss.jbossts.orchestration.rule.Rule : error parsing rule\n" + ruleSpec, e);
             }
             ParseNode eventTree = (ParseNode)ruleTree.getChild(0);
             ParseNode conditionTree = (ParseNode)ruleTree.getChild(1);
@@ -295,10 +295,11 @@
 
         typeGroup.resolveTypes();
 
-        // use the descriptor to derive the method argument types and install bindings for them
-        // in the bindings list
+        // use the descriptor to derive the method argument types and type any bindings for them
+        // that are located in the bindings list
 
-        installParameters((triggerAccess & Opcodes.ACC_STATIC) != 0, triggerClass, triggerDescriptor);
+        installParameters((triggerAccess & Opcodes.ACC_STATIC) != 0, triggerClass);
+
         event.typeCheck(Type.VOID);
         condition.typeCheck(Type.Z);
         action.typeCheck(Type.VOID);
@@ -329,51 +330,48 @@
         return Transformer.isCompileToBytecode();
     }
 
-    private void installParameters(boolean isStatic, String className, String descriptor)
+    private void installParameters(boolean isStatic, String className)
             throws TypeException
     {
-        List<Binding> parameterBindings = new ArrayList<Binding>();
         Type type;
         // add a binding for the rule so we can call builtin static methods
         type = typeGroup.create(helperClass.getCanonicalName());
-        // type = typeGroup.create("org.jboss.jbossts.orchestration.rule.helper.Helper");
-        Binding ruleBinding = new Binding(this, "$", type);
-        parameterBindings.add(ruleBinding);
+        Binding ruleBinding = bindings.lookup("$$");
+        if (ruleBinding != null) {
+            ruleBinding.setType(type);
+        } else {
+            bindings.append(new Binding(this, "$$", type));
+        }
 
         if (!isStatic) {
-            type = typeGroup.create(className);
-            if (type.isUndefined()) {
-                throw new TypeException("Rule.installParameters : Rule " + name + " unable to load class " + className);
+            Binding recipientBinding = bindings.lookup("$0");
+            if (recipientBinding != null) {
+                type = typeGroup.create(className);
+                if (type.isUndefined()) {
+                    throw new TypeException("Rule.installParameters : Rule " + name + " unable to load class " + className);
+                }
+                recipientBinding.setType(type);
             }
-            Binding binding =  new Binding(this, "0", type);
-            parameterBindings.add(binding);
         }
-        List<String> parameterTypenames = Type.parseDescriptor(descriptor, true);
-        int paramIdx = 1;
-        int last = parameterTypenames.size();
-        if (parameterTypenames != null) {
-            for (String typeName : parameterTypenames) {
+
+        Iterator<Binding> iterator = bindings.iterator();
+
+        while (iterator.hasNext()) {
+            Binding binding = iterator.next();
+            if (binding.isParam() || binding.isLocalVar()) {
+                String typeName = binding.getDescriptor();
                 String[] typeAndArrayBounds = typeName.split("\\[");
                 Type baseType = typeGroup.create(typeAndArrayBounds[0]);
                 Type paramType = baseType;
-                Binding binding;
                 if (baseType.isUndefined()) {
                     throw new TypeException("Rule.installParameters : Rule " + name + " unable to load class " + baseType);
                 }
                 for (int i = 1; i < typeAndArrayBounds.length ; i++) {
-                    paramType = typeGroup.createArray(baseType);
+                    paramType = typeGroup.createArray(paramType);
                 }
-                if (paramIdx == last) {
-                    // we also add a special binding to allow us to identify the return type
-                    binding = new Binding(this, "$!", paramType);
-                } else {
-                    binding = new Binding(this, Integer.toString(paramIdx++), paramType);
-                }
-                parameterBindings.add(binding);
+                binding.setType(paramType);
             }
         }
-
-        bindings.addBindings(parameterBindings);
     }
 
     /**

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -265,7 +265,7 @@
             throws CompileException
     {
         assert toType == Type.STRING;
-        if (fromType.isObject()) {
+        if (fromType.isObject() || fromType.isArray()) {
             // use the toString method
             mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;");
         } else if (fromType == Type.Z) {
@@ -449,7 +449,7 @@
         } else {
             // this happens when we downcast a bound variable from Object to the variable's type
             assert fromType.isAssignableFrom(toType);
-            mv.visitTypeInsn(Opcodes.CHECKCAST, toType.getInternalName());
+            mv.visitTypeInsn(Opcodes.CHECKCAST, toType.getInternalName(false, true));
         }
     }
 

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -60,15 +60,25 @@
         this.name = name;
         this.type = (type != null ? type : Type.UNDEFINED);
         this.value = value;
-        if (name.equals("$")) {
-            index = -1;
-        } else if (name.matches("[0-9].*")) {
-            index = Integer.valueOf(name);
+        // ok, check the name to see what type of binding we have
+        if (name.matches("\\$[0-9].*")) {
+            // $NNN references the method target or a parameter from 0 upwards
+            index = Integer.valueOf(name.substring(1));
+        } else if (name.equals("$$")) {
+            // $$ references the helper implicitly associated with a builtin call
+            index = HELPER;
         } else if (name.equals("$!")) {
-            index = -2;
+            // $! refers to the current return value for the triggger method and is only valid when
+            // the rule is triggered AT EXIT
+            index = RETURN;
+        } else if (name.matches("\\$[A-Za-z].*")) {
+           // $AAAAA refers  to a local variable in the trigger method
+            index = LOCALVAR;
         } else {
-            index = -3;
+            // anything else must be a variable introduced in the BINDS clause
+            index = BINDVAR;
         }
+        this.objectArrayIndex = 0;
     }
 
     public Type typeCheck(Type expected)
@@ -92,7 +102,7 @@
 
     public Object interpret(HelperAdapter helper) throws ExecuteException
     {
-        if (isVar()) {
+        if (isBindVar()) {
             Object result = value.interpret(helper);
             helper.bindVariable(getName(), result);
             return result;
@@ -102,7 +112,7 @@
 
     public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
     {
-        if (isVar()) {
+        if (isBindVar()) {
             int currentStack = currentStackHeights.stackCount;
 
             // push the current helper instance i.e. this -- adds 1 to stack height
@@ -158,44 +168,78 @@
 
     public void setType(Type type)
     {
+        this.type = type;
     }
 
-    public boolean isHelper()
+    public int getObjectArrayIndex()
     {
-        return index == -1;
+        return objectArrayIndex;
     }
 
-    public boolean isRecipient()
+    public void setObjectArrayIndex(int objectArrayIndex)
     {
-        return index == 0;
+        this.objectArrayIndex = objectArrayIndex;
     }
 
+    public int getLocalIndex()
+    {
+        return localIndex;
+    }
+
+    public void setLocalIndex(int localIndex)
+    {
+        this.localIndex = localIndex;
+    }
+
     public boolean isParam()
     {
         return index > 0;
     }
 
+    public boolean isRecipient()
+    {
+        return index == 0;
+    }
+
+    public boolean isHelper()
+    {
+        return index == HELPER;
+    }
+
     public boolean isReturn()
     {
-        return index == -2;
+        return index == RETURN;
     }
 
-    public boolean isVar()
+    public boolean isLocalVar()
     {
-        return index < -2;
+        return index == LOCALVAR;
     }
 
+    public boolean isBindVar()
+    {
+        return index <= BINDVAR;
+    }
+
     public int getIndex()
     {
         return index;
     }
 
+    public String getDescriptor() {
+        return descriptor;
+    }
+
+    public void setDescriptor(String desc) {
+        this.descriptor = desc;
+    }
+
     public void writeTo(StringWriter stringWriter)
     {
         if (isHelper()) {
-            stringWriter.write("$$");
+            stringWriter.write(name);
         } else if (isParam() || isRecipient()) {
-            stringWriter.write("$" + name);
+            stringWriter.write(name);
             if (type != null && (type.isDefined() || type.isObject())) {
                 stringWriter.write(" : ");
                 stringWriter.write(type.getName());
@@ -213,8 +257,22 @@
         }
     }
 
+    // special index values for non-positional parameters
+
+    private final static int HELPER = -1;
+    private final static int RETURN = -2;
+    private final static int LOCALVAR = -3;
+    private final static int BINDVAR = -4;
+
     private String name;
+    private String descriptor; // supplied when the binding is for a local var
     private Type type;
     private Expression value;
+    // the position index of the trigger method recipient or a trigger method parameter or one of the special index
+    // values for other types  of parameters.
     private int index;
+    // the offset into the trigger method Object array of the initial value for this parameter
+    private int objectArrayIndex;
+    // the offset into the stack at which a local var is located
+    private int localIndex;
 }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -301,21 +301,24 @@
         mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
         mv.visitInsn(POP);
         mv.visitJumpInsn(GOTO, l4);
-        // else if (binding.isParam())
+        // else if (binding.isParam() || binding.isLocalVar())
         mv.visitLabel(l5);
+        Label l6 = new Label();
         mv.visitVarInsn(ALOAD, 5);
         mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/binding/Binding", "isParam", "()Z");
-        mv.visitJumpInsn(IFEQ, l4);
+        mv.visitJumpInsn(IFNE, l6); // skip to then if true or drop throuogh to || branch if false
+        mv.visitVarInsn(ALOAD, 5);
+        mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/binding/Binding", "isLocalVar", "()Z");
+        mv.visitJumpInsn(IFEQ, l4); // bypass this branch
+        mv.visitLabel(l6);
         // then
-        // bindingMap.put(name, args[binding.getIndex() - 1]);
+        // bindingMap.put(name, args[binding.getObjectArrayIndex]);
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, compiledHelperName, "bindingMap", "Ljava/util/HashMap;");
         mv.visitVarInsn(ALOAD, 6);
         mv.visitVarInsn(ALOAD, 3);
         mv.visitVarInsn(ALOAD, 5);
-        mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/binding/Binding", "getIndex", "()I");
-        mv.visitInsn(ICONST_1);
-        mv.visitInsn(ISUB);
+        mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/binding/Binding", "getObjectArrayIndex", "()I");
         mv.visitInsn(AALOAD);
         mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
         mv.visitInsn(POP);

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -176,6 +176,7 @@
                 mv.visitInsn(Opcodes.DALOAD);
                 expected = 2;
             }
+            currentStackHeights.addStackCount(-2);
             if (iterator.hasNext()) {
                 assert valueType.isArray();
                 valueType =valueType.getBaseType();

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -24,6 +24,7 @@
 package org.jboss.jbossts.orchestration.rule.expression;
 
 import org.jboss.jbossts.orchestration.rule.binding.Binding;
+import org.jboss.jbossts.orchestration.rule.binding.Bindings;
 import org.jboss.jbossts.orchestration.rule.type.Type;
 import org.jboss.jbossts.orchestration.rule.exception.TypeException;
 import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
@@ -54,10 +55,10 @@
     public DollarExpression(Rule rule, Type type, ParseNode token, int index)
     {
         super(rule, type, token);
-        if (index < 0) {
-            name = "$";
+        if (index == -1) {
+            name = "$$";
         } else {
-            name = Integer.toString(index);
+            name = "$" + Integer.toString(index);
         }
         this.index = index;
     }
@@ -66,7 +67,7 @@
     {
         super(rule, type, token);
         this.index = -2;
-        this.name = name;
+        this.name = "$" + name;
     }
 
     /**
@@ -79,26 +80,29 @@
      */
 
     public boolean bind() {
-        if (index < 0) {
-            System.err.println("DollarExpression.bind : invalid bound parameter $" + name + getPos());
-            return false;
-        } else {
-            // reference to positional parameter -- name must be a non-signed integer
-            // we will do type checking later
-            return true;
+        // ensure that there is a binding in the bindings set for this parameter
+        // we will type check the binding later
+
+        Bindings bindings = getBindings();
+        Binding binding;
+
+        binding = bindings.lookup(name);
+
+        if (binding == null) {
+            binding = new Binding(rule, name, null);
+            bindings.append(binding);
         }
+
+        return true;
     }
 
     public Type typeCheck(Type expected) throws TypeException {
         // ensure there is a parameter with the relevant name in the bindings
         Binding binding;
-        if (index >= 0) {
-            binding = getBindings().lookup(Integer.toString(index));
-        } else {
-            binding = getBindings().lookup(name);
-        }
+        binding = getBindings().lookup(name);
+
         if (binding == null) {
-            throw new TypeException("DollarExpression.typeCheck : invalid bound parameter $" + name + getPos());
+            throw new TypeException("DollarExpression.typeCheck : invalid bound parameter " + name + getPos());
         }
         type = binding.getType();
         if (Type.dereference(expected).isDefined() && !expected.isAssignableFrom(type)) {
@@ -152,7 +156,7 @@
     }
 
     public void writeTo(StringWriter stringWriter) {
-        stringWriter.write("$" + name);
+        stringWriter.write(name);
     }
 
     private String name;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -211,9 +211,12 @@
             // we already know this is an invalid type so notify an error and return null
             throw new TypeException("ExpressionHelper.createExpression : invalid expression type " + exprType.getName() + " expecting " + targetType.getName() + exprTree.getPos());
         }
+        // don't do this here as it gets called recursively -- need to do it in Binding, Condition and Action
+        /*
         if (!expr.bind()) {
             throw new TypeException("ExpressionHelper.createExpression : unknown reference in expression" + exprTree.getPos());
         }
+        */
 
         return expr;
     }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -51,7 +51,7 @@
         this.owner = owner;
         this.pathList = pathList;
         this.ownerType = null;
-        this.indirectStatic = true;
+        this.indirectStatic = false;
     }
 
     /**

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -331,10 +331,10 @@
         buffer.append("(");
         int nParams = paramTypes.size();
         for (int i = 0; i < nParams; i++) {
-            buffer.append(paramTypes.get(i).getInternalName(true));
+            buffer.append(paramTypes.get(i).getInternalName(true, true));
         }
         buffer.append(")");
-        buffer.append(type.getInternalName(true));
+        buffer.append(type.getInternalName(true, true));
         return buffer.toString();
     }
     

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -311,7 +311,7 @@
         buffer.append("(");
         int nParams = paramTypes.size();
         for (int i = 0; i < nParams; i++) {
-            buffer.append(paramTypes.get(i).getInternalName(true));
+            buffer.append(paramTypes.get(i).getInternalName(true, true));
         }
         buffer.append(")V");
         return buffer.toString();

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -88,8 +88,8 @@
             } else if (binding.isRecipient()) {
                 bindingMap.put(name, recipient);
                 bindingTypeMap.put(name, type);
-            } else if (binding.isParam()) {
-                bindingMap.put(name, args[binding.getIndex() - 1]);
+            } else if (binding.isParam() || binding.isLocalVar()) {
+                bindingMap.put(name, args[binding.getObjectArrayIndex()]);
                 bindingTypeMap.put(name, type);
             }
         }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -106,7 +106,7 @@
      */
     public String getInternalName()
     {
-        return getInternalName(false);
+        return getInternalName(false, true);
     }
 
     /**
@@ -114,17 +114,20 @@
      * defined types, defined array types or primitive types
      * @return the type name
      */
-    public String getInternalName(boolean forDescriptor)
+    public String getInternalName(boolean forDescriptor, boolean slashSeparate)
     {
         if (isArray()) {
-            return "[" + baseType.getInternalName(forDescriptor);
+            // the base name has to be L...; bracketed
+            return "[" + baseType.getInternalName(true, slashSeparate);
         } else if (isPrimitive()) {
             return internalNames.get(typeName);
         } else if (isVoid()) {
             return internalNames.get(typeName);
         } else {
             String name = aliasFor.getTargetClass().getCanonicalName();
-            name = name.replaceAll("\\.", "/");
+            if (slashSeparate) {
+                name = name.replaceAll("\\.", "/");
+            }
             if (forDescriptor) {
                 name = "L" + name + ";";
             }
@@ -582,7 +585,7 @@
         }
     }
 
-    public static List<String> parseDescriptor(String descriptor, boolean includeReturnType)
+    public static List<String> parseMethodDescriptor(String descriptor, boolean includeReturnType)
     {
         List<String> argTypes = new ArrayList<String>();
         int length = descriptor.length();
@@ -720,6 +723,82 @@
         return (arrayDepth == 0 ? argTypes : null);
     }
 
+    public static String parseFieldDescriptor(String descriptor)
+    {
+        int length = descriptor.length();
+        int idx = 0;
+        int arrayDepth = 0;
+        while (idx < length) {
+            char c = descriptor.charAt(idx);
+            switch(descriptor.charAt(idx))
+            {
+                case 'Z':
+                {
+                    String baseType = "boolean";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'B':
+                {
+                    String baseType = "byte";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'S':
+                {
+                    String baseType = "short";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'C':
+                {
+                    String baseType = "char";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'I':
+                {
+                    String baseType = "int";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'J':
+                {
+                    String baseType = "long";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'F':
+                {
+                    String baseType = "float";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'D':
+                {
+                    String baseType = "double";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'V':
+                {
+                    String baseType = "void";
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case 'L':
+                {
+                    int endIdx = descriptor.indexOf(';', idx);
+                    if (endIdx < 0) {
+                        return null;
+                    }
+                    String baseType = descriptor.substring(idx+1, endIdx).replaceAll("/", ".");
+                    return(fixArrayType(baseType, arrayDepth));
+                }
+                case '[':
+                {
+                    arrayDepth++;
+                    idx++;
+                }
+                break;
+                default:
+                    return null;
+            }
+        }
+        return null;
+    }
+
     public static String fixArrayType(String baseType, int dimension)
     {
         String result = baseType;

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeGroup.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeGroup.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeGroup.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -210,7 +210,9 @@
             Class arrayClazz = null;
             if (baseType.isPrimitive() || baseType.isDefined()) {
                 try {
-                    arrayClazz = loader.loadClass("[" + baseType.getInternalName());
+                    // aaarrghh array base type names use dots not slashes bt still need  L...; bracketing
+                    String internalName ="[" + baseType.getInternalName(true, false);
+                    arrayClazz = loader.loadClass(internalName);
                 } catch (ClassNotFoundException e) {
                     // ignore
                 }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java	2009-04-02 10:02:30 UTC (rev 25915)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -129,43 +129,43 @@
                 while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
                     idx++;
                     if (idx == len) {
-                        throw new ParseException("Rule contains no text : " + script);
+                        throw new ParseException("Rule contains no text :\n" + script);
                     }
                 }
                 if (lines[idx].startsWith("RULE ")) {
                     ruleName = lines[idx].substring(5).trim();
                     idx++;
                 } else {
-                    throw new ParseException("Rule should start with RULE : " + lines[idx]);
+                    throw new ParseException("Rule should start with RULE :\n" + lines[idx]);
                 }
                 while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
                     idx++;
                     if (idx == len) {
-                        throw new ParseException("Rule does not specify CLASS : " + script);
+                        throw new ParseException("Rule does not specify CLASS :\n" + script);
                     }
                 }
                 if (lines[idx].startsWith("CLASS ")) {
                     targetClassName = lines[idx].substring(6).trim();
                     idx++;
                 } else {
-                    throw new ParseException("CLASS should follow RULE : " + lines[idx]) ;
+                    throw new ParseException("CLASS should follow RULE :\n" + lines[idx]) ;
                 }
                 while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
                     idx++;
                     if (idx == len) {
-                        throw new ParseException("Rule does not specify METHOD : " + script);
+                        throw new ParseException("Rule does not specify METHOD\n: " + script);
                     }
                 }
                 if (lines[idx].startsWith("METHOD ")) {
                     targetMethodName = lines[idx].substring(7).trim();
                     idx++;
                 } else {
-                    throw new ParseException("METHOD should follow CLASS : " + lines[idx]) ;
+                    throw new ParseException("METHOD should follow CLASS :\n" + lines[idx]) ;
                 }
                 while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
                     idx++;
                     if (idx == len) {
-                        throw new ParseException("Rule is incomplete : " + script);
+                        throw new ParseException("Rule is incomplete :\n" + script);
                     }
                 }
                 if (lines[idx].startsWith("HELPER ")) {
@@ -174,7 +174,7 @@
                     while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
                         idx++;
                         if (idx == len) {
-                            throw new ParseException("Rule is incomplete : " + script);
+                            throw new ParseException("Rule is incomplete :\n" + script);
                         }
                     }
                 }
@@ -183,7 +183,7 @@
                     String parameters = LocationType.parameterText(lines[idx]);
                     targetLocation = Location.create(locationType, parameters);
                     if (targetLocation == null) {
-                        throw new ParseException("Invalid parameters for location specifier " + locationType.specifierText() + " in rule " + ruleName);
+                        throw new ParseException("Invalid parameters for location specifier\n" + locationType.specifierText() + " in rule " + ruleName);
                     }
                     idx++;
                 }
@@ -198,7 +198,7 @@
                     sepr = "\n";
                 }
                 if (idx == len) {
-                    throw new ParseException("Missing ENDRULE : " + script);
+                    throw new ParseException("Missing ENDRULE :\n" + script);
                 }
 
                 Class targetHelperClass = null;

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestCall.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestCall.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestCall.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,50 @@
+RULE test call getCounter trigger
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT CALL getCounter
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("CALL getCounter triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test call getCounter trigger 2
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT CALL getCounter 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("CALL getCounter 2 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test call getCounter trigger 3
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT CALL getCounter 3
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("CALL getCounter 3 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test call setCounter trigger
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT CALL setCounter
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("CALL setCounter triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test call setCounter trigger 2
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT CALL setCounter 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("CALL setCounter 2 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestEntry.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestEntry.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestEntry.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,29 @@
+RULE test entry trigger for constructor
+CLASS TestEntryExitAuxiliarySub
+METHOD <init>(Test)
+AT ENTRY
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $1
+IF TRUE
+DO test.log("ENTRY triggered in constructor")
+ENDRULE
+
+RULE test entry trigger for subclass method
+CLASS TestEntryExitAuxiliarySub
+METHOD testMethod()
+AT ENTRY
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("ENTRY triggered in TestEntryExitAuxiliarySub.testMethod")
+ENDRULE
+
+RULE test entry trigger for superclass method
+CLASS TestEntryExitAuxiliary
+METHOD testMethod()
+AT ENTRY
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("ENTRY triggered in TestEntryExitAuxiliary.testMethod")
+ENDRULE

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestExit.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestExit.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestExit.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,29 @@
+RULE test exit trigger for constructor
+CLASS TestEntryExitAuxiliarySub
+METHOD <init>(Test)
+AT EXIT
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $1
+IF TRUE
+DO test.log("EXIT triggered in constructor")
+ENDRULE
+
+RULE test exit trigger for subclass method
+CLASS TestEntryExitAuxiliarySub
+METHOD testMethod()
+AT EXIT
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("EXIT triggered in TestEntryExitAuxiliarySub.testMethod")
+ENDRULE
+
+RULE test exit trigger for superclass method
+CLASS TestEntryExitAuxiliary
+METHOD testMethod()
+AT EXIT
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("EXIT triggered in TestEntryExitAuxiliary.testMethod")
+ENDRULE

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestReadWrite.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestReadWrite.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestReadWrite.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,39 @@
+RULE test at read trigger
+CLASS TestReadWriteAuxiliary
+METHOD testMethod()
+AT READ counter
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("AT READ 1 triggered in TestReadWriteAuxiliary.testMethod : counter == " + $0.counter)
+ENDRULE
+
+RULE test after read trigger 2
+CLASS TestReadWriteAuxiliary
+METHOD testMethod()
+AFTER READ counter 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("AFTER READ 2 triggered in TestReadWriteAuxiliary.testMethod : counter == " + $0.counter)
+ENDRULE
+
+RULE test at write trigger
+CLASS TestReadWriteAuxiliary
+METHOD testMethod()
+AT WRITE counter
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("AT WRITE 1 triggered in TestReadWriteAuxiliary.testMethod : counter == " + $0.counter)
+ENDRULE
+
+RULE test after write trigger 2
+CLASS TestReadWriteAuxiliary
+METHOD testMethod()
+AFTER WRITE counter 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("AFTER WRITE 2 triggered in TestReadWriteAuxiliary.testMethod : counter == " + $0.counter)
+ENDRULE

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestSynch.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestSynch.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestSynch.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,19 @@
+RULE test getSynchronize trigger
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT SYNCHRONIZE
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("SYNCHRONIZE triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test getSynchronize trigger 2
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT SYNCHRONIZE 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("SYNCHRONIZE 2 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE

Added: labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestThrow.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestThrow.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/dd/scripts/location/TestThrow.txt	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,19 @@
+RULE test throw trigger
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT THROW
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("THROW 1 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE
+
+RULE test throw trigger 2
+CLASS TestCallThrowSynchAuxiliary
+METHOD testMethod()
+AT THROW 2
+HELPER org.jboss.jbossts.orchestration.tests.helpers.Default
+BIND test : Test = $0.getTest()
+IF TRUE
+DO test.log("THROW 2 triggered in TestCallThrowSynchAuxiliary.testMethod")
+ENDRULE

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/Test.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/Test.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/Test.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,89 @@
+package org.jboss.jbossts.orchestration.tests;
+
+import junit.framework.TestCase;
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+
+/**
+ * generic test class extended by specific tests
+ */
+public abstract class Test extends TestCase
+{
+    protected String name;
+    private StringBuffer output;
+    private StringBuffer expected;
+
+    public Test(String name)
+    {
+        this.name = name;
+        this.output = new StringBuffer();
+        this.expected = new StringBuffer();
+    }
+
+    public void log(String message)
+    {
+        output.append(message);
+        output.append('\n');
+    }
+
+    public void log(Exception e)
+    {
+        log(e, false);
+    }
+    
+    public void log(Exception e, boolean noTrace)
+    {
+        if (noTrace) {
+            output.append(e.toString());
+            output.append('\n');
+        } else {
+            StringWriter sw = new StringWriter();
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            pw.flush();
+            output.append(sw.toString());
+        }
+    }
+
+    public void checkOutput()
+    {
+        checkOutput(false);
+    }
+    
+    public void checkOutput(boolean reset)
+    {
+        String output = getOutput();
+        String expected = getExpected();
+        if (!output.equals(expected)) {
+            fail("\n\nexpecting\n" + expected + "\n\ngot\n" + output);
+        }
+
+        if (reset) {
+            this.output = new StringBuffer();
+            this.expected = new StringBuffer();
+        }
+    }
+
+    public String getOutput()
+    {
+        return output.toString();
+    }
+
+    public void logExpected(String message)
+    {
+        expected.append(message);
+        expected.append('\n');
+    }
+
+    public void logExpected(Exception e)
+    {
+        expected.append(e.toString());
+        expected.append('\n');
+    }
+
+    public String getExpected()
+    {
+        return expected.toString();
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestCallThrowSynchAuxiliary.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestCallThrowSynchAuxiliary.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestCallThrowSynchAuxiliary.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,67 @@
+package org.jboss.jbossts.orchestration.tests.auxiliary;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+
+/**
+ * Auxiliary class used by call, throw and synchronization location test classes
+ */
+public class TestCallThrowSynchAuxiliary
+{
+    protected Test test;
+    public int counter;
+
+    public TestCallThrowSynchAuxiliary(Test test)
+    {
+        this.test = test;
+        this.counter = 0;
+        test.log("inside TestCallThrowSynchAuxiliary(Test)");
+    }
+
+    public void testMethod() throws Exception
+    {
+        test.log("inside TestCallThrowSynchAuxiliary.testMethod");
+        int currentCounter = getCounter();
+
+        test.log("1: currentCounter == " + currentCounter);
+
+        if (currentCounter == 1) {
+            throw new Exception("counter == " + currentCounter);
+        }
+
+        synchronized(this) {
+            setCounter(currentCounter + 1);
+            currentCounter = getCounter();
+
+            test.log("2: currentCounter == " + currentCounter);
+        }
+
+        setCounter(currentCounter + 1);
+        currentCounter = getCounter();
+
+        if (currentCounter == 4) {
+            throw new Exception("counter == " + currentCounter);
+        }
+
+        synchronized(this) {
+            test.log("3: currentCounter == " + currentCounter);
+        }
+    }
+
+    public Test getTest()
+    {
+        return test;
+    }
+
+    public int setCounter(int newValue)
+    {
+        int oldValue = counter;
+        counter = newValue;
+
+        return oldValue;
+    }
+
+    public int getCounter()
+    {
+        return counter;
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliary.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliary.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliary.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,27 @@
+package org.jboss.jbossts.orchestration.tests.auxiliary;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+
+/**
+ * Auxiliary class used by entry and exit location test classes
+ */
+public class TestEntryExitAuxiliary
+{
+    protected Test test;
+
+    public TestEntryExitAuxiliary(Test test)
+    {
+        this.test = test;
+        test.log("inside TestEntryExitAuxiliary(Test)");
+    }
+
+    public void testMethod()
+    {
+        test.log("inside TestEntryExitAuxiliary.testMethod");
+    }
+
+    public Test getTest()
+    {
+        return test;
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliarySub.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliarySub.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestEntryExitAuxiliarySub.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,23 @@
+package org.jboss.jbossts.orchestration.tests.auxiliary;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+
+/**
+ * Auxiliary subclass used by entry and exit location test classes
+ */
+public class TestEntryExitAuxiliarySub extends TestEntryExitAuxiliary
+{
+    public TestEntryExitAuxiliarySub(Test test)
+    {
+        super(test);
+        test.log("inside TestEntryExitAuxiliarySub(Test)");
+    }
+
+    public void testMethod()
+    {
+        test.log("inside TestEntryExitAuxiliarySub.testMethod");
+        test.log("calling TestEntryExitAuxiliary.testMethod");
+        super.testMethod();
+        test.log("called TestEntryExitAuxiliary.testMethod");
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestReadWriteAuxiliary.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestReadWriteAuxiliary.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/auxiliary/TestReadWriteAuxiliary.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,59 @@
+package org.jboss.jbossts.orchestration.tests.auxiliary;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+
+/**
+ * Auxiliary subclass used by read and write location test classes
+ */
+public class TestReadWriteAuxiliary
+{
+    protected Test test;
+    public int counter;
+
+    public TestReadWriteAuxiliary(Test test)
+    {
+        this.test = test;
+        this.counter = 0;
+        test.log("inside TestReadWriteAuxiliary(Test)");
+    }
+
+    public void testMethod() throws Exception
+    {
+        test.log("inside TestReadWriteAuxiliary.testMethod");
+        int currentCounter = counter;
+
+        test.log("1: currentCounter == " + currentCounter);
+
+        currentCounter++;
+
+        counter = currentCounter;
+
+        test.log("2: currentCounter == " + currentCounter);
+
+        currentCounter = counter;
+
+        currentCounter++;
+        
+        counter = currentCounter;
+
+        test.log("3: currentCounter == " + currentCounter);
+    }
+
+    public Test getTest()
+    {
+        return test;
+    }
+
+    public int setCounter(int newValue)
+    {
+        int oldValue = counter;
+        counter = newValue;
+
+        return oldValue;
+    }
+
+    public int getCounter()
+    {
+        return counter;
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/helpers/Default.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/helpers/Default.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/helpers/Default.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,19 @@
+package org.jboss.jbossts.orchestration.tests.helpers;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+
+/**
+ * default helper used in TOAST unit tests providing simple logging capability
+ */
+public class Default
+{
+    public void log(String message)
+    {
+        System.out.println(message);
+    }
+
+    public void log(Test test, String message)
+    {
+        test.log(message);
+    }
+}

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestCall.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestCall.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestCall.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,59 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliary;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliarySub;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestCallThrowSynchAuxiliary;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestCall extends Test
+{
+    public TestCall()
+    {
+        super(TestCall.class.getCanonicalName());
+    }
+
+    public void test()
+    {
+        try {
+        TestCallThrowSynchAuxiliary testAuxiliary;
+        log("creating TestCallThrowSynchAuxiliary");
+        testAuxiliary = new TestCallThrowSynchAuxiliary(this);
+        log("created TestCallThrowSynchAuxiliary");
+        log("calling TestCallThrowSynchAuxiliary.testMethod");
+        testAuxiliary.testMethod();
+        log("called TestCallThrowSynchAuxiliary.testMethod");
+        } catch (Exception e) {
+            log(e);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestCallThrowSynchAuxiliary");
+        logExpected("inside TestCallThrowSynchAuxiliary(Test)");
+        logExpected("created TestCallThrowSynchAuxiliary");
+        logExpected("calling TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("inside TestCallThrowSynchAuxiliary.testMethod");
+        // we should see trace from the first call to getCounter before printing the counter
+        logExpected("CALL getCounter triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("1: currentCounter == 0");
+        // we should see trace from the call to setCounter and the second call to getCounter
+        // before printing the counter
+        logExpected("CALL setCounter triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("CALL getCounter 2 triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("2: currentCounter == 1");
+        // we should see trace from the second call to setCounter and the third call to getCounter
+        // before printing the counter
+        logExpected("CALL setCounter 2 triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("CALL getCounter 3 triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("3: currentCounter == 2");
+        logExpected("called TestCallThrowSynchAuxiliary.testMethod");
+
+        return super.getExpected();
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestEntry.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestEntry.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestEntry.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,57 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliary;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliarySub;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestEntry extends Test
+{
+    public TestEntry()
+    {
+        super(TestEntry.class.getCanonicalName());
+    }
+
+    public void test()
+    {
+        try {
+        TestEntryExitAuxiliary testAuxiliary;
+        log("creating TestEntryExitAuxiliarySub");
+        testAuxiliary = new TestEntryExitAuxiliarySub(this);
+        log("created TestEntryExitAuxiliarySub");
+        log("calling TestEntryExitAuxiliarySub.testMethod");
+        testAuxiliary.testMethod();
+        log("called TestEntryExitAuxiliarySub.testMethod");
+        } catch (Exception e) {
+            log(e);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestEntryExitAuxiliarySub");
+        // super constructor should log first then injected ENTRY code then constructor body
+        logExpected("inside TestEntryExitAuxiliary(Test)");
+        logExpected("ENTRY triggered in constructor");
+        logExpected("inside TestEntryExitAuxiliarySub(Test)");
+        logExpected("created TestEntryExitAuxiliarySub");
+        // injected ENTRY code should log in subclass method code then
+        // body of subclass hsoudl log then injected ENTRY code in superclass method
+        // then body of superclass method
+        logExpected("calling TestEntryExitAuxiliarySub.testMethod");
+        logExpected("ENTRY triggered in TestEntryExitAuxiliarySub.testMethod");
+        logExpected("inside TestEntryExitAuxiliarySub.testMethod");
+        logExpected("calling TestEntryExitAuxiliary.testMethod");
+        logExpected("ENTRY triggered in TestEntryExitAuxiliary.testMethod");
+        logExpected("inside TestEntryExitAuxiliary.testMethod");
+        logExpected("called TestEntryExitAuxiliary.testMethod");
+        logExpected("called TestEntryExitAuxiliarySub.testMethod");
+
+        return super.getExpected();
+    }
+}
+

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestExit.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestExit.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestExit.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,56 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliary;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliarySub;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestExit extends Test
+{
+    public TestExit()
+    {
+        super(TestExit.class.getCanonicalName());
+    }
+
+    public void test()
+    {
+        try {
+        TestEntryExitAuxiliary testAuxiliary;
+        log("creating TestEntryExitAuxiliarySub");
+        testAuxiliary = new TestEntryExitAuxiliarySub(this);
+        log("created TestEntryExitAuxiliarySub");
+        log("calling TestEntryExitAuxiliarySub.testMethod");
+        testAuxiliary.testMethod();
+        log("called TestEntryExitAuxiliarySub.testMethod");
+        } catch (Exception e) {
+            log(e);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestEntryExitAuxiliarySub");
+        // super constructor should log first then constructor body then injected EXIT code
+        logExpected("inside TestEntryExitAuxiliary(Test)");
+        logExpected("inside TestEntryExitAuxiliarySub(Test)");
+        logExpected("EXIT triggered in constructor");
+        logExpected("created TestEntryExitAuxiliarySub");
+        // body of subclass should log then body of superclass method
+        // then injected EXIT code in superclass method then
+        // injected ENTRY code in subclass method code
+        logExpected("calling TestEntryExitAuxiliarySub.testMethod");
+        logExpected("inside TestEntryExitAuxiliarySub.testMethod");
+        logExpected("calling TestEntryExitAuxiliary.testMethod");
+        logExpected("inside TestEntryExitAuxiliary.testMethod");
+        logExpected("EXIT triggered in TestEntryExitAuxiliary.testMethod");
+        logExpected("called TestEntryExitAuxiliary.testMethod");
+        logExpected("EXIT triggered in TestEntryExitAuxiliarySub.testMethod");
+        logExpected("called TestEntryExitAuxiliarySub.testMethod");
+
+        return super.getExpected();
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestReadWrite.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestReadWrite.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestReadWrite.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,52 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestReadWriteAuxiliary;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestReadWrite extends Test
+{
+    public TestReadWrite()
+    {
+        super(TestReadWrite.class.getCanonicalName());
+    }
+
+    public void test()
+    {
+        try {
+            TestReadWriteAuxiliary testAuxiliary;
+            log("creating TestReadWriteAuxiliary");
+            testAuxiliary = new TestReadWriteAuxiliary(this);
+            log("created TestReadWriteAuxiliary");
+            log("calling TestReadWriteAuxiliary.testMethod");
+            testAuxiliary.testMethod();
+            log("called TestReadWriteAuxiliary.testMethod");
+        } catch (Exception e) {
+            log(e, true);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestReadWriteAuxiliary");
+        logExpected("inside TestReadWriteAuxiliary(Test)");
+        logExpected("created TestReadWriteAuxiliary");
+        logExpected("calling TestReadWriteAuxiliary.testMethod");
+        logExpected("inside TestReadWriteAuxiliary.testMethod");
+        logExpected("AT READ 1 triggered in TestReadWriteAuxiliary.testMethod : counter == 0");
+        logExpected("1: currentCounter == 0");
+        logExpected("AT WRITE 1 triggered in TestReadWriteAuxiliary.testMethod : counter == 0");
+        logExpected("2: currentCounter == 1");
+        logExpected("AFTER READ 2 triggered in TestReadWriteAuxiliary.testMethod : counter == 1");
+        // AFTER
+        logExpected("AFTER WRITE 2 triggered in TestReadWriteAuxiliary.testMethod : counter == 2");
+        logExpected("3: currentCounter == 2");
+        logExpected("called TestReadWriteAuxiliary.testMethod");
+
+        return super.getExpected();
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestSynch.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestSynch.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestSynch.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,54 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliary;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestEntryExitAuxiliarySub;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestCallThrowSynchAuxiliary;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestSynch extends Test
+{
+    public TestSynch()
+    {
+        super(TestSynch.class.getCanonicalName());
+    }
+
+    public void test()
+    {
+        try {
+        TestCallThrowSynchAuxiliary testAuxiliary;
+        log("creating TestCallThrowSynchAuxiliary");
+        testAuxiliary = new TestCallThrowSynchAuxiliary(this);
+        log("created TestCallThrowSynchAuxiliary");
+        log("calling TestCallThrowSynchAuxiliary.testMethod");
+        testAuxiliary.testMethod();
+        log("called TestCallThrowSynchAuxiliary.testMethod");
+        } catch (Exception e) {
+            log(e);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestCallThrowSynchAuxiliary");
+        logExpected("inside TestCallThrowSynchAuxiliary(Test)");
+        logExpected("created TestCallThrowSynchAuxiliary");
+        logExpected("calling TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("inside TestCallThrowSynchAuxiliary.testMethod");
+        // we should see trace from the first synchronize after printing the counter
+        logExpected("1: currentCounter == 0");
+        logExpected("SYNCHRONIZE triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("2: currentCounter == 1");
+        // we should see trace from the first synchronize after printing the 2nd counter
+        // and before printing the 3rd counter
+        logExpected("SYNCHRONIZE 2 triggered in TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("3: currentCounter == 2");
+        logExpected("called TestCallThrowSynchAuxiliary.testMethod");
+
+        return super.getExpected();
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestThrow.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestThrow.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/tests/src/org/jboss/jbossts/orchestration/tests/location/TestThrow.java	2009-04-02 10:13:56 UTC (rev 25916)
@@ -0,0 +1,79 @@
+package org.jboss.jbossts.orchestration.tests.location;
+
+import org.jboss.jbossts.orchestration.tests.Test;
+import org.jboss.jbossts.orchestration.tests.auxiliary.TestCallThrowSynchAuxiliary;
+
+/**
+ * Test to ensure at entry trigger points are correctly identified
+ */
+public class TestThrow extends Test
+{
+    public TestThrow()
+    {
+        super(TestThrow.class.getCanonicalName());
+    }
+
+    private int runNumber;
+
+    public void test()
+    {
+        runNumber = 1;
+
+        try {
+            TestCallThrowSynchAuxiliary testAuxiliary;
+            log("creating TestCallThrowSynchAuxiliary");
+            testAuxiliary = new TestCallThrowSynchAuxiliary(this);
+            log("created TestCallThrowSynchAuxiliary");
+            testAuxiliary.counter = 1;
+            log("assigned TestCallThrowSynchAuxiliary.counter = 1");
+            log("calling TestCallThrowSynchAuxiliary.testMethod");
+            testAuxiliary.testMethod();
+            log("called TestCallThrowSynchAuxiliary.testMethod");
+        } catch (Exception e) {
+            log(e, true);
+        }
+
+        checkOutput(true);
+
+        runNumber = 2;
+        
+        try {
+            TestCallThrowSynchAuxiliary testAuxiliary;
+            log("creating TestCallThrowSynchAuxiliary");
+            testAuxiliary = new TestCallThrowSynchAuxiliary(this);
+            log("created TestCallThrowSynchAuxiliary");
+            testAuxiliary.counter = 2;
+            log("assigned TestCallThrowSynchAuxiliary.counter = 1");
+            log("calling TestCallThrowSynchAuxiliary.testMethod");
+            testAuxiliary.testMethod();
+            log("called TestCallThrowSynchAuxiliary.testMethod");
+        } catch (Exception e) {
+            log(e, true);
+        }
+
+        checkOutput();
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("creating TestCallThrowSynchAuxiliary");
+        logExpected("inside TestCallThrowSynchAuxiliary(Test)");
+        logExpected("created TestCallThrowSynchAuxiliary");
+        logExpected("assigned TestCallThrowSynchAuxiliary.counter = 1");
+        logExpected("calling TestCallThrowSynchAuxiliary.testMethod");
+        logExpected("inside TestCallThrowSynchAuxiliary.testMethod");
+        if (runNumber == 1) {
+            logExpected("1: currentCounter == 1");
+            logExpected("THROW 1 triggered in TestCallThrowSynchAuxiliary.testMethod");
+            logExpected(new Exception("counter == 1"));
+        }
+        if (runNumber == 2) {
+            logExpected("1: currentCounter == 2");
+            logExpected("2: currentCounter == 3");
+            logExpected("THROW 2 triggered in TestCallThrowSynchAuxiliary.testMethod");
+            logExpected(new Exception("counter == 4"));
+        }
+
+        return super.getExpected();
+    }
+}
\ No newline at end of file




More information about the jboss-svn-commits mailing list