[jboss-svn-commits] JBL Code SVN: r25441 - in labs/jbosstm/workspace/adinn/orchestration: docs and 2 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Feb 26 12:21:00 EST 2009


Author: adinn
Date: 2009-02-26 12:20:59 -0500 (Thu, 26 Feb 2009)
New Revision: 25441

Added:
   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
Modified:
   labs/jbosstm/workspace/adinn/orchestration/README
   labs/jbosstm/workspace/adinn/orchestration/docs/ProgrammersGuide.odt
   labs/jbosstm/workspace/adinn/orchestration/docs/ProgrammersGuide.pdf
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java
   labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/LocationType.java
Log:
added and documented new location specifier AT THROW <count> plus modified toastcheck script to pass TOAST_JAVA_OPTS to the JVM 

Modified: labs/jbosstm/workspace/adinn/orchestration/README
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/README	2009-02-26 16:48:47 UTC (rev 25440)
+++ labs/jbosstm/workspace/adinn/orchestration/README	2009-02-26 17:20:59 UTC (rev 25441)
@@ -145,10 +145,10 @@
 types.
 
 Location specifications also include a further qualifier identifying
-where in the target method the trigger point for the rul should be
+where in the target method the trigger point for the rule should be
 located. The simplest location specification is AT ENTRY which locates
 the triggerpoint at the first executable instruction in a the atrget
-method's bytecode (or the first instrction following the superclass
+method's bytecode (or the first instruction following the superclass
 constructor if the target method is a constructor). Other qualifiers
 include
 
@@ -157,6 +157,7 @@
 AT WRITE <fieldname> [<count>]
 AT INVOKE <methodname>[[signature>] [<count>]
 AT SYNCHRONIZE [<count>]
+AT THROW [<typename>] [<count>]
 
 An event specification also includes a list of bindings for variables
 which can be referenced during evaluaton of the rule condition and

Modified: labs/jbosstm/workspace/adinn/orchestration/docs/ProgrammersGuide.odt
===================================================================
(Binary files differ)

Modified: labs/jbosstm/workspace/adinn/orchestration/docs/ProgrammersGuide.pdf
===================================================================
(Binary files differ)

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-02-26 16:48:47 UTC (rev 25440)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java	2009-02-26 17:20:59 UTC (rev 25441)
@@ -40,6 +40,8 @@
                 return SynchronizeLocation.create(parameters, false);
             case SYNCHRONIZE_COMPLETED:
                 return SynchronizeLocation.create(parameters, true);
+            case THROW:
+                return ThrowLocation.create(parameters);
         }
 
         return null;
@@ -552,4 +554,102 @@
             return text;
         }
     }
+    /**
+     * location identifying a throw trigger point
+     */
+    private static class ThrowLocation extends Location
+    {
+        /**
+         * count identifying which throw operation should be taken as the trigger point. if not specified
+         * as a parameter this defaults to the first throw.
+         */
+        private int count;
+
+        /**
+         * the name of the exception type to which the method belongs or null if any type will do
+         */
+        private String typeName;
+
+        /**
+         * construct a location identifying a throw trigger point
+         * @param count count identifying which throw should be taken as the trigger point
+         * @param typeName the name of the exception type associated with the throw operation
+         */
+        private ThrowLocation(int count, String typeName)
+        {
+            this.count = count;
+            this.typeName = typeName;
+        }
+
+        /**
+         * create a location identifying a throw trigger point
+         * @param parameters the text of the parameters appended to the location specifier
+         * @return a throw location or null if the parameters does not contain a valid type name
+         */
+        protected static Location create(String parameters)
+        {
+            String text = parameters.trim();
+            String typeName;
+            String signature;
+            int count;
+
+            // check for trailing count
+            if (text.contains(" ")) {
+                int tailIdx = text.lastIndexOf(" ");
+                String countText = text.substring(tailIdx + 1).trim();
+                try {
+                    count = Integer.valueOf(countText);
+                } catch (NumberFormatException nfe) {
+                    return null;
+                }
+                text = text.substring(0, tailIdx).trim();
+            } else {
+                count = 1;
+            }
+
+            // text may be either a count or a type name
+            if (text.equals("") || !Character.isDigit(text.charAt(0))) {
+                typeName = text;
+            } else {
+                try {
+                    count = Integer.valueOf(text);
+                } catch (NumberFormatException nfe) {
+                    return null;
+                }
+                typeName="";
+            }
+
+            // TODO sanity check type name
+
+            return new ThrowLocation(count, typeName);
+        }
+
+        /**
+         * return an adapter which can be used to check whether a method contains a trigger point whose position
+         * matches this location
+         * @return the required adapter
+         */
+        public RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod) {
+            return new ThrowCheckAdapter(cv, targetClass, targetMethod, typeName, count);
+        }
+
+        /**
+         * return an adapter which can be used to insert a trigger call in a method containing a trigger point whose
+         * position matches this location
+         * @return the required adapter
+         */
+        public RuleTriggerAdapter getRuleAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod) {
+            return new ThrowTriggerAdapter(cv, rule, targetClass, targetMethod, typeName, count);
+        }
+
+        public String toString() {
+            String text = "AT THROW";
+
+            if (count != 1) {
+                text += " " + count;
+            }
+
+            return text;
+        }
+    }
 }

Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/LocationType.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/LocationType.java	2009-02-26 16:48:47 UTC (rev 25440)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/LocationType.java	2009-02-26 17:20:59 UTC (rev 25441)
@@ -76,8 +76,16 @@
      *
      * script syntax : 'AFTER' 'SYNCHRONIZE' [ <count> ]
      */
-    SYNCHRONIZE_COMPLETED;
+    SYNCHRONIZE_COMPLETED,
 
+    /**
+     * specifies a location for trigger insertion by identifying throw of an exception of the nth such throw
+     * if a count is supplied
+     * script syntax : 'AT' 'THROW' [<typename>] [ <count> ]
+     * n.b. exception typename parsed but not yet implemented
+     */
+    THROW;
+
     public String specifierText()
     {
         for (int i = 0; i < specifiers.length; i++) {
@@ -127,6 +135,7 @@
             "AFTER INVOKE",
             "AT SYNCHRONIZE",
             "AFTER SYNCHRONIZE",
+            "AT THROW",
             "LINE", // for compatibility
             "AT CALL", // for ambiguity :-)
             "AFTER CALL" // for ambiguity :-)
@@ -143,6 +152,7 @@
             INVOKE_COMPLETED,
             SYNCHRONIZE,
             SYNCHRONIZE_COMPLETED,
+            THROW,
             LINE,
             INVOKE,
             INVOKE_COMPLETED

Added: 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	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowCheckAdapter.java	2009-02-26 17:20:59 UTC (rev 25441)
@@ -0,0 +1,101 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*
+* @authors Andrew Dinn
+*/
+package org.jboss.jbossts.orchestration.agent.adapter;
+
+import org.objectweb.asm.*;
+import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+
+/**
+ * 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)
+    {
+        super(cv, targetClass, targetMethod);
+        this.exceptionClass = exceptionClass;
+        this.count = count;
+        this.visitedCount = 0;
+    }
+
+    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 ThrowCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+        }
+
+        return mv;
+    }
+
+    /**
+     * a method visitor used to add a rule event trigger call to a method
+     */
+
+    private class ThrowCheckMethodAdapter extends MethodAdapter
+    {
+        private int access;
+        private String name;
+        private String descriptor;
+        private String signature;
+        private String[] exceptions;
+        private boolean visited;
+
+        ThrowCheckMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        {
+            super(mv);
+            this.access = access;
+            this.name = name;
+            this.descriptor = descriptor;
+            this.signature = signature;
+            this.exceptions = exceptions;
+            visitedCount = 0;
+        }
+
+        public void visitInsn(final int opcode) {
+            if (opcode == Opcodes.ATHROW) {
+                // 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) {
+                    visitedCount++;
+                    if (visitedCount == count) {
+                        // and we have enough occurences to match the count
+                        setVisitOk();
+                    }
+                }
+            }
+
+            mv.visitInsn(opcode);
+        }
+    }
+
+    private String exceptionClass;
+    private int count;
+    private int visitedCount;
+}
\ No newline at end of file

Added: 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	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/ThrowTriggerAdapter.java	2009-02-26 17:20:59 UTC (rev 25441)
@@ -0,0 +1,228 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*
+* @authors Andrew Dinn
+*/
+package org.jboss.jbossts.orchestration.agent.adapter;
+
+import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.agent.Transformer;
+import org.objectweb.asm.*;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+
+/**
+ * asm Adapter class used to add a rule event trigger call to a method of some given class
+ */
+public class ThrowTriggerAdapter extends RuleTriggerAdapter
+{
+    public ThrowTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, String exceptionClass, int count)
+    {
+        super(cv, rule, targetClass, targetMethod);
+        this.exceptionClass = exceptionClass;
+        this.count = count;
+        this.visitedCount = 0;
+    }
+
+    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)) {
+            if (name.equals("<init>")) {
+                return new ThrowTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+            } else {
+                return new ThrowTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+            }
+        }
+        return mv;
+    }
+
+    /**
+     * a method visitor used to add a rule event trigger call to a method
+     */
+
+    private class ThrowTriggerMethodAdapter extends GeneratorAdapter
+    {
+        /**
+         * flag used by subclass to avoid inserting trigger until after super constructor has been called
+         */
+        protected boolean latched;
+        private int access;
+        private String name;
+        private String descriptor;
+        private String signature;
+        private String[] exceptions;
+        private Label startLabel;
+        private Label endLabel;
+
+        ThrowTriggerMethodAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        {
+            super(mv, access, name, descriptor);
+            this.access = access;
+            this.name = name;
+            this.descriptor = descriptor;
+            this.signature = signature;
+            this.exceptions = exceptions;
+            startLabel = null;
+            endLabel = null;
+            visitedCount = 0;
+            latched = false;
+        }
+
+        public void visitInsn(final int opcode) {
+            if (opcode == Opcodes.ATHROW) {
+                // 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) {
+                    // a relevant invocation occurs in the called method
+                    visitedCount++;
+                    if (!latched && visitedCount == count) {
+                        rule.setTypeInfo(targetClass, access, name, descriptor, exceptions);
+                        String key = rule.getKey();
+                        Type ruleType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.Rule"));
+                        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());
+                        }
+                        startLabel = super.newLabel();
+                        endLabel = super.newLabel();
+                        super.visitLabel(startLabel);
+                        super.push(key);
+                        if ((access & Opcodes.ACC_STATIC) == 0) {
+                            super.loadThis();
+                        } else {
+                            super.push((Type)null);
+                        }
+                        super.loadArgArray();
+                        super.invokeStatic(ruleType, method);
+                        super.visitLabel(endLabel);
+                    }
+                }
+            }
+            
+            super.visitInsn(opcode);
+        }
+
+        public void visitEnd()
+        {
+            /*
+             * unfortunately, if we generate the handler code here it comes too late for the stack size
+             * computation to take account of it. the handler code uses 4 stack slots so this causes and
+             * error when the method body uses less than 4. we can patch this by generating the handler
+             * code when visitMaxs is called
+            Type exceptionType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.exception.ExecuteException"));
+            Type earlyReturnExceptionType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.exception.EarlyReturnException"));
+            Type returnType =  Type.getReturnType(descriptor);
+            // add exception handling code subclass first
+            super.catchException(startLabel, endLabel, earlyReturnExceptionType);
+            if (returnType == Type.VOID_TYPE) {
+                // drop exception and just return
+                super.pop();
+                super.visitInsn(Opcodes.RETURN);
+            } else {
+                // fetch value from exception, unbox if needed and return value
+                Method getReturnValueMethod = Method.getMethod("Object getReturnValue()");
+                super.invokeVirtual(earlyReturnExceptionType, getReturnValueMethod);
+                super.unbox(returnType);
+                super.returnValue();
+            }
+            super.catchException(startLabel, endLabel, exceptionType);
+            super.throwException(exceptionType, rule.getName() + " execution exception ");
+            */
+            super.visitEnd();
+        }
+
+        public void visitMaxs(int maxStack, int maxLocals) {
+            /*
+             * this really ought to be in visitEnd but see above for why we do it here
+             */
+            Type exceptionType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.exception.ExecuteException"));
+            Type earlyReturnExceptionType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.exception.EarlyReturnException"));
+            Type throwExceptionType = Type.getType(TypeHelper.externalizeType("org.jboss.jbossts.orchestration.rule.exception.ThrowException"));
+            Type throwableType = Type.getType(TypeHelper.externalizeType("java.lang.Throwable"));
+            Type returnType =  Type.getReturnType(descriptor);
+            // add exception handling code subclass first
+            super.catchException(startLabel, endLabel, earlyReturnExceptionType);
+            if (returnType == Type.VOID_TYPE) {
+                // drop exception and just return
+                super.pop();
+                super.visitInsn(Opcodes.RETURN);
+            } else {
+                // fetch value from exception, unbox if needed and return value
+                Method getReturnValueMethod = Method.getMethod("Object getReturnValue()");
+                super.invokeVirtual(earlyReturnExceptionType, getReturnValueMethod);
+                super.unbox(returnType);
+                super.returnValue();
+            }
+            super.catchException(startLabel, endLabel, throwExceptionType);
+            // fetch value from exception, unbox if needed and return value
+            Method getThrowableMethod = Method.getMethod("Throwable getThrowable()");
+            super.invokeVirtual(throwExceptionType, getThrowableMethod);
+            super.throwException();
+
+            super.catchException(startLabel, endLabel, exceptionType);
+            super.throwException(exceptionType, rule.getName() + " execution exception ");
+            // ok now recompute the stack size
+            super.visitMaxs(maxStack, maxLocals);
+        }
+
+    }
+
+    /**
+     * a method visitor used to add a rule event trigger call to a constructor -- this has to make sure
+     * the super constructor has been called before allowing a trigger call to be compiled
+     */
+
+    private class ThrowTriggerConstructorAdapter extends ThrowTriggerMethodAdapter
+    {
+        ThrowTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+        {
+            super(mv, access, name, descriptor, signature, exceptions);
+            // ensure we don't transform calls before the super constructor is called
+            latched = true;
+        }
+
+        public void visitMethodInsn(
+            final int opcode,
+            final String owner,
+            final String name,
+            final String desc)
+        {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            // hmm, this probably means the super constructor has been invoked :-)
+            if (latched && opcode == Opcodes.INVOKESPECIAL) {
+                latched = false;
+            }
+
+        }
+    }
+
+    private String exceptionClass;
+    private int count;
+    private int visitedCount;
+}
\ No newline at end of file




More information about the jboss-svn-commits mailing list