[jboss-svn-commits] JBL Code SVN: r24000 - in labs/jbosstm/workspace/adinn/orchestration: src/org/jboss/jbossts/orchestration and 5 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Nov 20 12:28:49 EST 2008
Author: adinn
Date: 2008-11-20 12:28:48 -0500 (Thu, 20 Nov 2008)
New Revision: 24000
Added:
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
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Script.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/
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/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
Removed:
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/annotation/
Modified:
labs/jbosstm/workspace/adinn/orchestration/handler.txt
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Main.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.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/type/TypeHelper.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java
Log:
modified to allow various extra specifiers for where to place the trigger point besides (AT) LINE
Modified: labs/jbosstm/workspace/adinn/orchestration/handler.txt
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/handler.txt 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/handler.txt 2008-11-20 17:28:48 UTC (rev 24000)
@@ -83,7 +83,7 @@
RULE add coordinator engine countdown
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD <init>(String, boolean, W3CEndpointReference, boolean, State)
-LINE 96
+AFTER WRITE recovered
BIND engine:CoordinatorEngine = $0,
recovered:boolean = engine.isRecovered(),
identifier:String = engine.getId()
@@ -102,7 +102,7 @@
RULE kill JVM
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
-LINE 316
+AT SYNCHRONIZE
BIND engine:CoordinatorEngine = $0,
recovered:boolean = engine.isRecovered(),
identifier:String = engine.getId()
@@ -125,7 +125,7 @@
RULE countdown at commit
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
-LINE 316
+AFTER SYNCHRONIZE
BIND engine:CoordinatorEngine = $0,
recovered:boolean = engine.isRecovered(),
identifier:String = engine.getId()
@@ -151,7 +151,7 @@
RULE kill committed thread
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD committed(Notification, AddressingProperties, ArjunaContext)
-LINE -1
+AT ENTRY
BIND engine:CoordinatorEngine = $0,
recovered:boolean = engine.isRecovered(),
identifier:String = engine.getId()
@@ -175,7 +175,7 @@
RULE trace prepared replay
CLASS org.jboss.jbossts.xts.recovery.coordinator.at.RecoverACCoordinator
METHOD replayPhase2
-LINE 74
+AT INVOKE phase2Commit
BIND coordinator = $0,
uid : Uid = coordinator.identifier(),
status : int = coordinator.status()
@@ -196,7 +196,7 @@
RULE trace heuristic committed replay
CLASS org.jboss.jbossts.xts.recovery.coordinator.at.RecoverACCoordinator
METHOD replayPhase2
-LINE 74
+AT INVOKE phase2Commit
BIND coordinator = $0,
uid : Uid = coordinator.identifier(),
status : int = coordinator.status()
@@ -215,7 +215,7 @@
RULE trace remove committed state
CLASS com.arjuna.ats.arjuna.coordinator.BasicAction
METHOD updateState
-LINE 3529
+AFTER CALL remove_committed
BIND action : BasicAction = $0,
uid = action.get_uid()
IF TRUE
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Location.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,555 @@
+package org.jboss.jbossts.orchestration.agent;
+
+import org.objectweb.asm.ClassVisitor;
+import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
+import org.jboss.jbossts.orchestration.agent.adapter.*;
+
+/**
+ * Specifies a location in a method at which a rule trigger should be inserted
+ */
+public abstract class Location
+{
+ /**
+ * create a location object of a given type
+ * @param type the type of location being specified
+ * @param parameters the text of the parameters appended to the location specifier
+ * @return a location of the appropriate type or null if the parameters are incorrectly specified
+ */
+ public static Location create(LocationType type, String parameters)
+ {
+ switch (type)
+ {
+ case ENTRY:
+ return EntryLocation.create(parameters);
+ case LINE:
+ return LineLocation.create(parameters);
+ case READ:
+ return AccessLocation.create(parameters, ACCESS_READ, false);
+ case READ_COMPLETED:
+ return AccessLocation.create(parameters, ACCESS_READ, true);
+ case WRITE:
+ return AccessLocation.create(parameters, ACCESS_WRITE, false);
+ case WRITE_COMPLETED:
+ return AccessLocation.create(parameters, ACCESS_WRITE, true);
+ case INVOKE:
+ return InvokeLocation.create(parameters, false);
+ case INVOKE_COMPLETED:
+ return InvokeLocation.create(parameters, true);
+ case SYNCHRONIZE:
+ return SynchronizeLocation.create(parameters, false);
+ case SYNCHRONIZE_COMPLETED:
+ return SynchronizeLocation.create(parameters, true);
+ }
+
+ return null;
+ }
+
+ /**
+ * 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 abstract RuleCheckAdapter getRuleCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod);
+
+ /**
+ * 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 abstract RuleTriggerAdapter getRuleAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod);
+
+ /**
+ * flag indicating that a field access location refers to field READ operations
+ */
+ public static final int ACCESS_READ = 1;
+
+ /**
+ * flag indicating that a field access location refers to field WRITE operations
+ */
+ public static final int ACCESS_WRITE = 2;
+
+ /**
+ * location identifying a method entry trigger point
+ */
+ private static class EntryLocation extends Location
+ {
+ /**
+ * create a location identifying a method entry trigger point
+ * @param parameters the text of the parameters appended to the location specifier
+ * @return a method entry location or null if the parameters is not a blank String
+ */
+ protected static Location create(String parameters) {
+ if (!parameters.trim().equals("")) {
+ // hmm, not expecting any parameters here
+ return null;
+ }
+ return new EntryLocation();
+ }
+
+ /**
+ * 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) {
+ // a line check adapter with line -1 will do the job
+
+ return new LineCheckAdapter(cv, targetClass, targetMethod, -1);
+ }
+
+ /**
+ * 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) {
+ // a line adapter with line -1 will do the job
+
+ return new LineTriggerAdapter(cv, rule, targetClass, targetMethod, -1);
+ }
+
+ public String toString() {
+ return "AT ENTRY";
+ }
+ }
+
+ /**
+ * location identifying a method line trigger point
+ */
+ private static class LineLocation extends Location
+ {
+ /**
+ * the line at which the trigger point should be inserted
+ */
+ private int targetLine;
+
+ /**
+ * construct a location identifying a method line trigger point
+ * @param targetLine the line at which the trigger point should be inserted
+ */
+ private LineLocation(int targetLine)
+ {
+ this.targetLine = targetLine;
+ }
+
+ /**
+ * create a location identifying a method entry trigger point
+ * @param parameters the text of the parameters appended to the location specifier
+ * @return a method entry location or null if the parameters is not a blank String
+ */
+ protected static Location create(String parameters)
+ {
+ try {
+ int targetLine = Integer.decode(parameters.trim());
+ return new LineLocation(targetLine);
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ }
+
+ /**
+ * 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 LineCheckAdapter(cv, targetClass, targetMethod, targetLine);
+ }
+
+ /**
+ * 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 LineTriggerAdapter(cv, rule, targetClass,targetMethod, targetLine);
+ }
+
+ public String toString() {
+ return "AT LINE " + targetLine;
+ }
+ }
+
+ /**
+ * location identifying a method field access trigger point
+ */
+ private static class AccessLocation extends Location
+ {
+ /**
+ * the name of the field being accessed at the point where the trigger point should be inserted
+ */
+ private String fieldName;
+
+ /**
+ * the name of the type to which the field belongs or null if any type will do
+ */
+ private String typeName;
+
+ /**
+ * count identifying which access should be taken as the trigger point. if not specified
+ * as a parameter this defaults to the first access.
+ */
+ private int count;
+
+ /**
+ * flags identifying which type of access should be used to identify the trigger. this is either
+ * ACCESS_READ, ACCESS_WRITE or an OR of these two values
+ */
+ private int flags;
+
+ /**
+ * flag which is false if the trigger should be inserted before the field access is performed
+ * and true if it should be inserted after
+ */
+ private boolean whenComplete;
+
+ /**
+ * construct a location identifying a field read trigger point
+ * @param typeName the name of the class owning the field
+ * @param fieldName the name of the field being read
+ * @param count count identifying which access should be taken as the trigger point
+ * @param flags bit field comprising one or other of flags ACCESS_READ and ACCESS_WRITE identifying
+ * whether this specifies field READ or WRITE operations
+ * @param whenComplete false if the trigger should be inserted before the access is performed
+ * and true if it should be inserted after
+ */
+ private AccessLocation(String typeName, String fieldName, int count, int flags, boolean whenComplete)
+ {
+ this.typeName = typeName;
+ this.fieldName = fieldName;
+ this.count = count;
+ this.flags = flags;
+ this.whenComplete = whenComplete;
+ }
+
+ /**
+ * create a location identifying a method entry trigger point
+ * @param parameters the text of the parameters appended to the location specifier
+ * @param whenComplete false if the trigger should be inserted before the access is performed
+ * and true if it should be inserted after
+ * @return a method entry location or null if the parameters is not a blank String
+ */
+ protected static Location create(String parameters, int flags, boolean whenComplete)
+ {
+ String text = parameters.trim();
+ String typeName;
+ String fieldName;
+ int count;
+
+ // check for trailing count
+ if (text.contains(" ")) {
+ int spaceIdx = text.lastIndexOf(" ");
+ String countText = text.substring(spaceIdx).trim();
+ try {
+ count = Integer.valueOf(countText);
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ text = text.substring(0, spaceIdx).trim();
+ } else {
+ count = 1;
+ }
+ // check for leading type name
+ if (text.contains(".")) {
+ int dotIdx = text.lastIndexOf(".");
+ typeName = text.substring(0, dotIdx).trim();
+ fieldName=text.substring(dotIdx + 1).trim();
+ } else {
+ typeName = null;
+ fieldName = text;
+ }
+ // TODO sanity check type and field name
+
+ return new AccessLocation(typeName, fieldName, count, flags, whenComplete);
+ }
+
+ /**
+ * 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 AccessCheckAdapter(cv, targetClass, targetMethod, typeName, fieldName, flags, 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 AccessTriggerAdapter(cv, rule, targetClass, targetMethod, typeName, fieldName, flags, count, whenComplete);
+ }
+
+ public String toString() {
+ String text;
+
+ if (whenComplete) {
+ text = "AFTER ";
+ } else {
+ text = "AT ";
+ }
+ if (flags == ACCESS_READ) {
+ text += "READ ";
+ } else if (flags == ACCESS_WRITE) {
+ text += "WRITE ";
+ } else {
+ text += "ACCESS ";
+ }
+
+ if (typeName != null) {
+ text += typeName + ".";
+ }
+ text += fieldName;
+
+ if (count != 1) {
+ text += " " + count;
+ }
+
+ return text;
+ }
+ }
+
+ /**
+ * location identifying a method invocation trigger point
+ */
+ private static class InvokeLocation extends Location
+ {
+ /**
+ * the name of the method being invoked at the point where the trigger point should be inserted
+ */
+ private String methodName;
+
+ /**
+ * the name of the type to which the method belongs or null if any type will do
+ */
+ private String typeName;
+
+ /**
+ * the method signature in externalised form
+ */
+ private String signature;
+
+ /**
+ * count identifying which invocation should be taken as the trigger point. if not specified
+ * as a parameter this defaults to the first invocation.
+ */
+ private int count;
+
+ /**
+ * flag which is false if the trigger should be inserted before the method invocation is performed
+ * and true if it should be inserted after
+ */
+ private boolean whenComplete;
+
+ /**
+ * construct a location identifying a method invocation trigger point
+ * @param typeName the name of the class owning the method
+ * @param methodName the name of the method being called
+ * @param signature the method signature in externalised form
+ * @param count count identifying which invocation should be taken as the trigger point
+ * @param whenComplete false if the trigger should be inserted before the method invocation is
+ * performed and true if it should be inserted after
+ */
+ private InvokeLocation(String typeName, String methodName, String signature, int count, boolean whenComplete)
+ {
+ this.typeName = typeName;
+ this.methodName = methodName;
+ this.signature = signature;
+ this.count = count;
+ this.whenComplete = whenComplete;
+ }
+
+ /**
+ * create a location identifying a method entry trigger point
+ * @param parameters the text of the parameters appended to the location specifier
+ * @param whenComplete false if the trigger should be inserted before the access is performed
+ * and true if ti shoudl be inserted after
+ * @return a method entry location or null if the parameters is not a blank String
+ */
+ protected static Location create(String parameters, boolean whenComplete)
+ {
+ String text = parameters.trim();
+ String typeName;
+ String fieldName;
+ 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 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;
+ }
+ // check for argument list
+ if (text.contains("(")) {
+ text=TypeHelper.parseMethodName(text);
+ signature = TypeHelper.parseMethodDescriptor(text);
+ } else {
+ signature = "";
+ }
+ // check for leading type name
+ if (text.contains(".")) {
+ int dotIdx = text.lastIndexOf(".");
+ typeName = text.substring(0, dotIdx).trim();
+ fieldName=text.substring(dotIdx + 1).trim();
+ } else {
+ typeName = null;
+ fieldName = text;
+ }
+ // TODO sanity check type and field name
+
+ return new InvokeLocation(typeName, fieldName, signature, count, whenComplete);
+ }
+
+ /**
+ * 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 InvokeCheckAdapter(cv, targetClass, targetMethod, typeName, methodName, signature, 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 InvokeTriggerAdapter(cv, rule, targetClass, targetMethod, typeName, methodName, signature, count, whenComplete);
+ }
+
+ public String toString() {
+ String text;
+
+ if (whenComplete) {
+ text = "AFTER INVOKE ";
+ } else {
+ text = "AT INVOKE ";
+ }
+
+ if (typeName != null) {
+ text += typeName + ".";
+ }
+ text += methodName;
+
+ if (signature.length() > 0) {
+ text = text + TypeHelper.internalizeDescriptor(signature);
+ }
+
+ if (count != 1) {
+ text += " " + count;
+ }
+
+ return text;
+ }
+ }
+
+ /**
+ * location identifying a synchronization trigger point
+ */
+ private static class SynchronizeLocation extends Location
+ {
+ /**
+ * count identifying which synchronization should be taken as the trigger point. if not specified
+ * as a parameter this defaults to the first synchronization.
+ */
+ private int count;
+
+ /**
+ * flag which is false if the trigger should be inserted before the synchronization is performed
+ * and true if it should be inserted after
+ */
+ private boolean whenComplete;
+
+ /**
+ * construct a location identifying a synchronization trigger point
+ * @param count count identifying which synchronization should be taken as the trigger point
+ * @param whenComplete false if the trigger should be inserted before the synchronization is
+ * performed and true if it should be inserted after
+ */
+ private SynchronizeLocation(int count, boolean whenComplete)
+ {
+ this.count = count;
+ this.whenComplete = whenComplete;
+ }
+
+ /**
+ * create a location identifying a synchronization trigger point
+ * @param parameters the text of the parameters appended to the location specifier
+ * @param whenComplete false if the trigger should be inserted before the synchronization is
+ * performed and true if it should be inserted after
+ * @return a method entry location or null if the parameters is not a blank String
+ */
+ protected static Location create(String parameters, boolean whenComplete)
+ {
+ String text = parameters.trim();
+ int count;
+
+ // check for count
+ if (text.length() != 0) {
+ try {
+ count = Integer.valueOf(text);
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ } else {
+ count = 1;
+ }
+
+ return new SynchronizeLocation(count, whenComplete);
+ }
+
+ /**
+ * 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 SynchronizeCheckAdapter(cv, targetClass, targetMethod, 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 SynchronizeTriggerAdapter(cv, rule, targetClass, targetMethod, count, whenComplete);
+ }
+
+ public String toString() {
+ String text;
+
+ if (whenComplete) {
+ text= "AFTER SYNCHRONIZE";
+ } else {
+ text= "AT SYNCHRONIZE";
+ }
+
+ if (count != 1) {
+ text += " " + count;
+ }
+
+ return text;
+ }
+ }
+}
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/LocationType.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,150 @@
+package org.jboss.jbossts.orchestration.agent;
+
+/**
+ * enum categorizing types of locations at which rule triggers can be inserted
+ */
+public enum LocationType
+{
+ /**
+ * specifies the default location for trigger insertion which is either the first line of a method or
+ * the first line of a constructor following any indirection via an alternative constructor or via
+ * the super constructor.
+ *
+ * script syntax : 'AT' 'ENTRY'
+ */
+ ENTRY,
+ /**
+ * specifies a location for trigger insertion via a line number.
+ *
+ * script syntax : 'AT' 'LINE' <linenumber>
+ */
+ LINE,
+ /**
+ * specifies a location for trigger insertion by identifying a field read operation or the nth such field
+ * read if a count is supplied.
+ *
+ * script syntax : 'AT' 'READ' [<typename> '.' ] <fieldname> [ <count> ]
+ */
+ READ,
+ /**
+ * specifies a location for trigger insertion by identifying a field read operation or the nth such field
+ * read if a count is supplied.
+ *
+ * script syntax : 'AFTER' 'READ' [<typename> '.' ] <fieldname> [ <count> ]
+ */
+ READ_COMPLETED,
+ /**
+ * specifies a location for trigger insertion by identifying a field write operation or the nth such field
+ * write if a count is supplied.
+ *
+ * script syntax : 'AT' 'WRITE' [<typename> '.' ] <fieldname> [ <count> ]
+ */
+ WRITE,
+ /**
+ * specifies a location for trigger insertion by identifying a field write operation or the nth such field
+ * write if a count is supplied.
+ *
+ * script syntax : 'AFTER' 'WRITE' [<typename> '.' ] <fieldname> [ <count> ]
+ */
+ WRITE_COMPLETED,
+ /**
+ * specifies a location for trigger insertion by identifying a method invoke operation or the nth such
+ * method invoke if a count is supplied.
+ *
+ * script syntax : 'AT' 'INVOKE' [<typename> '.' ] <methodname> ['(' <argtypes> ')' [ <count> ]
+ */
+ INVOKE,
+ /**
+ * specifies a location for trigger insertion by identifying return from a method invoke operation or the
+ * nth such return if a count is supplied.
+ *
+ * script syntax : 'AFTER' 'INVOKE' [<typename> '.' ] <methodname> ['(' <argtypes> ')' [ <count> ]
+ */
+ INVOKE_COMPLETED,
+ // this is tricky so we exclude it for now
+ // EXIT,
+ /**
+ * specifies a location for trigger insertion by identifying a synchronize operation or the nth such
+ * operation if a count is supplied.
+ *
+ * script syntax : 'AT' 'SYNCHRONIZE' [ <count> ]
+ */
+ SYNCHRONIZE,
+ /**
+ * specifies a location for trigger insertion by identifying completion of a synchronize operation or the
+ * nth such operation if a count is supplied.
+ *
+ * script syntax : 'AFTER' 'SYNCHRONIZE' [ <count> ]
+ */
+ SYNCHRONIZE_COMPLETED;
+
+ public String specifierText()
+ {
+ for (int i = 0; i < specifiers.length; i++) {
+ if (types[i] == this) {
+ return specifiers[i];
+ }
+ }
+ // hmm, well default to entry
+ return specifiers[0];
+ }
+
+ public static LocationType type(String locationSpec)
+ {
+ locationSpec = locationSpec.trim();
+ for (int i = 0; i < specifiers.length; i++) {
+ String specifier = specifiers[i];
+ if (locationSpec.startsWith(specifier)) {
+ return types[i];
+ }
+ }
+ // hmm, well default to entry
+ return null;
+ }
+
+ public static String parameterText(String locationSpec)
+ {
+ locationSpec = locationSpec.trim();
+ for (int i = 0; i < specifiers.length; i++) {
+ String specifier = specifiers[i];
+ if (locationSpec.startsWith(specifier)) {
+ return locationSpec.substring(specifier.length());
+ }
+ }
+ // hmm, doesn't really matter but ENTRY has no parameters
+
+ return "";
+ }
+
+ private static String[] specifiers = {
+ "AT ENTRY",
+ "AT LINE",
+ "AT READ",
+ "AFTER READ",
+ "AT WRITE",
+ "AFTER WRITE",
+ "AT INVOKE",
+ "AFTER INVOKE",
+ "AT SYNCHRONIZE",
+ "AFTER SYNCHRONIZE",
+ "LINE", // for compatibility
+ "AT CALL", // for ambiguity :-)
+ "AFTER CALL" // for ambiguity :-)
+ };
+
+ private static LocationType[] types = {
+ ENTRY,
+ LINE,
+ READ,
+ READ_COMPLETED,
+ WRITE,
+ WRITE_COMPLETED,
+ INVOKE,
+ INVOKE_COMPLETED,
+ SYNCHRONIZE,
+ SYNCHRONIZE_COMPLETED,
+ LINE,
+ INVOKE,
+ INVOKE_COMPLETED
+ };
+}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Main.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Main.java 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Main.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -23,21 +23,14 @@
*/
package org.jboss.jbossts.orchestration.agent;
-import org.jboss.jbossts.orchestration.annotation.EventHandlerClass;
import java.lang.instrument.Instrumentation;
-import java.lang.annotation.Annotation;
import java.util.jar.JarFile;
-import java.util.jar.JarEntry;
import java.util.ArrayList;
import java.util.List;
-import java.util.Enumeration;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
-import java.net.URLClassLoader;
-import java.net.URL;
-import java.net.MalformedURLException;
/**
* agent class supplied at JVM startup to install orchestration package bytecode transformer
Deleted: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -1,252 +0,0 @@
-/*
-* 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;
-
-import org.jboss.jbossts.orchestration.rule.Rule;
-import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
-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 som egiven class
- */
-public class RuleAdapter extends ClassAdapter
-{
- RuleAdapter(ClassVisitor cv, Rule rule, String targetClass, String handlerMethod, int handlerLine)
- {
- super(cv);
- this.rule = rule;
- this.targetClass = targetClass;
- this.targetMethod = TypeHelper.parseMethodName(handlerMethod);
- this.targetDescriptor = TypeHelper.parseMethodDescriptor(handlerMethod);
- this.targetLine = handlerLine;
- this.visitedLine = false;
- }
-
- void visitClass(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- public FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- FieldVisitor fv = super.visitField(access, name, desc, signature, value);
- return fv;
- }
-
- 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 (targetMethod.equals(name)) {
- if (targetDescriptor.equals("") || TypeHelper.equalDescriptors(targetDescriptor, desc))
- {
- if (name == "<init>") {
- return new RuleConstructorAdapter(mv, access, name, desc, signature, exceptions);
- } else {
- return new RuleMethodAdapter(mv, access, name, desc, signature, exceptions);
- }
- }
- }
-
- return mv;
- }
-
- /**
- * a method visitor used to add a rule event trigger call to a method
- */
-
- private class RuleMethodAdapter extends GeneratorAdapter
- {
- private int access;
- private String name;
- private String descriptor;
- private String signature;
- private String[] exceptions;
- private Label startLabel;
- private Label endLabel;
-
- RuleMethodAdapter(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;
- }
-
- // somewhere we need to add a catch exception block
- // super.catchException(startLabel, endLabel, new Type("org.jboss.jbossts.orchestration.rule.exception.ExecuteException")));
-
- public void visitLineNumber(final int line, final Label start) {
- if (!visitedLine && (targetLine <= line)) {
- 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
- System.out.println("RuleMethodAdapter.visitLineNumber : 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);
- visitedLine = true;
- }
- super.visitLineNumber(line, start);
- }
-
- 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 RuleConstructorAdapter extends RuleMethodAdapter
- {
- private boolean superCalled;
-
- RuleConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
- {
- super(mv, access, name, descriptor, signature, exceptions);
- this.superCalled = false;
- }
-
- // don't pass on line visits until we have seen an INVOKESPECIAL
- public void visitLineNumber(final int line, final Label start) {
- if (superCalled) {
- super.visitLineNumber(line, start);
- }
- }
-
- 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 :-)
- superCalled &= (opcode == Opcodes.INVOKESPECIAL);
- }
- }
-
- private Rule rule;
- private String targetClass;
- private String targetMethod;
- private String targetDescriptor;
- private int targetLine;
- private String fieldName;
- private boolean visitedLine;
-}
Deleted: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -1,114 +0,0 @@
-/*
-* 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;
-
-import org.jboss.jbossts.orchestration.rule.Rule;
-import org.jboss.jbossts.orchestration.rule.exception.TypeException;
-import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
-import org.objectweb.asm.*;
-
-/**
- * asm Adapter class used to check that the target method for a rule exists in a class
- */
-public class RuleCheckAdapter extends ClassAdapter
-{
- RuleCheckAdapter(ClassVisitor cv, String targetClass, String handlerMethod, int handlerLine)
- {
- super(cv);
- this.targetClass = targetClass;
- this.targetMethod = TypeHelper.parseMethodName(handlerMethod);
- this.targetDescriptor = TypeHelper.parseMethodDescriptor(handlerMethod);
- this.targetLine = handlerLine;
- this.visitOk = false;
- }
-
- 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 (targetMethod.equals(name)) {
- if (targetDescriptor.equals("") || TypeHelper.equalDescriptors(targetDescriptor, desc))
- {
- return new RuleCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
- }
- }
-
- return mv;
- }
-
- public boolean isVisitOk()
- {
- return visitOk;
- }
-
- /**
- * a method visitor used to add a rule event trigger call to a method
- */
-
- private class RuleCheckMethodAdapter extends MethodAdapter
- {
- private int access;
- private String name;
- private String descriptor;
- private String signature;
- private String[] exceptions;
- private boolean visited;
-
- RuleCheckMethodAdapter(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;
- this.visited = false;
- }
-
- public void visitLineNumber(final int line, final Label start) {
- if (!visited && (targetLine <= line)) {
- // the relevant line occurs in the called method
- visited = true;
- visitOk = true;
- String name = targetClass + "." + targetMethod + targetDescriptor;
- if (targetLine >= 0) {
- name += targetLine;
- }
- }
- mv.visitLineNumber(line, start);
- }
-
- }
-
- private Rule rule;
- private String targetClass;
- private String targetMethod;
- private String targetDescriptor;
- private int targetLine;
- private boolean visitOk;
-}
\ No newline at end of file
Added: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Script.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Script.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Script.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,43 @@
+package org.jboss.jbossts.orchestration.agent;
+
+/**
+ * information about a single rule derived from a rule script
+ */
+
+public class Script
+{
+ private String name;
+ private String targetClass;
+ private String targetMethod;
+ private Location targetLocation;
+ private String ruleText;
+
+ Script (String name, String targetClass, String targetMethod, Location targetLocation, String ruleText)
+ {
+ this.name = name;
+ this.targetClass = targetClass;
+ this.targetMethod = targetMethod;
+ this.targetLocation = targetLocation;
+ this.ruleText = ruleText;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTargetClass() {
+ return targetClass;
+ }
+
+ public String getTargetMethod() {
+ return targetMethod;
+ }
+
+ public Location getTargetLocation() {
+ return targetLocation;
+ }
+
+ public String getRuleText() {
+ return ruleText;
+ }
+}
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 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/Transformer.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -27,6 +27,8 @@
import org.jboss.jbossts.orchestration.rule.type.TypeHelper;
import org.jboss.jbossts.orchestration.rule.exception.ParseException;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
+import org.jboss.jbossts.orchestration.agent.adapter.RuleTriggerAdapter;
+import org.jboss.jbossts.orchestration.agent.adapter.RuleCheckAdapter;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.EmptyVisitor;
@@ -71,12 +73,13 @@
String name = null;
String targetClass = null;
String targetMethod = null;
- int targetLine = -1;
+ LocationType locationType = null;
+ Location targetLocation = null;
int lineNumber = 0;
int maxLines = lines.length;
boolean inRule = false;
for (String line : lines) {
- lineNumber++;
+ lineNumber++;
if (line.trim().startsWith("#")) {
if (inRule) {
// add a blank line in place of the comment so the line numbers
@@ -95,12 +98,11 @@
targetClass = line.substring(6).trim();
} else if (line.startsWith("METHOD ")) {
targetMethod = line.substring(7).trim();
- } else if (line.startsWith("LINE ")) {
- String lineSpec = line.substring(5).trim();
- try {
- targetLine = Integer.valueOf(lineSpec);
- } catch (NumberFormatException e) {
- throw new Exception("org.jboss.jbossts.orchestration.agent.Transformer : invalid LINE specification " + lineSpec + "for RULE " + name + " in script " + scriptPaths.get(scriptIdx));
+ } else if ((locationType = LocationType.type(line)) != null) {
+ String parameters = LocationType.parameterText(line);
+ targetLocation = Location.create(locationType, parameters);
+ if (targetLocation == null) {
+ throw new Exception("org.jboss.jbossts.orchestration.agent.Transformer : invalid target location at line " + lineNumber + " in script " + scriptPaths.get(scriptIdx));
}
} else if (line.startsWith("ENDRULE")) {
if (name == null) {
@@ -109,26 +111,29 @@
throw new Exception("org.jboss.jbossts.orchestration.agent.Transformer : no CLASS for RULE " + name + " in script " + scriptPaths.get(scriptIdx));
} else if (targetMethod == null) {
throw new Exception("org.jboss.jbossts.orchestration.agent.Transformer : no METHOD for RULE " + name + " in script " + scriptPaths.get(scriptIdx));
- } else if (targetMethod.startsWith("<init>") && targetLine < 0) {
- throw new Exception("org.jboss.jbossts.orchestration.agent.Transformer : rule for constructor METHOD " + targetMethod + " must specify source LINE in RULE " + name + " in script " + scriptPaths.get(scriptIdx));
} else {
List<Script> scripts = targetToScriptMap.get(targetClass);
if (scripts == null) {
scripts = new ArrayList<Script>();
targetToScriptMap.put(targetClass, scripts);
}
- Script script = new Script(name, targetClass, targetMethod, targetLine, nextRule);
+ Script script = new Script(name, targetClass, targetMethod, targetLocation, nextRule);
scripts.add(script);
System.out.println("RULE " + script.getName());
System.out.println("CLASS " + script.getTargetClass());
System.out.println("METHOD " + script.getTargetMethod());
- System.out.println("LINE " + script.getTargetLine());
+ if (targetLocation != null) {
+ System.out.println(targetLocation);
+ } else {
+ System.out.println("AT ENTRY");
+ }
System.out.println(script.getRuleText());
System.out.println("ENDRULE");
}
name = null;
targetClass = null;
targetMethod = null;
+ targetLocation = null;
nextRule = "";
sepr = "";
inRule = false;
@@ -296,15 +301,15 @@
{
final String handlerClass = script.getTargetClass();
final String handlerMethod = script.getTargetMethod();
- final int handlerLine = script.getTargetLine();
+ final Location handlerLocation = script.getTargetLocation();
System.out.println("org.jboss.jbossts.orchestration.agent.Transformer : Inserting trigger event");
System.out.println(" class " + handlerClass);
System.out.println(" method " + handlerMethod);
- System.out.println(" line " + handlerLine);
+ System.out.println(" " + handlerLocation);
final Rule rule;
String ruleName = script.getName();
try {
- rule = Rule.create(ruleName, handlerClass, handlerMethod, handlerLine, script.getRuleText(), loader);
+ rule = Rule.create(ruleName, handlerClass, handlerMethod, handlerLocation, script.getRuleText(), loader);
} catch (ParseException pe) {
System.out.println("org.jboss.jbossts.orchestration.agent.Transformer : error parsing rule : " + pe);
return targetClassBytes;
@@ -317,17 +322,17 @@
}
System.out.println(rule);
- // ok, we have a rule with a matchingclass and a candidiate method and line number
+ // ok, we have a rule with a matchingclass and a candidiate method and location
// we need to see if the class has a matching method and, if so, add a call to
// 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 = new RuleCheckAdapter(empty, className, handlerMethod, handlerLine);
+ RuleCheckAdapter checkAdapter = handlerLocation.getRuleCheckAdapter(empty, className, handlerMethod);
// PrintWriter pw = new PrintWriter(System.out);
// ClassVisitor traceAdapter = new TraceClassVisitor(cw, pw);
- // RuleCheckAdapter adapter = new RuleAdapter(traceAdapter, rule, className, handlerMethod, handlerLine, loader);
+ // RuleCheckAdapter adapter = handlerLocation.getRuleCheckAdapter(traceAdapter, rule, className, handlerMethod);
try {
cr.accept(checkAdapter, 0);
} catch (Throwable th) {
@@ -335,14 +340,14 @@
th.printStackTrace(System.out);
return targetClassBytes;
}
- // only insert the rule trigger call if there is a suitable line in the target method
+ // only insert the rule trigger call if there is a suitable location in the target method
if (checkAdapter.isVisitOk()) {
cr = new ClassReader(targetClassBytes);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// PrintWriter pw = new PrintWriter(System.out);
// ClassVisitor traceAdapter = new TraceClassVisitor(cw, pw);
- // RuleAdapter adapter = new RuleAdapter(traceAdapter, rule, className, handlerMethod, handlerLine);
- RuleAdapter adapter = new RuleAdapter(cw, rule, className, handlerMethod, handlerLine);
+ // RuleTriggerAdapter adapter = handlerLocation.getRuleAdapter(traceAdapter, rule, className, handlerMethod);
+ RuleTriggerAdapter adapter = handlerLocation.getRuleAdapter(cw, rule, className, handlerMethod);
try {
cr.accept(adapter, 0);
} catch (Throwable th) {
@@ -389,47 +394,6 @@
private final HashMap<String, List<Script>> targetToScriptMap;
/**
- * information about a single rule derived from a rule script
- */
-
- private static class Script
- {
- private String name;
- private String targetClass;
- private String targetMethod;
- private int targetLine;
- private String ruleText;
-
- Script (String name, String targetClass, String targetMethod, int targetLine, String ruleText)
- {
- this.name = name;
- this.targetClass = targetClass;
- this.targetMethod = targetMethod;
- this.targetLine = targetLine;
- this.ruleText = ruleText;
- }
-
- public String getName() {
- return name;
- }
-
- public String getTargetClass() {
- return targetClass;
- }
-
- public String getTargetMethod() {
- return targetMethod;
- }
-
- public int getTargetLine() {
- return targetLine;
- }
-
- public String getRuleText() {
- return ruleText;
- }
- }
- /**
* switch to control dumping of generated bytecode to .class files
*/
private final static boolean dumpGeneratedClasses = (System.getProperty(DUMP_GENERATED_CLASSES) != null);
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,141 @@
+/*
+* 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.agent.Location;
+
+/**
+ * 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,
+ String fieldName, int flags, int count)
+ {
+ super(cv, targetClass, targetMethod);
+ this.ownerClass = ownerClass;
+ this.fieldName = fieldName;
+ this.flags = flags;
+ 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 AccessCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class AccessCheckMethodAdapter extends MethodAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private boolean visited;
+
+ AccessCheckMethodAdapter(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 visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ if (visitedCount < count && matchCall(opcode, owner, name, desc)) {
+ // a relevant invocation occurs in the called method
+ visitedCount++;
+ if (visitedCount == count) {
+ // and we have enough occurences to match the count
+ setVisitOk();
+ }
+ }
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ private boolean matchCall(int opcode, String owner, String name, String desc)
+ {
+ if (!fieldName.equals(name)) {
+ return false;
+ }
+
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ case Opcodes.GETFIELD:
+ {
+ if ((flags & Location.ACCESS_READ) == 0) {
+ return false;
+ }
+ }
+ break;
+ case Opcodes.PUTSTATIC:
+ case Opcodes.PUTFIELD:
+ {
+ if ((flags & Location.ACCESS_WRITE) == 0) {
+ return false;
+ }
+ }
+ break;
+ }
+ if (ownerClass != null) {
+ if (!ownerClass.equals(owner)) {
+ // TODO check for unqualified names
+ return false;
+ }
+ }
+ // TODO work out how to use desc???
+ return true;
+ }
+ }
+
+ private String ownerClass;
+ private String fieldName;
+ private int flags;
+ 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/AccessTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/AccessTriggerAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,276 @@
+/*
+* 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.Location;
+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 som egiven class
+ */
+public class AccessTriggerAdapter extends RuleTriggerAdapter
+{
+ public AccessTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, String ownerClass,
+ String fieldName, int flags, int count, boolean whenComplete)
+ {
+ super(cv, rule, targetClass, targetMethod);
+ this.ownerClass = ownerClass;
+ this.fieldName = fieldName;
+ this.flags = flags;
+ this.count = count;
+ this.whenComplete = whenComplete;
+ 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 == "<init>") {
+ return new AccessTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+ } else {
+ return new AccessTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+ }
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class AccessTriggerMethodAdapter 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;
+
+ AccessTriggerMethodAdapter(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;
+ }
+
+ // somewhere we need to add a catch exception block
+ // super.catchException(startLabel, endLabel, new Type("org.jboss.jbossts.orchestration.rule.exception.ExecuteException")));
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ if (whenComplete) {
+ // access the field before generating the trigger call
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+ if (visitedCount < count && matchCall(opcode, owner, name, desc)) {
+ // 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
+ System.out.println("AccessTriggerMethodAdapter.visitFieldInsn : 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);
+ }
+ }
+ if (!whenComplete) {
+ // access the field after generating the trigger call
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ 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);
+ }
+
+ private boolean matchCall(int opcode, String owner, String name, String desc)
+ {
+ if (!fieldName.equals(name)) {
+ return false;
+ }
+
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ case Opcodes.GETFIELD:
+ {
+ if ((flags & Location.ACCESS_READ) == 0) {
+ return false;
+ }
+ }
+ break;
+ case Opcodes.PUTSTATIC:
+ case Opcodes.PUTFIELD:
+ {
+ if ((flags & Location.ACCESS_WRITE) == 0) {
+ return false;
+ }
+ }
+ break;
+ }
+ if (ownerClass != null) {
+ if (!ownerClass.equals(owner)) {
+ // TODO check for unqualified names
+ return false;
+ }
+ }
+ // TODO work out how to use desc???
+ return true;
+ }
+ }
+
+ /**
+ * 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 AccessTriggerConstructorAdapter extends AccessTriggerMethodAdapter
+ {
+ AccessTriggerConstructorAdapter(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 ownerClass;
+ private String fieldName;
+ private int flags;
+ private int count;
+ private boolean whenComplete;
+ private int visitedCount;
+}
\ No newline at end of file
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,127 @@
+/*
+* 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 InvokeCheckAdapter extends RuleCheckAdapter
+{
+ public InvokeCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, String calledClass,
+ String calledMethodName, String calledMethodDescriptor, int count)
+ {
+ super(cv, targetClass, targetMethod);
+ this.calledClass = calledClass;
+ this.calledMethodName = calledMethodName;
+ this.calledMethodDescriptor = calledMethodDescriptor;
+ 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 InvokeCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class InvokeCheckMethodAdapter extends MethodAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private boolean visited;
+
+ InvokeCheckMethodAdapter(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 visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ if (visitedCount < count && matchCall(owner, name, desc)) {
+ // a relevant invocation occurs in the called method
+ visitedCount++;
+ if (visitedCount == count) {
+ // and we have enough occurences to match the count
+ setVisitOk();
+ }
+ }
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ private boolean matchCall(String owner, String name, String desc)
+ {
+ if (!calledMethodName.equals(name)) {
+ return false;
+ }
+ if (calledClass != null) {
+ if (!calledClass.equals(owner)) {
+ // TODO check for unqualified names
+ return false;
+ }
+ }
+ if (calledMethodDescriptor.length() > 0) {
+ if (!TypeHelper.equalDescriptors(calledMethodDescriptor, desc)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private String calledClass;
+ private String calledMethodName;
+ private String calledMethodDescriptor;
+ 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/InvokeTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/InvokeTriggerAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,262 @@
+/*
+* 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.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 som egiven class
+ */
+public class InvokeTriggerAdapter extends RuleTriggerAdapter
+{
+ public InvokeTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, String calledClass,
+ String calledMethodName, String calledMethodDescriptor, int count, boolean whenComplete)
+ {
+ super(cv, rule, targetClass, targetMethod);
+ this.calledClass = calledClass;
+ this.calledMethodName = calledMethodName;
+ this.calledMethodDescriptor = calledMethodDescriptor;
+ this.count = count;
+ this.whenComplete = whenComplete;
+ 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 == "<init>") {
+ return new InvokeTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+ } else {
+ return new InvokeTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+ }
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class InvokeTriggerMethodAdapter 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;
+
+ InvokeTriggerMethodAdapter(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;
+ }
+
+ // somewhere we need to add a catch exception block
+ // super.catchException(startLabel, endLabel, new Type("org.jboss.jbossts.orchestration.rule.exception.ExecuteException")));
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ if (whenComplete) {
+ // invoke the method before generating the trigger call
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+ if (visitedCount < count && matchCall(owner, name, desc)) {
+ // 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
+ System.out.println("AccessTriggerMethodAdapter.visitMethodInsn : 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);
+ }
+ }
+ if (!whenComplete) {
+ // invoke the method before generating the trigger call
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ 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);
+ }
+
+ private boolean matchCall(String owner, String name, String desc)
+ {
+ if (!calledMethodName.equals(name)) {
+ return false;
+ }
+ if (calledClass != null) {
+ if (!calledClass.equals(owner)) {
+ // TODO check for unqualified names
+ return false;
+ }
+ }
+ if (calledMethodDescriptor.length() > 0) {
+ if (!TypeHelper.equalDescriptors(calledMethodDescriptor, desc)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * 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 InvokeTriggerConstructorAdapter extends InvokeTriggerMethodAdapter
+ {
+ InvokeTriggerConstructorAdapter(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 calledClass;
+ private String calledMethodName;
+ private String calledMethodDescriptor;
+ private int count;
+ private boolean whenComplete;
+
+ private int visitedCount;
+}
\ No newline at end of file
Copied: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java (from rev 23806, labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java)
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,94 @@
+/*
+* 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.*;
+
+/**
+ * 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)
+ {
+ super(cv, targetClass, targetMethod);
+ this.targetLine = targetLine;
+ }
+
+ 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 LineCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class LineCheckMethodAdapter extends MethodAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private boolean visited;
+
+ LineCheckMethodAdapter(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;
+ this.visited = false;
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ if (!visited && (targetLine <= line)) {
+ // the relevant line occurs in the called method
+ visited = true;
+ setVisitOk();
+ String name = targetClass + "." + targetMethodName + targetDescriptor;
+ if (targetLine >= 0) {
+ name += targetLine;
+ }
+ }
+ mv.visitLineNumber(line, start);
+ }
+
+ }
+
+ private int targetLine;
+}
\ No newline at end of file
Property changes on: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineCheckAdapter.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java (from rev 23806, labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java)
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,217 @@
+/*
+* 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.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 som egiven class
+ */
+public class LineTriggerAdapter extends RuleTriggerAdapter
+{
+ public LineTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, int targetLine)
+ {
+ super(cv, rule, targetClass, targetMethod);
+ this.targetLine = targetLine;
+ this.visitedLine = false;
+ }
+
+ 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 == "<init>") {
+ return new LineTriggerConstructorAdapter(mv, access, name, desc, signature, exceptions);
+ } else {
+ return new LineTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+ }
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class LineTriggerMethodAdapter extends GeneratorAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private Label startLabel;
+ private Label endLabel;
+
+ LineTriggerMethodAdapter(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;
+ }
+
+ // somewhere we need to add a catch exception block
+ // super.catchException(startLabel, endLabel, new Type("org.jboss.jbossts.orchestration.rule.exception.ExecuteException")));
+
+ public void visitLineNumber(final int line, final Label start) {
+ if (!visitedLine && (targetLine <= line)) {
+ 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
+ System.out.println("AccessTriggerMethodAdapter.visitLineNumber : 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);
+ visitedLine = true;
+ }
+ super.visitLineNumber(line, start);
+ }
+
+ 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 LineTriggerConstructorAdapter extends LineTriggerMethodAdapter
+ {
+ private boolean superCalled;
+
+ LineTriggerConstructorAdapter(MethodVisitor mv, int access, String name, String descriptor, String signature, String[] exceptions)
+ {
+ super(mv, access, name, descriptor, signature, exceptions);
+ this.superCalled = false;
+ }
+
+ // don't pass on line visits until we have seen an INVOKESPECIAL
+ public void visitLineNumber(final int line, final Label start) {
+ if (superCalled) {
+ super.visitLineNumber(line, start);
+ }
+ }
+
+ 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 :-)
+ superCalled &= (opcode == Opcodes.INVOKESPECIAL);
+ }
+ }
+
+ private int targetLine;
+ private boolean visitedLine;
+}
\ No newline at end of file
Property changes on: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/LineTriggerAdapter.java
___________________________________________________________________
Name: svn:mergeinfo
+
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,52 @@
+/*
+* 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.type.TypeHelper;
+import org.objectweb.asm.*;
+
+/**
+ * generic asm Adapter class specialised by both check adapters (RuleCheckAdapter) and trigger
+ * adapters (RuleTriggerAdapter)
+ */
+public class RuleAdapter extends ClassAdapter
+{
+ protected RuleAdapter(ClassVisitor cv, String targetClass, String targetMethod)
+ {
+ super(cv);
+ this.targetClass = targetClass;
+ this.targetMethodName = TypeHelper.parseMethodName(targetMethod);
+ this.targetDescriptor = TypeHelper.parseMethodDescriptor(targetMethod);
+ }
+
+ protected String targetClass;
+ protected String targetMethodName;
+ protected String targetDescriptor;
+
+ protected boolean matchTargetMethod(String name, String desc)
+ {
+ return (targetMethodName.equals(name) &&
+ (targetDescriptor.equals("") || TypeHelper.equalDescriptors(targetDescriptor, desc)));
+ }
+}
\ No newline at end of file
Property changes on: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleAdapter.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java (from rev 23806, labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleCheckAdapter.java)
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,50 @@
+/*
+* 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.*;
+
+/**
+ * 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)
+ {
+ super(cv, targetClass, targetMethod);
+ this.visitOk = false;
+ }
+
+ public boolean isVisitOk()
+ {
+ return visitOk;
+ }
+
+ protected void setVisitOk()
+ {
+ visitOk = true;
+ }
+
+ private boolean visitOk;
+}
\ No newline at end of file
Copied: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java (from rev 23806, labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/RuleAdapter.java)
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/RuleTriggerAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,41 @@
+/*
+* 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.objectweb.asm.*;
+
+/**
+ * asm Adapter class used to add a rule event trigger call to a method of some given class
+ */
+public class RuleTriggerAdapter extends RuleAdapter
+{
+ protected RuleTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod)
+ {
+ super(cv, targetClass, targetMethod);
+ this.rule = rule;
+ }
+
+ protected Rule rule;
+}
Added: 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 (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeCheckAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,96 @@
+/*
+* 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 SynchronizeCheckAdapter extends RuleCheckAdapter
+{
+ public SynchronizeCheckAdapter(ClassVisitor cv, String targetClass, String targetMethod, int count)
+ {
+ super(cv, targetClass, targetMethod);
+ 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 SynchronizeCheckMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class SynchronizeCheckMethodAdapter extends MethodAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private boolean visited;
+
+ SynchronizeCheckMethodAdapter(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;
+ }
+
+ @Override
+ public void visitInsn(int opcode) {
+ if (opcode == Opcodes.MONITORENTER && visitedCount < count) {
+ // a synchronized block occurs in the called method
+ visitedCount++;
+ if (visitedCount == count) {
+ // and we have enough occurences to match the count
+ setVisitOk();
+ }
+ }
+ super.visitInsn(opcode);
+ }
+ }
+
+ 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/SynchronizeTriggerAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java (rev 0)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/agent/adapter/SynchronizeTriggerAdapter.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -0,0 +1,198 @@
+/*
+* 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.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 som egiven class
+ */
+public class SynchronizeTriggerAdapter extends RuleTriggerAdapter
+{
+ public SynchronizeTriggerAdapter(ClassVisitor cv, Rule rule, String targetClass, String targetMethod, int count, boolean whenComplete)
+ {
+ super(cv, rule, targetClass, targetMethod);
+ this.calledClass = calledClass;
+ this.calledMethodName = calledMethodName;
+ this.calledMethodDescriptor = calledMethodDescriptor;
+ this.count = count;
+ this.whenComplete = whenComplete;
+ 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);
+ // we can use the same adapter for methods and constructors
+ if (matchTargetMethod(name, desc)) {
+ return new SynchronizeTriggerMethodAdapter(mv, access, name, desc, signature, exceptions);
+ }
+ return mv;
+ }
+
+ /**
+ * a method visitor used to add a rule event trigger call to a method
+ */
+
+ private class SynchronizeTriggerMethodAdapter extends GeneratorAdapter
+ {
+ private int access;
+ private String name;
+ private String descriptor;
+ private String signature;
+ private String[] exceptions;
+ private Label startLabel;
+ private Label endLabel;
+
+ SynchronizeTriggerMethodAdapter(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;
+ }
+
+ // somewhere we need to add a catch exception block
+ // super.catchException(startLabel, endLabel, new Type("org.jboss.jbossts.orchestration.rule.exception.ExecuteException")));
+
+ @Override
+ public void visitInsn(int opcode) {
+ if (whenComplete) {
+ super.visitInsn(opcode);
+ }
+ if (opcode == Opcodes.MONITORENTER && visitedCount < count) {
+ // a relevant invocation occurs in the called method
+ visitedCount++;
+ if (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
+ System.out.println("SynchronizeTriggerMethodAdapter.visitMethodInsn : 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);
+ }
+ }
+ if (!whenComplete) {
+ 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);
+ }
+ }
+
+ private String calledClass;
+ private String calledMethodName;
+ private String calledMethodDescriptor;
+ private int count;
+ private boolean whenComplete;
+
+ private int visitedCount;
+}
\ No newline at end of file
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 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -36,6 +36,7 @@
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
import org.jboss.jbossts.orchestration.synchronization.CountDown;
import org.jboss.jbossts.orchestration.synchronization.Waiter;
+import org.jboss.jbossts.orchestration.agent.Location;
import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -64,10 +65,9 @@
*/
private String targetMethod;
/**
- * the line number at which to insert the trigger call in the target method for this rule
- * supplied in the rule script
+ * the location at which the rule trigger point is attached
*/
- private int targetLine;
+ private Location targetLocation;
/**
* the parsed event derived from the script for this rule
*/
@@ -134,7 +134,7 @@
*/
private boolean checkFailed;
- private Rule(String name, String targetClass, String targetMethod, int targetLine, String ruleSpec, ClassLoader loader)
+ private Rule(String name, String targetClass, String targetMethod, Location targetLocation, String ruleSpec, ClassLoader loader)
throws ParseException, TypeException, CompileException
{
ParseNode ruleTree;
@@ -163,7 +163,7 @@
checked = false;
this.targetClass = targetClass;
this.targetMethod = targetMethod;
- this.targetLine = targetLine;
+ this.targetLocation = targetLocation;
triggerClass = null;
triggerMethod = null;
triggerDescriptor = null;
@@ -192,8 +192,8 @@
return targetMethod;
}
- public int getTargetLine() {
- return targetLine;
+ public Location getTargetLocation() {
+ return targetLocation;
}
public Event getEvent()
@@ -209,10 +209,10 @@
return action;
}
- public static Rule create(String name, String targetClass, String targetMethod, int targetLine, String ruleSpec, ClassLoader loader)
+ public static Rule create(String name, String targetClass, String targetMethod, Location targetLocation, String ruleSpec, ClassLoader loader)
throws ParseException, TypeException, CompileException
{
- return new Rule(name, targetClass, targetMethod, targetLine, ruleSpec, loader);
+ return new Rule(name, targetClass, targetMethod, targetLocation, ruleSpec, loader);
}
public void setEvent(String eventSpec) throws ParseException, TypeException
@@ -442,6 +442,14 @@
stringWriter.write("RULE ");
stringWriter.write(name);
stringWriter.write("\n");
+ stringWriter.write("CLASS ");
+ stringWriter.write(targetClass);
+ stringWriter.write('\n');
+ stringWriter.write("METHOD ");
+ stringWriter.write(targetMethod);
+ stringWriter.write('\n');
+ stringWriter.write(targetLocation.toString());
+ stringWriter.write('\n');
if (event != null) {
event.writeTo(stringWriter);
} else {
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeHelper.java 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/TypeHelper.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -268,6 +268,95 @@
}
/**
+ * convert a method descriptor from the form used to represent it externally to canonical form
+ *
+ * @param desc the method descriptor which must be trimmed of any surrounding white space
+ * @return an internalised form for the descriptor
+ */
+ public static String internalizeDescriptor(String desc)
+ {
+ StringBuffer buffer = new StringBuffer();
+ String sepr = "";
+ buffer.append("(");
+ int max = desc.length();
+ int arrayCount = 0;
+
+ for (int idx = 0; idx < max;) {
+ buffer.append(sepr);
+ char next = desc.charAt(idx);
+ switch(next) {
+ case 'B':
+ {
+ buffer.append("byte");
+ }
+ break;
+ case 'C':
+ {
+ buffer.append("char");
+ }
+ break;
+ case 'S':
+ {
+ buffer.append("short");
+ }
+ break;
+ case 'I':
+ {
+ buffer.append("int");
+ }
+ break;
+ case 'J':
+ {
+ buffer.append("long");
+ }
+ break;
+ case 'Z':
+ {
+ buffer.append("boolean");
+ }
+ break;
+ case 'F':
+ {
+ buffer.append("float");
+ }
+ break;
+ case 'D':
+ {
+ buffer.append("double");
+ }
+ break;
+ case 'L':
+ {
+ int tailIdx = idx+1;
+ while (tailIdx < max && desc.charAt(tailIdx) != ';') {
+ tailIdx++;
+ }
+ if (tailIdx < max) {
+ buffer.append(desc.substring(idx + 1, tailIdx));
+ }
+ idx = tailIdx;
+ }
+ break;
+ case '[':
+ {
+ arrayCount++;
+ }
+ break;
+ }
+ if (next != '[') {
+ while (arrayCount > 0) {
+ buffer.append("[]");
+ arrayCount--;
+ }
+ }
+ idx++;
+ sepr = ",";
+ }
+
+ return buffer.toString();
+ }
+
+ /**
* split off the method name preceding the signature and return it
* @param targetMethod - the unqualified method name, possibly including signature
* @return
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 2008-11-20 17:20:26 UTC (rev 23999)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/test/TestScript.java 2008-11-20 17:28:48 UTC (rev 24000)
@@ -28,6 +28,8 @@
import org.jboss.jbossts.orchestration.rule.exception.ParseException;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.CompileException;
+import org.jboss.jbossts.orchestration.agent.LocationType;
+import org.jboss.jbossts.orchestration.agent.Location;
import org.objectweb.asm.Opcodes;
import java.util.List;
@@ -114,7 +116,8 @@
String[] lines = script.split("\n");
String targetClassName;
String targetMethodName;
- int targetLine = -1;
+ LocationType locationType = null;
+ Location targetLocation = null;
String text = "";
String sepr = "";
int idx = 0;
@@ -150,9 +153,13 @@
while (lines[idx].trim().equals("") || lines[idx].trim().startsWith("#")) {
idx++;
}
- if (lines[idx].startsWith("LINE ")) {
- String targetLineString = lines[idx].substring(5).trim();
- targetLine = Integer.valueOf(targetLineString);
+ locationType = LocationType.type(lines[idx]);
+ if (locationType != null) {
+ 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);
+ }
idx++;
}
for (;idx < len; idx++) {
@@ -165,10 +172,7 @@
text += sepr + lines[idx];
sepr = "\n";
}
- if (targetMethodName.startsWith("<init>") && (targetLine < 0)) {
- throw new ParseException("constructor method " + targetMethodName + " must specify target line in rule " + ruleName);
- }
- Rule rule = Rule.create(ruleName, targetClassName, targetMethodName, targetLine, text, loader);
+ Rule rule = Rule.create(ruleName, targetClassName, targetMethodName, targetLocation, text, loader);
System.err.println("TestScript: parsed rule " + rule.getName());
System.err.println(rule);
More information about the jboss-svn-commits
mailing list