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
         {


Reply via email to