You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/21 00:45:30 UTC

svn commit: r1095542 - in /tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic: PlasticClassImpl.java PlasticClassPool.java

Author: hlship
Date: Wed Apr 20 22:45:30 2011
New Revision: 1095542

URL: http://svn.apache.org/viewvc?rev=1095542&view=rev
Log:
TAP5-853: Merge annotations into the target class, and handle cases where the source is a generated proxy class itself

Modified:
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java?rev=1095542&r1=1095541&r2=1095542&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java Wed Apr 20 22:45:30 2011
@@ -2278,9 +2278,18 @@ public class PlasticClassImpl extends Lo
     {
         assert PlasticInternalUtils.isNonBlank(sourceClassName);
 
-        ClassNode sourceClass = pool.constructClassNode(sourceClassName);
+        ClassNode sourceClass = pool.constructClassNode(sourceClassName, false);
 
-        classNode.visibleAnnotations = sourceClass.visibleAnnotations;
+        if (sourceClass == null)
+            return this;
+
+        if (sourceClass.visibleAnnotations != null)
+        {
+            if (classNode.visibleAnnotations == null)
+                classNode.visibleAnnotations = PlasticInternalUtils.newList();
+
+            mergeAnnotations(classNode.visibleAnnotations, sourceClass.visibleAnnotations);
+        }
 
         Map<String, MethodNode> sourceMethods = buildMethodNodeMap(sourceClass, true);
 
@@ -2301,13 +2310,60 @@ public class PlasticClassImpl extends Lo
 
             MethodNode source = entry.getValue();
 
-            target.visibleAnnotations = source.visibleAnnotations;
-            target.visibleParameterAnnotations = source.visibleParameterAnnotations;
+            if (source.visibleAnnotations != null)
+            {
+                if (target.visibleAnnotations == null)
+                    target.visibleAnnotations = PlasticInternalUtils.newList();
+
+                mergeAnnotations(target.visibleAnnotations, source.visibleAnnotations);
+            }
+
+            if (source.visibleParameterAnnotations != null)
+            {
+                int count = source.visibleParameterAnnotations.length;
+
+                if (target.visibleParameterAnnotations == null)
+                    target.visibleParameterAnnotations = new List[count];
+
+                for (int i = 0; i < count; i++)
+                {
+                    if (source.visibleParameterAnnotations[i] == null)
+                        continue;
+
+                    if (target.visibleParameterAnnotations[i] == null)
+                        target.visibleParameterAnnotations[i] = PlasticInternalUtils.newList();
+
+                    mergeAnnotations(target.visibleParameterAnnotations[i], source.visibleParameterAnnotations[i]);
+                }
+
+            }
         }
 
         return this;
     }
 
+    /**
+     * Copies nodes from the source list to the target list, as long as they don't conflict with an
+     * annotation already present in the target list (as annotations must be unique).
+     */
+    private static void mergeAnnotations(List<AnnotationNode> targetAnnotations, List<AnnotationNode> sourceAnnotations)
+    {
+        Set<String> targetDescs = PlasticInternalUtils.newSet();
+
+        for (AnnotationNode targetNode : targetAnnotations)
+        {
+            targetDescs.add(targetNode.desc);
+        }
+
+        for (AnnotationNode sourceNode : sourceAnnotations)
+        {
+            if (targetDescs.contains(sourceNode.desc))
+                continue;
+
+            targetAnnotations.add(sourceNode);
+        }
+    }
+
     private static Map<String, MethodNode> buildMethodNodeMap(ClassNode source, boolean withAnnotationsOnly)
     {
         boolean all = !withAnnotationsOnly;

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java?rev=1095542&r1=1095541&r2=1095542&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java Wed Apr 20 22:45:30 2011
@@ -49,18 +49,20 @@ public class PlasticClassPool implements
 
     private final Set<String> controlledPackages;
 
-    private final Map<String, ClassInstantiator> instantiators = new HashMap<String, ClassInstantiator>();
+    private final Map<String, ClassInstantiator> instantiators = PlasticInternalUtils.newMap();
 
     private final MethodBundle emptyMethodBundle = new MethodBundle();
 
     private final StaticContext emptyStaticContext = new StaticContext();
 
+    private final Map<String, byte[]> createdClassesBytecode = PlasticInternalUtils.newMap();
+
     private final Cache<String, TypeCategory> typeName2Category = new Cache<String, TypeCategory>()
     {
 
         protected TypeCategory convert(String typeName)
         {
-            ClassNode cn = constructClassNode(typeName);
+            ClassNode cn = constructClassNode(typeName, true);
 
             return Modifier.isInterface(cn.access) ? TypeCategory.INTERFACE : TypeCategory.CLASS;
         }
@@ -115,13 +117,17 @@ public class PlasticClassPool implements
         return result;
     }
 
-    public Class realize(ClassNode classNode)
+    public synchronized Class realize(ClassNode classNode)
     {
         PlasticInternalUtils.debugClass(classNode);
 
         byte[] bytecode = toBytecode(classNode);
 
-        return loader.defineClassWithBytecode(PlasticInternalUtils.toClassName(classNode.name), bytecode);
+        String className = PlasticInternalUtils.toClassName(classNode.name);
+
+        createdClassesBytecode.put(className, bytecode);
+
+        return loader.defineClassWithBytecode(className, bytecode);
     }
 
     private byte[] toBytecode(ClassNode classNode)
@@ -251,7 +257,7 @@ public class PlasticClassPool implements
 
     private Class loadInnerClass(String className)
     {
-        byte[] bytecode = readBytecode(className);
+        byte[] bytecode = readBytecode(className, true);
 
         return loader.defineClassWithBytecode(className, bytecode);
     }
@@ -267,7 +273,7 @@ public class PlasticClassPool implements
     {
         assert PlasticInternalUtils.isNonBlank(className);
 
-        ClassNode classNode = constructClassNode(className);
+        ClassNode classNode = constructClassNode(className, true);
 
         String baseClassName = PlasticInternalUtils.toClassName(classNode.superName);
 
@@ -297,11 +303,16 @@ public class PlasticClassPool implements
      * 
      * @param className
      *            fully qualified class name
+     * @param mustExist
+     *            TODO
      * @return corresponding ClassNode
      */
-    public ClassNode constructClassNode(String className)
+    public ClassNode constructClassNode(String className, boolean mustExist)
     {
-        byte[] bytecode = readBytecode(className);
+        byte[] bytecode = readBytecode(className, mustExist);
+
+        if (bytecode == null)
+            return null;
 
         return convertBytecodeToClassNode(bytecode);
     }
@@ -317,8 +328,13 @@ public class PlasticClassPool implements
         return result;
     }
 
-    private byte[] readBytecode(String className)
+    private byte[] readBytecode(String className, boolean mustExist)
     {
+        byte[] createdBytecode = createdClassesBytecode.get(className);
+
+        if (createdBytecode != null)
+            return createdBytecode;
+
         ClassLoader parentClassLoader = loader.getParent();
 
         String path = PlasticInternalUtils.toClassPath(className);
@@ -326,8 +342,13 @@ public class PlasticClassPool implements
         InputStream stream = parentClassLoader.getResourceAsStream(path);
 
         if (stream == null)
-            throw new RuntimeException(String.format("Unable to locate class file for '%s' in class loader %s.",
-                    className, parentClassLoader));
+        {
+            if (mustExist)
+                throw new RuntimeException(String.format("Unable to locate class file for '%s' in class loader %s.",
+                        className, parentClassLoader));
+
+            return null;
+        }
 
         try
         {