[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