[jboss-cvs] JBossAS SVN: r59493 - in projects/aop/trunk/aop/src: main/org/jboss/aop/instrument and 2 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed Jan 10 14:06:39 EST 2007
Author: flavia.rainone at jboss.com
Date: 2007-01-10 14:06:18 -0500 (Wed, 10 Jan 2007)
New Revision: 59493
Added:
projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/ComparableMixin.java
Modified:
projects/aop/trunk/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java
projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java
projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/Instrumentor.java
projects/aop/trunk/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java
projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/AnnotatedTestCase.java
projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/IntroductionAspect.java
Log:
[JBAOP-317] Most of task is done
Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -21,8 +21,18 @@
*/
package org.jboss.aop;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javassist.CtClass;
+import javassist.CtPrimitiveType;
+import javassist.Modifier;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
+import javassist.bytecode.Descriptor;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.annotation.ArrayMemberValue;
@@ -62,12 +72,6 @@
import org.jboss.aop.pointcut.ast.TypeExpressionParser;
import org.jboss.aop.util.MethodHashing;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Iterator;
-
/**
* Comment
*
@@ -595,7 +599,6 @@
MemberValue mv = binfo.getMemberValue("target");
String target = (mv != null) ? ((ClassMemberValue) mv).getValue() : "java.lang.Class";//Note! this should be the same as the default in @Mixin
-
mv = binfo.getMemberValue("typeExpression");
String typeExpression = (mv != null) ? ((StringMemberValue) mv).getValue() : "";//Note! this should be the same as the default in @Mixin
@@ -608,14 +611,82 @@
boolean isTransient = (mv != null) ? ((BooleanMemberValue) mv).getValue() : true;//Note! this should be the same as the default in @Mixin
String name = cf.getName() + "." + minfo.getName(); //Name of the method defined on
+
+ InterfaceIntroduction intro = null;
+ String construction = name;
+ switch(Descriptor.numOfParameters(minfo.getDescriptor()))
+ {
+ case 0:
+ construction += "()";
+ break;
+ case 1:
+ construction += "(this)";
+
+/*
+ String parameter = Descriptor.getParamDescriptor(minfo.getDescriptor());
+
+ if (parameter.charAt(1) != 'L')
+ {
+ String errorMessage = "Mixin creator method '" + name +
+ "' parameter is primitive type ";
+ char desc = parameter.charAt(1);
+ if (desc == ((CtPrimitiveType) CtClass.booleanType).getDescriptor())
+ {
+ errorMessage += "boolean";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.byteType).getDescriptor())
+ {
+ errorMessage += "byte";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.charType).getDescriptor())
+ {
+ errorMessage += "char";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.doubleType).getDescriptor())
+ {
+ errorMessage += "double";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.floatType).getDescriptor())
+ {
+ errorMessage += "float";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.intType).getDescriptor())
+ {
+ errorMessage += "int";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.longType).getDescriptor())
+ {
+ errorMessage += "long";
+ }
+ else if (desc == ((CtPrimitiveType) CtClass.shortType).getDescriptor())
+ {
+ errorMessage += "short";
+ }
+ else
+ {
+ break;
+ }
+ errorMessage += ".\n It should have the introduction target type as parameter, or have no parameter at all.";
+ throw new RuntimeException(errorMessage);
- InterfaceIntroduction intro = createIntroduction(name, target, typeExpression, null);
-
-
- String construction = name + "(this)";
+ }*/
+ break;
+ default:
+ throw new RuntimeException("Mixin creator method '" + name +
+ "' should not have more than one parameter.");
+ }
+ intro = createIntroduction(name, target, typeExpression, null, null, null);//cf.getName(), minfo.getName());
+ if (!Modifier.isStatic(minfo.getAccessFlags()) ||
+ !Modifier.isPublic(minfo.getAccessFlags()))
+ {
+ throw new RuntimeException("Mixin creator method '" + name +
+ "' must be public and static.");
+ }
+
//Parse the descriptor to get the returntype of the method.
String classname = getReturnType(minfo);
+
intro.getMixins().add(new InterfaceIntroduction.Mixin(classname, interfaces, construction, isTransient));
manager.addInterfaceIntroduction(intro);
@@ -674,7 +745,7 @@
String name = cf.getName() + "." + finfo.getName(); //Name of the field defined on
- InterfaceIntroduction interfaceIntro = createIntroduction(name, target, typeExpression, interfaces);
+ InterfaceIntroduction interfaceIntro = createIntroduction(name, target, typeExpression, interfaces, null, null);
manager.addInterfaceIntroduction(interfaceIntro);
}
}
@@ -916,7 +987,8 @@
return cf.getName() + "." + finfo.getName();
}
- private InterfaceIntroduction createIntroduction(String name, String target, String typeExpression, String[] interfaces)
+ private InterfaceIntroduction createIntroduction(String name, String target, String typeExpression, String[] interfaces,
+ String constructorClass, String constructorMethod)
throws Exception
{
if (typeExpression != null && typeExpression.trim().equals(""))
@@ -944,12 +1016,12 @@
if (target != null)
{
- intro = new InterfaceIntroduction(name, target, interfaces);
+ intro = new InterfaceIntroduction(name, target, interfaces, constructorClass, constructorMethod);
}
else
{
ASTStart start = new TypeExpressionParser(new StringReader(typeExpression)).Start();
- intro = new InterfaceIntroduction(name, start, interfaces);
+ intro = new InterfaceIntroduction(name, start, interfaces, constructorClass, constructorMethod);
}
return intro;
Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -147,17 +147,9 @@
" }" +
"}";
- CtMethod wmethod = null;
- try
- {
- wmethod = CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(),
+ CtMethod wmethod = CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(),
method.getExceptionTypes(), code, clazz);
wmethod.setModifiers(modifier);
- }
- catch (CannotCompileException e)
- {
- throw new RuntimeException("<mixin> construction may have syntax error: '" + initializer + "'", e);
- }
clazz.addMethod(wmethod);
return wmethod;
Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/Instrumentor.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/Instrumentor.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/instrument/Instrumentor.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -231,7 +231,51 @@
// mixin is adding any interfaces already
// defined in base class or another mixin.
CtClass mixinClass = classPool.get(mixin.getClassName());
- String initializer = (mixin.getConstruction() == null) ? ("new " + mixinClass.getName() + "()") : mixin.getConstruction();
+
+ // check mixin constructor method if this is the case
+ if (pointcut.getConstructorClass() != null)
+ {
+ CtClass type = forName(pointcut.getConstructorClass());
+ CtMethod[] methods = type.getDeclaredMethods();
+ boolean correct = false;
+ for (int i = 0; i < methods.length; i++)
+ {
+ if (methods[i].getName().equals(pointcut.getConstructorMethod())
+ && methods[i].getParameterTypes().length == 1)
+ {
+ if (clazz.subclassOf(methods[i].getParameterTypes()[0]))
+ {
+ correct = true;
+ }
+
+ }
+ }
+ if (!correct)
+ {
+ throw new RuntimeException("Could not find a method named '" +
+ pointcut.getConstructorMethod() + "' on class " +
+ pointcut.getConstructorClass() + " that receives " +
+ clazz.getName() + " or one of its superclasses as parameter.");
+ }
+ }
+
+ String initializer = null;
+ if (mixin.getConstruction() == null)
+ {
+ CtConstructor[] constructors = mixinClass.getConstructors();
+ for (int i = 0; i < constructors.length; i++)
+ System.out.println("constructors[" + i + "] = " + constructors[i].getSignature());
+ if (mixinClass.getConstructor("()V") == null)
+ {
+ throw new RuntimeException("Default constructor of mixin class '" +
+ mixinClass + "' not found.");
+ }
+ initializer = "new " + mixinClass.getName() + "()";
+ }
+ else
+ {
+ initializer = mixin.getConstruction();
+ }
CtClass type = forName(mixinClass.getName());
CtField field = new CtField(type, mixinFieldName(mixinClass), clazz);
int modifiers = Modifier.PRIVATE;
@@ -271,7 +315,17 @@
}
// If another interface of this mixin has a duplicate method, then its ok, but don't re-add
if (addedMethods.contains(hash)) continue;
- createMixinInvokeMethod(clazz, mixinClass, initializer, method, hash.longValue());
+ try{
+ createMixinInvokeMethod(clazz, mixinClass, initializer, method, hash.longValue());
+ }
+ catch (CannotCompileException e)
+ {
+ String generatedCode = "class " + clazz.getName() + "\n{\n ...\n" +
+ " private " + type.getName() + " = " + initializer + ";\n"
+ + " ...\n}";
+ throw new RuntimeException("Mixin construction expression '"
+ + initializer + "' may have sintax error:\n" + generatedCode, e);
+ }
baseMethods.put(hash, method);
addedMethods.add(hash);
}
Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -105,17 +105,29 @@
protected ArrayList mixins = new ArrayList();
protected ClassExpression classExpr;
protected ASTStart ast;
+
+ protected String constructorClass; // name of the class containing the mixin constructor method
+ protected String constructorMethod; // name of the mixin constructor method
public InterfaceIntroduction()
{
}
+
public InterfaceIntroduction(String name, String exp, String[] interfaces)
{
this.name = name;
this.interfaces = interfaces;
this.classExpr = new ClassExpression(exp);
}
+
+ public InterfaceIntroduction(String name, String exp, String[] interfaces,
+ String constructorClass, String constructorMethod)
+ {
+ this(name, exp, interfaces);
+ this.constructorClass = constructorClass;
+ this.constructorMethod = constructorMethod;
+ }
public InterfaceIntroduction(String name, ASTStart ast, String[] interfaces)
{
@@ -124,6 +136,15 @@
this.interfaces = interfaces;
}
+
+ public InterfaceIntroduction(String name, ASTStart ast, String[] interfaces,
+ String constructorClass, String constructorMethod)
+ {
+ this(name, ast, interfaces);
+ this.constructorClass = constructorClass;
+ this.constructorMethod = constructorMethod;
+ }
+
public void setClassExpression(String exp)
{
this.classExpr = new ClassExpression(exp);
@@ -176,7 +197,18 @@
return mixins;
}
+ // this value is set only when there is a mixin constructor class and this
+ // method receives the target as parameter
+ public String getConstructorClass()
+ {
+ return this.constructorClass;
+ }
+ public String getConstructorMethod()
+ {
+ return this.constructorMethod;
+ }
+
public void addAdvisor(Advisor advisor)
{
advisors.add(new WeakReference(advisor));
Modified: projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/AnnotatedTestCase.java
===================================================================
--- projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/AnnotatedTestCase.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/AnnotatedTestCase.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -183,7 +183,10 @@
System.out.println("deserialized pojo2.stuff2: " + pojo2.stuff);
assertTrue("writeExternal was not called for pojo2", ExternalizableMixin.write);
assertTrue("readExternal was not called for pojo2", ExternalizableMixin.read);
-
+
+ ComparableMixin.COMPARED = false;
+ ((Comparable) pojo2).compareTo(null);
+ assertTrue("mixin method was not called", ComparableMixin.COMPARED);
}
public void testIntroduction() throws Exception
Added: projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/ComparableMixin.java
===================================================================
--- projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/ComparableMixin.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/ComparableMixin.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * 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.
+ */
+package org.jboss.test.aop.jdk15annotated;
+
+/**
+ * Mixin that implements the <code>Comparable</code> interface.
+ *
+ * @author <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+ */
+public class ComparableMixin implements Comparable
+{
+ static boolean COMPARED = false;
+
+ public int compareTo(Object o)
+ {
+ COMPARED = true;
+ return 0;
+ }
+}
\ No newline at end of file
Modified: projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/IntroductionAspect.java
===================================================================
--- projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/IntroductionAspect.java 2007-01-10 18:57:06 UTC (rev 59492)
+++ projects/aop/trunk/aop/src/test/org/jboss/test/aop/jdk15annotated/IntroductionAspect.java 2007-01-10 19:06:18 UTC (rev 59493)
@@ -37,6 +37,11 @@
return new ExternalizableMixin(pojo);
}
+ @Mixin (target=org.jboss.test.aop.jdk15annotated.NoInterfacesPOJO2.class, interfaces={Comparable.class})
+ public static ComparableMixin createComparableMixin(/*NoInterfacesPOJO2 pojo*/) {
+ return new ComparableMixin();
+ }
+
@Introduction (target=org.jboss.test.aop.jdk15annotated.NoInterfacesPOJO.class, interfaces={org.jboss.test.aop.jdk15annotated.EmptyInterface.class})
public static Object noInterfacesPOJOIntro;
@@ -48,4 +53,4 @@
@Introduction (typeExpression="has(* *->pojoInterfaces2Method(..))", interfaces={org.jboss.test.aop.jdk15annotated.EmptyInterface.class})
public static Object noInterfacesPOJO2Intro;
-}
+}
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list