User: austinchau
Date: 03/03/02 08:23:15
Modified: src/main/org/jboss/aop ClassAdvisor.java Instrumentor.java
ProxyAdvisor.java
Log:
added instrumentation code for constructor interception and static method
invokation
Revision Changes Path
1.18 +45 -1 jboss-aop/src/main/org/jboss/aop/ClassAdvisor.java
Index: ClassAdvisor.java
===================================================================
RCS file: /cvsroot/jboss/jboss-aop/src/main/org/jboss/aop/ClassAdvisor.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- ClassAdvisor.java 21 Feb 2003 01:56:02 -0000 1.17
+++ ClassAdvisor.java 2 Mar 2003 16:23:15 -0000 1.18
@@ -13,6 +13,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -31,7 +32,7 @@
*
* @author <a href="mailto:crazybob@... Lee</a>
* @author <a href="mailto:bill@... Burke</a>
- * @version $Revision: 1.17 $
+ * @version $Revision: 1.18 $
*/
public class ClassAdvisor extends Advisor implements Interceptor
{
@@ -328,6 +329,29 @@
throw e.getTargetException();
}
}
+
+ public static Object invokeNewWithoutAdvisement(Class cl, Object[] arguments) throws Throwable
+ {
+ try
+ {
+
+ Class[] argTypes = new Class[arguments.length];
+
+ for (int i=0;i<arguments.length ;i++ )
+ {
+ argTypes[i] = arguments[i].getClass();
+ }
+
+ Constructor constructor = cl.getConstructor(argTypes);
+
+ return constructor.newInstance(arguments);
+
+ }
+ catch(Throwable ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
/**
* Invokes interceptor chain.
@@ -362,6 +386,14 @@
return response.getResponse();
}
+
+ public static Object invokeNew(Object[] args, ClassAdvisor advisor, Class cl) throws Throwable
+ {
+ // need to add in code later to invoke the interceptor chain
+
+ return invokeNewWithoutAdvisement(cl, args);
+ }
+
/**
* Invokes interceptor chain.
* This is the beginning
@@ -427,6 +459,7 @@
return response.getResponse();
}
+
/**
* Invokes target object
* This is the end of the chain
@@ -503,4 +536,15 @@
}
}
+ public static Object trapConstructor(Object[] args, ClassAdvisor advisor, Class cl)
+ {
+ try
+ {
+ return ClassAdvisor.invokeNew(args, advisor, cl);
+ }
+ catch (Throwable e)
+ {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
}
1.14 +149 -64 jboss-aop/src/main/org/jboss/aop/Instrumentor.java
Index: Instrumentor.java
===================================================================
RCS file: /cvsroot/jboss/jboss-aop/src/main/org/jboss/aop/Instrumentor.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Instrumentor.java 20 Feb 2003 20:56:10 -0000 1.13
+++ Instrumentor.java 2 Mar 2003 16:23:15 -0000 1.14
@@ -18,6 +18,7 @@
import javassist.ClassPool;
import javassist.CodeConverter;
import javassist.CtClass;
+import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
@@ -42,7 +43,7 @@
*
* @author <a href="mailto:crazybob@... Lee</a>
* @author <a href="mailto:bill@... Burke</a>
- * @version $Revision: 1.13 $
+ * @version $Revision: 1.14 $
*/
public class Instrumentor
{
@@ -84,7 +85,8 @@
(method.getModifiers() & Modifier.ABSTRACT) == 0 &&
(method.getModifiers() & Modifier.NATIVE) == 0 &&
!method.getName().endsWith(ClassAdvisor.UNADVISED_SUFFIX) &&
- !method.getName().startsWith("_");
+ !method.getName().startsWith("_") &&
+ !method.getName().equals("");
}
/**
@@ -132,19 +134,22 @@
return true;
}
- /*
+
private CtMethod createTrapConstructor(CtClass clazz)
throws CannotCompileException
{
CtMethod trap = CtNewMethod.make(
"protected static Object trapConstructor(Object[] args) " +
- "{" +
- " return org.jboss.aop.ClassAdvisor.trapConstructor(Object[]args);" +
+ "{ " +
+ " return org.jboss.aop.ClassAdvisor.trapConstructor(args, (org.jboss.aop.ClassAdvisor) " +
+ HELPER_FIELD_NAME + "," +
+ CLASS_FIELD_NAME + ");" +
+
"}",
clazz);
return trap;
}
- */
+
private CtMethod createTrapRead(CtClass clazz)
throws CannotCompileException
@@ -179,6 +184,10 @@
{
return fieldName + "_w_" + ClassAdvisor.UNADVISED_SUFFIX;
}
+
+ private String constructorFactory(String className) {
+ return className + "_new_" + ClassAdvisor.UNADVISED_SUFFIX;
+ }
private void replaceFieldAccess(List fields, CtClass clazz)
{
@@ -196,6 +205,11 @@
}
+ private void replaceConstructorAccess(CtClass clazz)
+ {
+ converter.replaceNew(clazz, clazz, constructorFactory(clazz.getSimpleName()));
+ }
+
private void instrumentFields(CtClass clazz, int filter)
throws NotFoundException, CannotCompileException
{
@@ -235,9 +249,12 @@
String name = field.getName();
CtClass ftype = field.getType();
+
CtMethod wmethod
- = CtNewMethod.wrapped(ftype, fieldRead(name),
- readParam, null, trapRead,
+ = CtNewMethod.wrapped(ftype,
+ fieldRead(name),
+ readParam, null,
+ trapRead,
ConstParameter.integer(index),
clazz);
wmethod.setModifiers(mod);
@@ -255,34 +272,35 @@
}
}
- /*
+
private void instrumentConstructors(CtClass clazz, int filter)
throws NotFoundException, CannotCompileException
{
if (filter == 0) return;
- List constructors = getConstructors(clazz);
- replaceConstructorAccess(constructors, clazz);
+ replaceConstructorAccess(clazz);
- CtClass[] readParam = new CtClass[] { classPool.get("java.lang.Object") };
CtMethod trapConstructor = createTrapConstructor(clazz);
+ List constructors = getConstructors(clazz);
+
Iterator it = constructors.iterator();
- for (int index = offset; it.hasNext(); index++)
+ while (it.hasNext())
{
+
CtConstructor constructor = (CtConstructor)it.next();
if (!InterceptorFilter.isMatch(constructor, filter)) continue;
int mod = Modifier.STATIC;
- if ((field.getModifiers() & Modifier.PUBLIC) != 0)
+ if ((constructor.getModifiers() & Modifier.PUBLIC) != 0)
{
mod |= Modifier.PUBLIC;
}
- else if ((field.getModifiers() & Modifier.PROTECTED) != 0)
+ else if ((constructor.getModifiers() & Modifier.PROTECTED) != 0)
{
mod |= Modifier.PROTECTED;
}
- else if ((field.getModifiers() & Modifier.PRIVATE) != 0)
+ else if ((constructor.getModifiers() & Modifier.PRIVATE) != 0)
{
mod |= Modifier.PRIVATE;
}
@@ -291,28 +309,27 @@
mod |= Modifier.PUBLIC;
}
- String name = field.getName();
- CtClass ftype = field.getType();
+ CtClass[] exceptions = constructor.getExceptionTypes();
+ CtClass[] _exceptions = new CtClass[exceptions.length + 1];
+
+ java.lang.System.arraycopy(exceptions, 0, _exceptions, 0, exceptions.length);
+ _exceptions[exceptions.length] = forName("java.lang.reflect.InvocationTargetException");
+
+ String name = clazz.getSimpleName();
+ CtClass type = constructor.getDeclaringClass();
CtMethod wmethod
- = CtNewMethod.wrapped(ftype, fieldRead(name),
- readParam, null, trapRead,
- ConstParameter.integer(index),
- clazz);
- wmethod.setModifiers(mod);
- clazz.addMethod(wmethod);
- CtClass[] writeParam = new CtClass[2];
- writeParam[0] = classPool.get("java.lang.Object");
- writeParam[1] = ftype;
- wmethod = CtNewMethod.wrapped(CtClass.voidType,
- fieldWrite(name),
- writeParam, null, trapWrite,
- ConstParameter.integer(index),
- clazz);
+ = CtNewMethod.wrapped(type,
+ constructorFactory(name),
+ constructor.getParameterTypes(),
+ _exceptions,
+ trapConstructor,
+ null,
+ clazz);
+
wmethod.setModifiers(mod);
clazz.addMethod(wmethod);
}
}
- */
private void instrumentMethods(CtClass clazz, int filter)
throws NotFoundException, CannotCompileException, BadBytecode
@@ -407,6 +424,7 @@
instrumentMethods(clazz, methodFilter);
instrumentFields(clazz, fieldFilter);
+ instrumentConstructors(clazz, constructorFilter);
}
// need to instrument no matter what so that
@@ -422,9 +440,9 @@
{
throw NestedException.wrap(e);
}
- catch (BadBytecode e)
+ catch (BadBytecode e)
{
- throw NestedException.wrap(e);
+ throw NestedException.wrap(e);
}
}
@@ -439,7 +457,7 @@
CtMethod getter = CtNewMethod.make(
"public org.jboss.aop.InstanceAdvisor _getInstanceAdvisor()" +
- "{" +
+ "{ " +
" return _instanceAdvisor;" +
"}",
clazz);
@@ -454,36 +472,70 @@
CtMethod method, CtMethod delegate, int index) throws
NotFoundException, CannotCompileException, BadBytecode
{
+
+ // create a new exception array "_exceptions" with all the original exception thrown by method
+ // and then add java.lang.reflect.InvocationTargetException
+ CtClass[] exceptions = method.getExceptionTypes();
+ CtClass[] _exceptions = new CtClass[exceptions.length + 1];
+
+ java.lang.System.arraycopy(exceptions, 0, _exceptions, 0, exceptions.length);
+ _exceptions[exceptions.length] = forName("java.lang.reflect.InvocationTargetException");
+
+
// create base, delegating method.
CtMethod newMethod = CtNewMethod.wrapped(
method.getReturnType(),
name,
method.getParameterTypes(),
- method.getExceptionTypes(),
+ _exceptions,
delegate,
CtMethod.ConstParameter.integer(index),
clazz
);
+
+ /*
+ // the following two lines are commented out by Austin Chau
+ // addCatch() from javassist has bugs
+
+ // unwrap invocation target execeptions.
+ // newMethod.addCatch(";",forName("java.lang.reflect.InvocationTargetException"), "e");
- // unwrap invocation target execeptions.
- newMethod.addCatch("throw e.getTargetException();",
- forName("java.lang.reflect.InvocationTargetException"), "e");
+ */
// generate bytecode to delegate directly when no aspects are
// present.
- CtClass advisorClass = forName("org.jboss.aop.ClassInstanceAdvisor");
-
- Bytecode bc = new Bytecode(
- clazz.getClassFile().getConstPool(),
- Descriptor.dataSize(Descriptor.of(advisorClass)), 0);
-
- bc.addAload(0);
- bc.addGetfield(clazz, "_instanceAdvisor",
- Descriptor.of(advisorClass));
- bc.addInvokevirtual(advisorClass, "hasAspects",
- Descriptor.ofMethod(CtClass.booleanType, new CtClass[0]));
-
+ boolean isStatic = Modifier.isStatic(newMethod.getModifiers());
+
+ CtClass advisorClass = null;
+ Bytecode bc = null;
+
+ if (!isStatic)
+ {
+ advisorClass = forName("org.jboss.aop.ClassInstanceAdvisor");
+ bc = new Bytecode(
+ clazz.getClassFile().getConstPool(),
+ Descriptor.dataSize(Descriptor.of(advisorClass)), 0);
+
+ bc.addAload(0);
+ bc.addGetfield(clazz, "_instanceAdvisor",
+ Descriptor.of(advisorClass));
+
+ bc.addInvokevirtual(advisorClass, "hasAspects",
+ Descriptor.ofMethod(CtClass.booleanType, new CtClass[0]));
+ }
+ else
+ {
+ advisorClass = forName(HELPER_CLASS_NAME);
+ bc = new Bytecode(
+ clazz.getClassFile().getConstPool(),
+ Descriptor.dataSize(Descriptor.of(advisorClass)), 0);
+ bc.addGetstatic(clazz, HELPER_FIELD_NAME,
+ Descriptor.of(advisorClass));
+ bc.addInvokevirtual(advisorClass, "hasAspects",
+ Descriptor.ofMethod(CtClass.booleanType, new CtClass[0]));
+
+ }
// if aspects are present, jump to advising code.
bc.addOpcode(Opcode.IFNE);
@@ -491,7 +543,7 @@
bc.addIndex(0); // place holder.
// otherwise, delegate directly to unadvised method.
- boolean isStatic = Modifier.isStatic(newMethod.getModifiers());
+
// load arguments onto stack.
if (!isStatic) {
@@ -541,6 +593,26 @@
return newMethod;
}
+
+ private int constructorOffset(CtClass clazz)
+ throws NotFoundException
+ {
+ if (clazz == null) return 0;
+ if (clazz.getName().equals("java.lang.Object")) return 0;
+ int offset = constructorOffset(clazz.getSuperclass());
+
+ if (!isAdvised(clazz)) return offset;
+
+ CtConstructor[] constructors = clazz.getDeclaredConstructors();
+ for (int i = 0; i < constructors.length; i++)
+ {
+ offset++;
+ }
+ return offset;
+ }
+
+
+
/**
*
*/
@@ -587,6 +659,21 @@
return offset;
}
+ private List getConstructors(CtClass clazz)
+ throws NotFoundException
+ {
+ List list = new ArrayList();
+
+ CtConstructor[] constructors = clazz.getDeclaredConstructors();
+
+ for (int i = 0;i < constructors.length ;i++ )
+ {
+ list.add(constructors[i]);
+ }
+
+ return list;
+ }
+
/**
* Gets sorted collection of advisable methods.
*/
@@ -650,8 +737,8 @@
"public static java.lang.Object " +
" invokeStatic(java.lang.Object[] args, int i)" +
" throws java.lang.Throwable {" +
- " return " + HELPER_FIELD_NAME +
- ".invoke((Object) null, i, args);" +
+ " return ((org.jboss.aop.ClassAdvisor)" + HELPER_FIELD_NAME +
+ ").invoke((Object) null, i, args);" +
"}",
clazz
);
@@ -679,7 +766,6 @@
clazz.getName() + "\")"
)
);
-
}
/**
@@ -688,18 +774,20 @@
private void addHelperClass(CtClass clazz)
throws CannotCompileException, NotFoundException
{
+
CtField field = addStaticField(clazz,
HELPER_FIELD_NAME,
HELPER_CLASS_NAME,
CtField.Initializer.byExpr(
- ASPECT_MANAGER_CLASS_NAME + "#instance().getAdvisor(" +
+ ASPECT_MANAGER_CLASS_NAME + ".instance().getAdvisor(" +
CLASS_FIELD_NAME + ")"
)
);
+
// To make sure that correct Advisor gets called
CtMethod getter = CtNewMethod.make(
"public " + HELPER_CLASS_NAME + " _getAdvisor()" +
- "{" +
+ "{ " +
" return " + HELPER_FIELD_NAME + ";" +
"}",
clazz);
@@ -718,6 +806,7 @@
field.setModifiers(
Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL);
clazz.addField(field, initializer);
+
return field;
}
@@ -736,23 +825,20 @@
return field;
}
- /**
- * Entry point for command line tool.
-
// Needs to be made Up to date.
public static void main(String[] args) throws Exception
{
String destDir = args[0];
ClassPool pool = ClassPool.getDefault();
- Instrumentor instrumentor = new Instrumentor(pool);
+ Instrumentor instrumentor = new Instrumentor(pool, new CodeConverter());
for (int i=1; i < args.length; i++)
{
String className = args[i];
try
{
System.out.println("Instrumenting " + className + "...");
- instrumentor.makeAdvisable(pool.get(className), );
+ instrumentor.makeAdvisable(pool.get(className), 0xFF,0xFF,0xFF);
System.out.println("Done.");
}
catch (AlreadyAdvisedException e)
@@ -766,6 +852,5 @@
pool.writeFile(className, destDir);
}
}
- */
}
1.3 +1 -4 jboss-aop/src/main/org/jboss/aop/ProxyAdvisor.java
Index: ProxyAdvisor.java
===================================================================
RCS file: /cvsroot/jboss/jboss-aop/src/main/org/jboss/aop/ProxyAdvisor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ProxyAdvisor.java 23 Jan 2003 18:32:25 -0000 1.2
+++ ProxyAdvisor.java 2 Mar 2003 16:23:15 -0000 1.3
@@ -12,7 +12,7 @@
/**
*
* @author <a href="mailto:bill@... Burke</a>
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
*
*/
public class ProxyAdvisor extends Advisor
@@ -49,9 +49,6 @@
super.rebuildInterceptorFactories();
createInterceptorChain();
}
-
-
-
////////////////////////////////
// abstract method implementations
|