[jboss-cvs] JBossAS SVN: r59532 - in branches/Branch_AOP_1_5/aop: src/main/org/jboss/aop and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Jan 11 11:29:47 EST 2007


Author: flavia.rainone at jboss.com
Date: 2007-01-11 11:29:27 -0500 (Thu, 11 Jan 2007)
New Revision: 59532

Added:
   branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/ComparableMixin.java
Modified:
   branches/Branch_AOP_1_5/aop/docs/reference/reference/en/modules/annotated.xml
   branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java
   branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java
   branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/Instrumentor.java
   branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java
   branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/AnnotatedTestCase.java
   branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/IntroductionAspect.java
Log:
[JBAOP-317] Task done

Modified: branches/Branch_AOP_1_5/aop/docs/reference/reference/en/modules/annotated.xml
===================================================================
--- branches/Branch_AOP_1_5/aop/docs/reference/reference/en/modules/annotated.xml	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/docs/reference/reference/en/modules/annotated.xml	2007-01-11 16:29:27 UTC (rev 59532)
@@ -595,6 +595,7 @@
          <itemizedlist>
             <listitem>be public</listitem>
             <listitem>be static</listitem>
+            <listitem>have an empty parameter list, or receive the target of introduction as parameter</listitem>
             <listitem>contain the logic to create the mixin class</listitem>
             <listitem>return an instance of the mixin class</listitem>
          </itemizedlist>

Modified: branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/AspectAnnotationLoader.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -21,8 +21,12 @@
   */
 package org.jboss.aop;
 
+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;
@@ -598,11 +602,78 @@
 
          String name = cf.getName() + "." + minfo.getName(); //Name of the method defined on
 
-         InterfaceIntroduction intro = createIntroduction(name, target, typeExpression, null);
+         InterfaceIntroduction intro = null;
+         String construction = name;
+         switch(Descriptor.numOfParameters(minfo.getDescriptor()))
+         {
+            case 0:
+               construction += "()";
+               intro = createIntroduction(name, target, typeExpression, null, null, null);//cf.getName(), minfo.getName());
+               break;
+            case 1:
+               construction += "(this)";
+               intro = createIntroduction(name, target, typeExpression, null, cf.getName(), minfo.getName());               
+  
+               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);
 
-
-         String construction = name + "(this)";
+               }
+               break;
+            default:
+               throw new RuntimeException("Mixin creator method '" + name +
+                     "' should not have more than one parameter.");
+         }
          
+         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));
@@ -663,7 +734,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);
       }
    }
@@ -905,7 +976,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(""))
@@ -933,12 +1005,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;
@@ -946,11 +1018,11 @@
 
    private String getReturnType(MethodInfo minfo)
    {
-      String descriptor = minfo.getDescriptor();
-      int paramsEnd = descriptor.indexOf(";)");
-      String classname = descriptor.substring(paramsEnd + 3, descriptor.length() - 1);
-      classname = classname.replace('/', '.');
-      return classname;
+	   String descriptor = minfo.getDescriptor();
+	      int paramsEnd = descriptor.indexOf(")");
+	      String classname = descriptor.substring(paramsEnd + 2, descriptor.length() - 1);
+	      classname = classname.replace('/', '.');
+	      return classname;
    }
    
    private String getFieldType(FieldInfo finfo)

Modified: branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/ClassicInstrumentor.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -144,14 +144,7 @@
       CtMethod wmethod = CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(),
                                         method.getExceptionTypes(), null, clazz);
       wmethod.setModifiers(method.getModifiers());
-      try
-      {
-         wmethod.setBody(code);
-      }
-      catch (CannotCompileException e)
-      {
-         throw new RuntimeException("<mixin> construction may have syntax error: '" + initializer + "'", e);
-      }
+      wmethod.setBody(code);
       clazz.addMethod(wmethod);
       
       return wmethod;

Modified: branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/Instrumentor.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/Instrumentor.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/instrument/Instrumentor.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -249,6 +249,34 @@
       // mixin is adding any interfaces already
       // defined in base class or another mixin.
       CtClass mixinClass = classPool.get(mixin.getClassName());
+      
+      // 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 = (mixin.getConstruction() == null) ? ("new " + mixinClass.getName() + "()") : mixin.getConstruction();
       CtClass type = forName(mixinClass.getName());
       CtField field = new CtField(type, mixinFieldName(mixinClass), clazz);
@@ -289,7 +317,18 @@
             }
             // 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: branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/main/org/jboss/aop/introduction/InterfaceIntroduction.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -106,6 +106,9 @@
    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()
    {
 
@@ -117,12 +120,32 @@
       this.classExpr = new ClassExpression(exp);
    }
 
+   // call this constructor only when constructor method receives the mixin target
+   // as parameter, for posterior validation of constructor method signature
+   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)
    {
       this.name = name;
       this.ast = ast;
       this.interfaces = interfaces;
    }
+   
+   // call this constructor only when constructor method receives the mixin target
+   // as parameter, for posterior validation of constructor method signature
+   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)
    {
@@ -171,7 +194,20 @@
       return mixins;
    }
 
+   // this value is set only when there is a mixin constructor method and this
+   // method receives the target as parameter
+   public String getConstructorClass()
+   {
+      return this.constructorClass;
+   }
 
+   // this value is set only when there is a mixin constructor method and this
+   // method receives the target as parameter
+   public String getConstructorMethod()
+   {
+      return this.constructorMethod;
+   }
+   
    public void addAdvisor(Advisor advisor)
    {
       advisors.add(new WeakReference(advisor));

Modified: branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/AnnotatedTestCase.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/AnnotatedTestCase.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/AnnotatedTestCase.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -182,7 +182,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: branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/ComparableMixin.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/ComparableMixin.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/ComparableMixin.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -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.jdk15.annotated;
+
+/**
+ * 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: branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/IntroductionAspect.java
===================================================================
--- branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/IntroductionAspect.java	2007-01-11 16:25:34 UTC (rev 59531)
+++ branches/Branch_AOP_1_5/aop/src/test/org/jboss/test/aop/jdk15/annotated/IntroductionAspect.java	2007-01-11 16:29:27 UTC (rev 59532)
@@ -24,6 +24,7 @@
 import org.jboss.aop.Mixin;
 import org.jboss.aop.Introduction;
 import org.jboss.aop.Aspect;
+
 /**
  *
  * @author <a href="mailto:kabir.khan at jboss.org">Kabir Khan</a>
@@ -37,6 +38,11 @@
        return new ExternalizableMixin(pojo);
    }
    
+   @Mixin (target=org.jboss.test.aop.jdk15.annotated.NoInterfacesPOJO2.class, interfaces={Comparable.class})
+   public static ComparableMixin createComparableMixin() {
+       return new ComparableMixin();
+   }
+   
    @Introduction (target=org.jboss.test.aop.jdk15.annotated.NoInterfacesPOJO.class, interfaces={org.jboss.test.aop.jdk15.annotated.EmptyInterface.class})
    public static Object noInterfacesPOJOIntro;
 




More information about the jboss-cvs-commits mailing list