You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2011/07/25 20:03:25 UTC
svn commit: r1150816 - in /tapestry/tapestry5/trunk/plastic/src:
main/java/org/apache/tapestry5/internal/plastic/
main/java/org/apache/tapestry5/plastic/
test/groovy/org/apache/tapestry5/plastic/
Author: hlship
Date: Mon Jul 25 18:03:24 2011
New Revision: 1150816
URL: http://svn.apache.org/viewvc?rev=1150816&view=rev
Log:
Rename MethodBundle to InheritanceData
Add PlasticClass.isInterfaceImplemented()
Added:
tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java
- copied, changed from r1150815, tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java
Removed:
tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java
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
tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy
Copied: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java (from r1150815, tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java?p2=tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java&p1=tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java&r1=1150815&r2=1150816&rev=1150816&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java Mon Jul 25 18:03:24 2011
@@ -14,36 +14,34 @@
package org.apache.tapestry5.internal.plastic;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.Set;
/**
* Used to track which methods are implemented by a base class, which is often needed when transforming
* a subclass.
*/
-public class MethodBundle
+public class InheritanceData
{
- private final MethodBundle parent;
+ private final InheritanceData parent;
private final Set<String> methodNames = PlasticInternalUtils.newSet();
private final Set<String> methods = PlasticInternalUtils.newSet();
+ private final Set<String> interfaceNames = PlasticInternalUtils.newSet();
- public MethodBundle()
+ public InheritanceData()
{
this(null);
}
- private MethodBundle(MethodBundle parent)
+ private InheritanceData(InheritanceData parent)
{
this.parent = parent;
}
/**
* Is this bundle for a transformed class, or for a base class (typically Object)?
- *
- * @return
- * true if this bundle is for transformed class, false otherwise
+ *
+ * @return true if this bundle is for transformed class, false otherwise
*/
public boolean isTransformed()
{
@@ -53,24 +51,21 @@ public class MethodBundle
/**
* Returns a new MethodBundle that represents the methods of a child class
* of this bundle. The returned bundle will always be {@linkplain #isTransformed() transformed}.
- *
- * @param childClassName
- * name of subclass
+ *
+ * @param childClassName name of subclass
* @return new method bundle
*/
- public MethodBundle createChild(String childClassName)
+ public InheritanceData createChild(String childClassName)
{
- return new MethodBundle(this);
+ return new InheritanceData(this);
}
/**
* Adds a new instance method. Only non-private, non-abstract methods should be added (that is, methods which might
* be overridden in subclasses). This can later be queried to see if any base class implements the method.
- *
- * @param name
- * name of method
- * @param desc
- * method descriptor
+ *
+ * @param name name of method
+ * @param desc method descriptor
*/
public void addMethod(String name, String desc)
{
@@ -82,11 +77,9 @@ public class MethodBundle
/**
* Returns true if a transformed parent class contains the indicated method.
- *
- * @param name
- * method name
- * @param desc
- * method descriptor
+ *
+ * @param name method name
+ * @param desc method descriptor
* @return the <em>internal name</em> of the implementing base class for this method,
* or null if no base class implements the method
*/
@@ -95,6 +88,7 @@ public class MethodBundle
return checkForMethod(toValue(name, desc));
}
+
private boolean checkForMethod(String value)
{
if (methods.contains(value))
@@ -104,6 +98,31 @@ public class MethodBundle
}
/**
+ * Returns true if the class represented by this data, or any parent data, implements
+ * the named interface.
+ */
+ public boolean isInterfaceImplemented(String name)
+ {
+ InheritanceData cursor = this;
+
+ while (cursor != null)
+ {
+ if (cursor.interfaceNames.contains(name))
+ {
+ return true;
+ }
+
+ cursor = cursor.parent;
+ }
+
+ return false;
+ }
+
+ public void addInterface(String name) {
+ interfaceNames.add(name);
+ }
+
+ /**
* Combines a method name and its desc (which describes parameter types and return value) to form
* a value, which is how methods are tracked.
*/
@@ -119,7 +138,7 @@ public class MethodBundle
{
Set<String> result = PlasticInternalUtils.newSet();
- MethodBundle cursor = this;
+ InheritanceData cursor = this;
while (cursor != null)
{
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=1150816&r1=1150815&r2=1150816&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 Mon Jul 25 18:03:24 2011
@@ -188,7 +188,7 @@ public class PlasticClassImpl extends Lo
{
check();
- return parentMethodBundle.isImplemented(node.name, node.desc);
+ return parentInheritanceData.isImplemented(node.name, node.desc);
}
public String getMethodIdentifier()
@@ -794,7 +794,7 @@ public class PlasticClassImpl extends Lo
String desc = nameCache.toDesc(description);
- if (methodBundle.isImplemented(name, desc))
+ if (inheritanceData.isImplemented(name, desc))
throw new IllegalArgumentException(String.format(
"Unable to create new accessor method %s on class %s as the method is already implemented.",
description.toString(), className));
@@ -1045,7 +1045,7 @@ public class PlasticClassImpl extends Lo
private final ClassNode invocationClassNode;
- private final List<MethodAdvice> advice = new ArrayList<MethodAdvice>();
+ private final List<MethodAdvice> advice = PlasticInternalUtils.newList();
private final boolean isVoid;
@@ -1095,7 +1095,7 @@ public class PlasticClassImpl extends Lo
invocationClassNode.visitField(ACC_PUBLIC, RETURN_VALUE, nameCache.toDesc(description.returnType),
null, null);
- List<String> consTypes = new ArrayList<String>();
+ List<String> consTypes = PlasticInternalUtils.newList();
consTypes.add(Object.class.getName());
consTypes.add(InstanceContext.class.getName());
consTypes.add(MethodInvocationBundle.class.getName());
@@ -1450,7 +1450,7 @@ public class PlasticClassImpl extends Lo
private final Set<String> methodNames = new HashSet<String>();
- private final List<ConstructorCallback> constructorCallbacks = new ArrayList<ConstructorCallback>();
+ private final List<ConstructorCallback> constructorCallbacks = PlasticInternalUtils.newList();
// All non-introduced instance fields
@@ -1472,7 +1472,7 @@ public class PlasticClassImpl extends Lo
private final StaticContext staticContext;
- private final MethodBundle parentMethodBundle, methodBundle;
+ private final InheritanceData parentInheritanceData, inheritanceData;
// MethodNodes in which field transformations should occur; this is most existing and
// introduced methods, outside of special access methods.
@@ -1525,10 +1525,10 @@ public class PlasticClassImpl extends Lo
/**
* @param classNode
* @param pool
- * @param parentMethodBundle
+ * @param parentInheritanceData
* @param parentStaticContext
*/
- public PlasticClassImpl(ClassNode classNode, PlasticClassPool pool, MethodBundle parentMethodBundle,
+ public PlasticClassImpl(ClassNode classNode, PlasticClassPool pool, InheritanceData parentInheritanceData,
StaticContext parentStaticContext)
{
this.classNode = classNode;
@@ -1542,8 +1542,13 @@ public class PlasticClassImpl extends Lo
annotationAccess = new DelegatingAnnotationAccess(pool.createAnnotationAccess(classNode.visibleAnnotations),
pool.createAnnotationAccess(superClassName));
- this.parentMethodBundle = parentMethodBundle;
- methodBundle = parentMethodBundle.createChild(className);
+ this.parentInheritanceData = parentInheritanceData;
+ inheritanceData = parentInheritanceData.createChild(className);
+
+ for (String interfaceName : (List<String>) classNode.interfaces)
+ {
+ inheritanceData.addInterface(interfaceName);
+ }
methods = new ArrayList(classNode.methods.size());
@@ -1575,7 +1580,7 @@ public class PlasticClassImpl extends Lo
{
if (!Modifier.isPrivate(node.access))
{
- methodBundle.addMethod(node.name, node.desc);
+ inheritanceData.addMethod(node.name, node.desc);
}
methodNames.add(node.name);
@@ -1594,12 +1599,12 @@ public class PlasticClassImpl extends Lo
description2method.put(pmi.getDescription(), pmi);
if (isInheritableMethod(node))
- methodBundle.addMethod(node.name, node.desc);
+ inheritanceData.addMethod(node.name, node.desc);
methodNames.add(node.name);
}
- methodNames.addAll(parentMethodBundle.methodNames());
+ methodNames.addAll(parentInheritanceData.methodNames());
Collections.sort(methods);
@@ -1637,7 +1642,7 @@ public class PlasticClassImpl extends Lo
// Start by calling the super-class no args constructor
- if (parentMethodBundle.isTransformed())
+ if (parentInheritanceData.isTransformed())
{
// If the parent is transformed, our first step is always to invoke its constructor.
@@ -1706,7 +1711,7 @@ public class PlasticClassImpl extends Lo
completeConstructor();
- transformedClass = pool.realizeTransformedClass(classNode, methodBundle, staticContext);
+ transformedClass = pool.realizeTransformedClass(classNode, inheritanceData, staticContext);
return createInstantiatorFromClass(transformedClass);
}
@@ -2004,7 +2009,7 @@ public class PlasticClassImpl extends Lo
methodNames.add(methodNode.name);
if (!Modifier.isPrivate(methodNode.access))
- methodBundle.addMethod(methodNode.name, methodNode.desc);
+ inheritanceData.addMethod(methodNode.name, methodNode.desc);
}
private PlasticMethod createNewMethod(MethodDescription description)
@@ -2024,7 +2029,7 @@ public class PlasticClassImpl extends Lo
MethodNode methodNode = new MethodNode(description.modifiers, description.methodName, desc,
description.genericSignature, exceptions);
- boolean isOverride = methodBundle.isImplemented(methodNode.name, desc);
+ boolean isOverride = inheritanceData.isImplemented(methodNode.name, desc);
if (isOverride)
createOverrideOfBaseClassImpl(description, methodNode);
@@ -2413,10 +2418,11 @@ public class PlasticClassImpl extends Lo
String interfaceName = nameCache.toInternalName(interfaceType);
- // I suppose this means that a subclass may restate that it implements an interface from a base class.
-
- if (!classNode.interfaces.contains(interfaceName))
+ if (!inheritanceData.isInterfaceImplemented(interfaceName))
+ {
classNode.interfaces.add(interfaceName);
+ inheritanceData.addInterface(interfaceName);
+ }
Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
@@ -2453,36 +2459,17 @@ public class PlasticClassImpl extends Lo
public boolean isMethodImplemented(MethodDescription description)
{
- return methodBundle.isImplemented(description.methodName, nameCache.toDesc(description));
+ return inheritanceData.isImplemented(description.methodName, nameCache.toDesc(description));
}
- /**
- * True if the node has any visible annotations, or it has visible annotations on any
- * parameter.
- *
- * @param mn
- * @return true if any annotations present
- */
- private static boolean hasAnnotations(MethodNode mn)
+ public boolean isInterfaceImplemented(Class interfaceType)
{
- if (nonEmpty(mn.visibleAnnotations))
- return true;
-
- if (mn.visibleParameterAnnotations != null)
- {
- for (List pa : mn.visibleParameterAnnotations)
- {
- if (nonEmpty(pa))
- return true;
- }
- }
+ assert interfaceType != null;
+ assert interfaceType.isInterface();
- return false;
- }
+ String interfaceName = nameCache.toInternalName(interfaceType);
- private static boolean nonEmpty(List l)
- {
- return l != null && !l.isEmpty();
+ return inheritanceData.isInterfaceImplemented(interfaceName);
}
public String getSuperClassName()
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=1150816&r1=1150815&r2=1150816&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 Mon Jul 25 18:03:24 2011
@@ -54,7 +54,7 @@ public class PlasticClassPool implements
private final Map<String, ClassInstantiator> instantiators = PlasticInternalUtils.newMap();
- private final MethodBundle emptyMethodBundle = new MethodBundle();
+ private final InheritanceData emptyInheritanceData = new InheritanceData();
private final StaticContext emptyStaticContext = new StaticContext();
@@ -73,13 +73,13 @@ public class PlasticClassPool implements
static class BaseClassDef
{
- final MethodBundle methodBundle;
+ final InheritanceData inheritanceData;
final StaticContext staticContext;
- public BaseClassDef(MethodBundle methodBundle, StaticContext staticContext)
+ public BaseClassDef(InheritanceData inheritanceData, StaticContext staticContext)
{
- this.methodBundle = methodBundle;
+ this.inheritanceData = inheritanceData;
this.staticContext = staticContext;
}
}
@@ -116,12 +116,12 @@ public class PlasticClassPool implements
return loader;
}
- public synchronized Class realizeTransformedClass(ClassNode classNode, MethodBundle methodBundle,
+ public synchronized Class realizeTransformedClass(ClassNode classNode, InheritanceData inheritanceData,
StaticContext staticContext)
{
Class result = realize(PlasticInternalUtils.toClassName(classNode.name), ClassType.PRIMARY, classNode);
- baseClassDefs.put(result.getName(), new BaseClassDef(methodBundle, staticContext));
+ baseClassDefs.put(result.getName(), new BaseClassDef(inheritanceData, staticContext));
return result;
}
@@ -363,10 +363,10 @@ public class PlasticClassPool implements
assert def != null;
- return new PlasticClassImpl(classNode, this, def.methodBundle, def.staticContext);
+ return new PlasticClassImpl(classNode, this, def.inheritanceData, def.staticContext);
}
- return new PlasticClassImpl(classNode, this, emptyMethodBundle, emptyStaticContext);
+ return new PlasticClassImpl(classNode, this, emptyInheritanceData, emptyStaticContext);
}
/**
Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java?rev=1150816&r1=1150815&r2=1150816&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java Mon Jul 25 18:03:24 2011
@@ -182,6 +182,14 @@ public interface PlasticClass extends An
boolean isMethodImplemented(MethodDescription description);
/**
+ * Returns true if this class, or a super-class, implements the indicated interface.
+ *
+ * @param interfaceType
+ * @return true if the interface is implemented
+ */
+ boolean isInterfaceImplemented(Class interfaceType);
+
+ /**
* Returns the name of the super-class of the class being transformed.
*/
String getSuperClassName();
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy?rev=1150816&r1=1150815&r2=1150816&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy Mon Jul 25 18:03:24 2011
@@ -1,15 +1,18 @@
package org.apache.tapestry5.plastic
-class MethodIntroduction extends AbstractPlasticSpecification {
+class MethodIntroduction extends AbstractPlasticSpecification
+{
static final String CLASS_NAME = "testsubjects.ChildClass"
- def instanceWithIntroducedMethod(MethodDescription md, isOverride) {
- def mgr = createMgr ({ PlasticClass pc ->
- if (pc.className == CLASS_NAME) {
+ def instanceWithIntroducedMethod(MethodDescription md, isOverride)
+ {
+ def mgr = createMgr({ PlasticClass pc ->
+ if (pc.className == CLASS_NAME)
+ {
def method = pc.introduceMethod(md)
-
+
assert method.override == isOverride
}
} as PlasticClassTransformer)
@@ -17,7 +20,8 @@ class MethodIntroduction extends Abstrac
return mgr.getClassInstantiator(CLASS_NAME).newInstance()
}
- def "introduce method not present in base class"() {
+ def "introduce method not present in base class"()
+ {
def o = instanceWithIntroducedMethod(new MethodDescription(returnType, methodName), false)
@@ -38,19 +42,20 @@ class MethodIntroduction extends Abstrac
where:
- returnType | methodName | access | expectedValue | expectedType
+ returnType | methodName | access | expectedValue | expectedType
- "java.lang.String" | "getString" | { it.getString() } | null | null
- "java.util.Date[]" | "getDates" | { it.getDates() } | null | null
- "int" | "getInt" | { it.getInt() } | 0 | Integer.class
- "int[]" | "getInts" | { it.getInts() } | null | null
- "char" | "getChar" | { it.getChar() } | 0 | Character.class
- "float" | "getFloat" | { it.getFloat() } | 0f | Float.class
- "long" | "getLong" | { it.getLong() } | 0l | Long.class
- "double" | "getDouble" | { it.getDouble() } | 0d | Double.class
+ "java.lang.String" | "getString" | { it.getString() } | null | null
+ "java.util.Date[]" | "getDates" | { it.getDates() } | null | null
+ "int" | "getInt" | { it.getInt() } | 0 | Integer.class
+ "int[]" | "getInts" | { it.getInts() } | null | null
+ "char" | "getChar" | { it.getChar() } | 0 | Character.class
+ "float" | "getFloat" | { it.getFloat() } | 0f | Float.class
+ "long" | "getLong" | { it.getLong() } | 0l | Long.class
+ "double" | "getDouble" | { it.getDouble() } | 0d | Double.class
}
- def "introduce void method override"() {
+ def "introduce void method override"()
+ {
setup:
@@ -65,28 +70,31 @@ class MethodIntroduction extends Abstrac
true
}
- def "introduce primitive method override"() {
+ def "introduce primitive method override"()
+ {
setup:
- def o = instanceWithIntroducedMethod (new MethodDescription("int", "primitiveMethod", "int"), true)
+ def o = instanceWithIntroducedMethod(new MethodDescription("int", "primitiveMethod", "int"), true)
expect:
o.primitiveMethod(97) == 97
}
- def "introduce object method override"() {
+ def "introduce object method override"()
+ {
setup:
- def o = instanceWithIntroducedMethod (new MethodDescription("java.lang.String", "objectMethod", "java.lang.String"), true)
+ def o = instanceWithIntroducedMethod(new MethodDescription("java.lang.String", "objectMethod", "java.lang.String"), true)
expect:
o.objectMethod("plastic") == "plastic"
}
- def "introduce interface"() {
+ def "introduce interface"()
+ {
def introduced
@@ -110,5 +118,35 @@ class MethodIntroduction extends Abstrac
introduced.size() == 1
introduced[0].methodName == "run"
}
+
+ def "check for introduced interface is visible in subclasses"()
+ {
+ setup:
+
+ boolean present;
+
+ def mgr = createMgr({
+ PlasticClass pc ->
+ if (pc.className.contains("Base"))
+ {
+ pc.introduceInterface(Serializable.class)
+ }
+
+ if (pc.className.contains("Child"))
+ {
+ present = pc.isInterfaceImplemented(Serializable.class)
+ }
+
+ } as PlasticClassTransformer)
+
+ when:
+
+ mgr.getClassInstantiator("testsubjects.ChildClass")
+
+ then:
+
+ present == true
+ }
+
}