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
{