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/05/03 23:12:43 UTC
svn commit: r1099253 [1/2] - in /tapestry/tapestry5/trunk:
plastic/src/main/java/org/apache/tapestry5/plastic/
plastic/src/test/groovy/org/apache/tapestry5/plastic/
plastic/src/test/java/testsubjects/
tapestry-core/src/main/java/org/apache/tapestry5/in...
Author: hlship
Date: Tue May 3 21:12:42 2011
New Revision: 1099253
URL: http://svn.apache.org/viewvc?rev=1099253&view=rev
Log:
TAP5-1508: Revise how PlasticManager is created, rebuild relationship between ComponentClassResolver and ComponentInstantiatorSource
Added:
tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AccessorsAlreadyExistSubject.java
- copied, changed from r1098835, tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AccessorsAlreadyExistSubject.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHub.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java
- copied, changed from r1098835, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ForceDevelopmentModeModule.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/transform/ControlledPackageType.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AddTransformPagesToCISModule.java
Removed:
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AccessorsAlreadyExistSubject.java
Modified:
tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy
tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassResolverImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSource.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentClassResolverImplTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImplTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ForceDevelopmentModeModule.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java Tue May 3 21:12:42 2011
@@ -14,7 +14,7 @@
package org.apache.tapestry5.plastic;
-import java.util.Collections;
+import java.util.Collection;
import java.util.Set;
import org.apache.tapestry5.internal.plastic.NoopDelegate;
@@ -23,7 +23,9 @@ import org.apache.tapestry5.internal.pla
/**
* Manages the internal class loaders and other logics necessary to load and transform existing classes,
- * or to create new classes dynamically at runtime.
+ * or to create new classes dynamically at runtime. New instances are instantiates using
+ * {@link #withClassLoader(ClassLoader)} or {@link #withContextClassLoader()}, then configuring
+ * the returned options object before invoking {@link PlasticManagerOptions#create()}.
*/
@SuppressWarnings("unchecked")
public class PlasticManager implements PlasticClassListenerHub
@@ -31,23 +33,72 @@ public class PlasticManager implements P
private final PlasticClassPool pool;
/**
- * Creates a PlasticManager using the Thread's contextClassLoader as the parent class loader. No classes will
- * be automatically transformed, but instead {@link #createClass(Class, CreateClassCallback)} can be used to create
- * entirely new classes.
+ * A builder object for configuring the PlasticManager before instantiating it. Assumes a no-op
+ * {@link PlasticManagerDelegate} and an empty
+ * set of controlled packages.
*/
- public PlasticManager()
+ public static class PlasticManagerOptions
{
- this(Thread.currentThread().getContextClassLoader());
+ private final ClassLoader loader;
+
+ private PlasticManagerDelegate delegate = new NoopDelegate();
+
+ private final Set<String> packages = PlasticInternalUtils.newSet();
+
+ private PlasticManagerOptions(ClassLoader loader)
+ {
+ assert loader != null;
+
+ this.loader = loader;
+ }
+
+ /**
+ * Sets the {@link PlasticManagerDelegate}, which is ultimately responsible for
+ * transforming classes loaded from controlled packages. The default delegate
+ * does nothing.
+ */
+ public PlasticManagerOptions delegate(PlasticManagerDelegate delegate)
+ {
+ assert delegate != null;
+
+ this.delegate = delegate;
+
+ return this;
+ }
+
+ /**
+ * Adds additional controlled packages, in which classes are loaded and transformed.
+ */
+ public PlasticManagerOptions packages(Collection<String> packageNames)
+ {
+ packages.addAll(packageNames);
+
+ return this;
+ }
+
+ /**
+ * Creates the PlasticManager with the current set of options.
+ *
+ * @return the PlasticManager
+ */
+ public PlasticManager create()
+ {
+ return new PlasticManager(loader, delegate, packages);
+ }
}
/**
- * Creates a PlasticManager using the Thread's contextClassLoader as the parent class loader. No classes will
- * be automatically transformed, but instead {@link #createClass(Class, CreateClassCallback)} can be used to create
- * entirely new classes.
+ * Creates a new options using the thread's context class loader.
*/
- public PlasticManager(ClassLoader parentClassLoader)
+ public static PlasticManagerOptions withContextClassLoader()
+ {
+ return withClassLoader(Thread.currentThread().getContextClassLoader());
+ }
+
+ /** Creates a new options using the specified class loader. */
+ public static PlasticManagerOptions withClassLoader(ClassLoader loader)
{
- this(parentClassLoader, new NoopDelegate(), Collections.<String> emptySet());
+ return new PlasticManagerOptions(loader);
}
/**
@@ -62,7 +113,7 @@ public class PlasticManager implements P
* defines the packages that are to be transformed; top-classes in these packages
* (or sub-packages) will be passed to the delegate for transformation
*/
- public PlasticManager(ClassLoader parentClassLoader, PlasticManagerDelegate delegate,
+ private PlasticManager(ClassLoader parentClassLoader, PlasticManagerDelegate delegate,
Set<String> controlledPackageNames)
{
assert parentClassLoader != null;
@@ -74,10 +125,10 @@ public class PlasticManager implements P
/**
* Returns the ClassLoader that is used to instantiate transformed classes. The parent class loader
- * of the returned class loader is the class loader provided to
- * {@link #PlasticManager(ClassLoader, PlasticManagerDelegate, Set)}
+ * of the returned class loader is the context class loader, or the class loader specified by
+ * {@link #withClassLoader(ClassLoader)}.
*
- * @return class loader
+ * @return class loader used to load classes in controlled packages
*/
public ClassLoader getClassLoader()
{
@@ -134,7 +185,7 @@ public class PlasticManager implements P
throw new IllegalArgumentException(String.format("Class %s defines an interface, not a base class.",
baseClass.getName()));
- String name = String.format("$PlasticProxy$%s_%s", baseClass.getSimpleName(), PlasticUtils.nextUID());
+ String name = String.format("$%s_%s", baseClass.getSimpleName(), PlasticUtils.nextUID());
PlasticClassTransformation<T> transformation = pool.createTransformation(baseClass.getName(), name);
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy Tue May 3 21:12:42 2011
@@ -5,6 +5,9 @@ import org.apache.tapestry5.internal.pla
import spock.lang.Specification
abstract class AbstractPlasticSpecification extends Specification {
+
+ def mgr = PlasticManager.withContextClassLoader().create()
+
PlasticMethod findMethod(pc, name) {
pc.methods.find { it.description.methodName == name }
}
@@ -17,6 +20,6 @@ abstract class AbstractPlasticSpecificat
def delegate = new StandardDelegate(transformers)
def packages = ["testsubjects"]as Set
- return new PlasticManager(Thread.currentThread().contextClassLoader, delegate, packages)
+ return PlasticManager.withContextClassLoader().delegate(delegate).packages(packages).create()
}
}
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy Tue May 3 21:12:42 2011
@@ -6,46 +6,45 @@ import spock.lang.Specification;
import testannotations.ArrayAnnotation;
import testannotations.Truth;
-class ArrayAttributeAnnotations extends Specification {
- def mgr = new PlasticManager()
-
+class ArrayAttributeAnnotations extends AbstractPlasticSpecification {
+
def "handling of array attribute defaults"() {
when:
def pc = mgr.getPlasticClass("testsubjects.AnnotationSubject")
-
+
def a = pc.getAnnotation(ArrayAnnotation.class)
-
+
then:
a.numbers().length == 0
a.strings().length == 0
a.types().length == 0
a.annotations().length == 0
}
-
+
def "explicit values for array attributes"() {
when:
def pc = mgr.getPlasticClass("testsubjects.ArrayAttributesSubject")
def a = pc.getAnnotation(ArrayAnnotation.class)
-
+
then:
-
+
a.numbers() == [5]
-
+
a.strings() == ["frodo", "sam"]
-
+
a.types() == [Runnable.class]
-
+
a.annotations().length == 2
a.annotations()[0].value() == Truth.YES
a.annotations()[1].value() == Truth.NO
}
-
+
def "handling of explicitly empty array attributes"() {
when:
def pc = mgr.getPlasticClass("testsubjects.ExplicityEmptyArrayAttributesSubject")
-
+
def a = pc.getAnnotation(ArrayAnnotation.class)
-
+
then:
a.numbers().length == 0
a.strings().length == 0
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy Tue May 3 21:12:42 2011
@@ -6,8 +6,8 @@ import spock.lang.Specification;
import testannotations.InheritedAnnotation;
import testannotations.SimpleAnnotation;
-class ClassAnnotationAccess extends Specification {
- def mgr = new PlasticManager()
+class ClassAnnotationAccess extends AbstractPlasticSpecification {
+
def pc = mgr.getPlasticClass("testsubjects.AnnotationSubject")
def "access to non-existent annotation"() {
@@ -30,7 +30,7 @@ class ClassAnnotationAccess extends Spec
a instanceof SimpleAnnotation
a.annotationType() == SimpleAnnotation.class
-
+
a.toString() == "@testannotations.SimpleAnnotation"
}
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy Tue May 3 21:12:42 2011
@@ -5,8 +5,7 @@ import org.apache.tapestry5.plastic.Plas
import spock.lang.Specification
import testannotations.Maybe;
-class FieldAnnotationAccess extends Specification {
- def mgr = new PlasticManager()
+class FieldAnnotationAccess extends AbstractPlasticSpecification {
def "locate field by annotation"() {
setup:
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy Tue May 3 21:12:42 2011
@@ -18,40 +18,38 @@ import org.apache.tapestry5.plastic.Plas
import spock.lang.Specification;
-class FieldClaiming extends Specification
+class FieldClaiming extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
def "get fields ignores claimed fields"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.SingleField")
def f = pc.unclaimedFields.first()
-
+
expect:
f.name == "myField"
! f.claimed
-
+
when:
def f2 = f.claim("my tag")
-
+
then:
f2.is(f)
-
+
f.claimed
pc.unclaimedFields == []
pc.allFields == [f]
}
-
+
def "a field may only be claimed once"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.SingleField")
def f = pc.unclaimedFields.first()
-
+
f.claim "[first tag]"
-
+
when:
f.claim "[second tag]"
-
+
then:
def e = thrown(IllegalStateException)
e.message == "Field myField of class testsubjects.SingleField can not be claimed by [second tag] as it is already claimed by [first tag]."
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy Tue May 3 21:12:42 2011
@@ -14,15 +14,8 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.FieldConduit;
-import org.apache.tapestry5.plastic.PlasticManager;
-
-import spock.lang.Specification
-
-class FieldConduitTests extends Specification
+class FieldConduitTests extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
def "setting a field invokes the conduit"() {
FieldConduit fc = Mock()
@@ -106,7 +99,7 @@ class FieldConduitTests extends Specific
pc.allFields.first().setConduit(fc)
},
configureInstantiator: { className, instantiator -> instantiator }
- ] as PlasticManagerDelegate , ["testsubjects"] as Set)
+ ] as PlasticManagerDelegate , ["testsubjects"]as Set)
def o = mgr.getClassInstantiator("testsubjects.AccessMethodsSubject").newInstance()
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy Tue May 3 21:12:42 2011
@@ -14,14 +14,8 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.PlasticManager;
-
-import spock.lang.Specification;
-
-class FieldHandleTests extends Specification
+class FieldHandleTests extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
def "getting access to a new primitive field"() {
def pc = mgr.getPlasticClass("testsubjects.Empty")
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy Tue May 3 21:12:42 2011
@@ -14,16 +14,10 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.ComputedValue;
-import org.apache.tapestry5.plastic.PlasticManager;
+import testsubjects.StringPropertyHolder
-import spock.lang.Specification;
-import testsubjects.StringPropertyHolder;
-
-class FieldInjection extends Specification
+class FieldInjection extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
def "injection of a reference value"() {
String injected = "Value injected into the Empty class"
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy Tue May 3 21:12:42 2011
@@ -18,13 +18,13 @@ import java.util.concurrent.atomic.Atomi
import spock.lang.Specification
import testannotations.Property
+import testsubjects.AccessorsAlreadyExistSubject;
import testsubjects.CreateAccessorsSubject
import testsubjects.GenericCreateAccessorsSubject
-class FieldPropertyMethodCreation extends Specification
+class FieldPropertyMethodCreation extends AbstractPlasticSpecification
{
def withAccessors(Class subject, PropertyAccessType accessType) {
- def mgr = new PlasticManager()
def pc = mgr.getPlasticClass (subject.name)
pc.getFieldsWithAnnotation(Property.class).each { f ->
@@ -95,7 +95,7 @@ class FieldPropertyMethodCreation extend
def e = thrown(IllegalArgumentException)
- assert e.message == "Unable to create new accessor method public java.lang.String getValue() on class org.apache.tapestry5.plastic.AccessorsAlreadyExistSubject as the method is already implemented."
+ assert e.message == "Unable to create new accessor method public java.lang.String getValue() on class testsubjects.AccessorsAlreadyExistSubject as the method is already implemented."
}
def "create setter that already exists"() {
@@ -107,6 +107,6 @@ class FieldPropertyMethodCreation extend
def e = thrown(IllegalArgumentException)
- assert e.message == "Unable to create new accessor method public void setValue(java.lang.String) on class org.apache.tapestry5.plastic.AccessorsAlreadyExistSubject as the method is already implemented."
+ assert e.message == "Unable to create new accessor method public void setValue(java.lang.String) on class testsubjects.AccessorsAlreadyExistSubject as the method is already implemented."
}
}
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy Tue May 3 21:12:42 2011
@@ -14,77 +14,71 @@
package org.apache.tapestry5.plastic
-import java.lang.reflect.Modifier;
+import java.lang.reflect.Modifier
-import org.apache.tapestry5.plastic.PlasticManager;
-
-import spock.lang.Specification
-
-class IntroduceFieldTests extends Specification
+class IntroduceFieldTests extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
def "introduced fields are not visible in the allFields list"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.Empty")
-
+
expect:
pc.allFields == []
-
+
when:
def f = pc.introduceField("java.lang.String", "message")
-
+
then:
f.toString() == "PlasticField[private java.lang.String message (in class testsubjects.Empty)]"
f.name == "message"
pc.allFields == []
}
-
+
def "introducing a duplicate field name results in a unique id"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.Empty")
-
+
when:
def f1 = pc.introduceField("java.lang.Integer", "count")
def f2 = pc.introduceField("java.lang.Integer", "count")
-
+
then:
! f1.is(f2)
f1.name == "count"
-
+
f2.name != "count"
f2.name.startsWith("count")
}
-
-
+
+
def "instantiate a class with an introduced field"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.Empty")
-
+
pc.introduceField("java.lang.Integer", "count")
-
+
def ins = pc.createInstantiator()
-
+
when:
def empty = ins.newInstance()
def f = empty.class.getDeclaredField("count")
-
+
// Use Groovy to access the field directly
-
+
empty.@count = 77
-
+
then:
empty.@count == 77
-
+
when:
empty.@count = 99
-
+
then:
empty.@count == 99
-
+
expect:
-
- f.modifiers == Modifier.PRIVATE
+
+ f.modifiers == Modifier.PRIVATE
f.type == Integer.class
}
}
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy Tue May 3 21:12:42 2011
@@ -1,57 +1,54 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.PlasticManager;
+import testannotations.Maybe
+import testannotations.Outer
+import testannotations.PrimitiveValues
+import testannotations.Truth
-import spock.lang.Specification;
-import testannotations.Maybe;
-import testannotations.Outer;
-import testannotations.PrimitiveValues;
-import testannotations.Truth;
+class MethodAnnotationAccess extends AbstractPlasticSpecification {
-class MethodAnnotationAccess extends Specification {
- def mgr = new PlasticManager()
def pc = mgr.getPlasticClass("testsubjects.AnnotationSubject")
-
+
def "access to method annotation with enum attribute"() {
-
+
when:
-
+
def methods = pc.getMethodsWithAnnotation(Maybe.class)
def noMethod = methods[0]
def yesMethod = methods[1]
-
+
then:
-
+
methods.size == 2
-
+
noMethod.description.methodName == "no"
yesMethod.description.methodName == "yes"
-
+
noMethod.getAnnotation(Maybe.class).value() == Truth.NO
yesMethod.getAnnotation(Maybe.class).value() == Truth.YES
}
-
+
def "method annotation with primitive attributes"() {
when:
def methods = pc.getMethodsWithAnnotation(PrimitiveValues.class)
-
+
then:
methods.size == 1
-
+
when:
def pv = methods[0].getAnnotation(PrimitiveValues.class)
-
+
then:
pv.count() == 5
pv.title() == "runnables" // explicit
pv.type() == Runnable.class
pv.message() == "created" // default
}
-
+
def "nested annotation as attribute of outer annotation"() {
when:
def ann = pc.getMethodsWithAnnotation(Outer.class)[0].getAnnotation(Outer.class)
-
+
then:
ann.maybe().value() == Truth.YES
}
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy Tue May 3 21:12:42 2011
@@ -1,11 +1,8 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.PlasticManager;
-
import testsubjects.WillNotDoubleException
class MethodHandleAccess extends AbstractPlasticSpecification {
- def mgr = new PlasticManager()
def init(name) {
def pc = mgr.getPlasticClass("testsubjects.MethodHandleSubject")
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy Tue May 3 21:12:42 2011
@@ -1,9 +1,5 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.InstructionBuilderCallback;
-import org.apache.tapestry5.plastic.PlasticClass;
-import org.apache.tapestry5.plastic.PlasticClassTransformer;
-
class MethodImplementationTests extends AbstractPlasticSpecification {
def "overwrite implementation of method"() {
@@ -47,8 +43,6 @@ class MethodImplementationTests extends
def "while, increment, array operations"() {
setup:
- def mgr = new PlasticManager();
-
PlasticClass pc = mgr.getPlasticClass("testsubjects.WhileSubject")
PlasticMethod m = findMethod(pc, "firstNonNull")
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=1099253&r1=1099252&r2=1099253&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 Tue May 3 21:12:42 2011
@@ -1,8 +1,5 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.MethodDescription;
-import org.apache.tapestry5.plastic.PlasticClass;
-import org.apache.tapestry5.plastic.PlasticClassTransformer;
class MethodIntroduction extends AbstractPlasticSpecification {
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy Tue May 3 21:12:42 2011
@@ -1,25 +1,15 @@
package org.apache.tapestry5.plastic
-import org.apache.tapestry5.plastic.MethodAdvice;
-import org.apache.tapestry5.plastic.MethodDescription;
-import org.apache.tapestry5.plastic.MethodInvocation;
-import org.apache.tapestry5.plastic.PlasticClass;
-import org.apache.tapestry5.plastic.PlasticClassTransformer;
-import org.apache.tapestry5.plastic.PlasticManager;
-import org.apache.tapestry5.plastic.PlasticMethod;
-
import testsubjects.Memory
class MethodProxying extends AbstractPlasticSpecification {
- PlasticManager mgr = new PlasticManager()
def "basic proxying"() {
setup:
def mockRunnable = Mock(Runnable.class)
- def o = mgr.createClass (Object.class, {
- PlasticClass pc ->
+ def o = mgr.createClass (Object.class, { PlasticClass pc ->
def field = pc.introduceField (Runnable.class, "delegate").inject(mockRunnable)
@@ -45,8 +35,7 @@ class MethodProxying extends AbstractPla
def handle
def methodToString
- def o = mgr.createClass(Object.class, {
- PlasticClass pc ->
+ def o = mgr.createClass(Object.class, { PlasticClass pc ->
def field = pc.introduceField(Memory.class, "delegate").inject(new Memory())
@@ -76,8 +65,7 @@ class MethodProxying extends AbstractPla
def handle
- def o = mgr.createClass(Object.class, {
- PlasticClass pc ->
+ def o = mgr.createClass(Object.class, { PlasticClass pc ->
def memory = new Memory()
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy Tue May 3 21:12:42 2011
@@ -18,27 +18,22 @@ import java.lang.reflect.InvocationTarge
import org.apache.tapestry5.internal.plastic.NoopDelegate
-import spock.lang.Specification
-
-class ObtainPlasticClass extends Specification
+class ObtainPlasticClass extends AbstractPlasticSpecification
{
- def mgr = new PlasticManager()
-
- def "abstract classes may not be instantiated"()
- {
+ def "abstract classes may not be instantiated"() {
def pc = mgr.getPlasticClass("testsubjects.AbstractSubject")
-
+
when:
-
+
pc.createInstantiator().newInstance()
-
+
then:
-
+
def e = thrown(IllegalStateException)
-
+
assert e.message == "Class testsubjects.AbstractSubject is abstract and can not be instantiated."
}
-
+
def "access to simple empty class"() {
setup:
def pc = mgr.getPlasticClass("testsubjects.Empty")
@@ -145,10 +140,10 @@ class ObtainPlasticClass extends Specifi
when:
- clazz.getConstructor([] as Class[]).newInstance([] as Object[])
+ clazz.getConstructor([]as Class[]).newInstance([]as Object[])
then:
-
+
e = thrown(InvocationTargetException)
e.cause.getClass() == IllegalStateException.class
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy Tue May 3 21:12:42 2011
@@ -1,13 +1,10 @@
package org.apache.tapestry5.plastic
-import spock.lang.Specification
-class ProxyCreation extends Specification {
+class ProxyCreation extends AbstractPlasticSpecification {
def "create a field delegating proxy"() {
setup:
- def mgr = new PlasticManager()
-
Runnable r = Mock(Runnable)
def ins = mgr.createProxy(Runnable.class, {
@@ -37,8 +34,6 @@ class ProxyCreation extends Specificatio
setup:
"Each method of the interface delegates through a method that returns the new target for the method."
- def mgr = new PlasticManager()
-
Runnable r = Mock(Runnable)
def ins = mgr.createProxy(Runnable.class, {
@@ -77,9 +72,6 @@ class ProxyCreation extends Specificatio
def "type must be an interface"() {
- setup:
- def mgr = new PlasticManager()
-
when:
mgr.createProxy (String.class, {
@@ -102,8 +94,6 @@ class ProxyCreation extends Specificatio
assert event.type == ClassType.PRIMARY
} as PlasticClassListener
- def mgr = new PlasticManager()
-
mgr.addPlasticClassListener listener
def ins = mgr.createProxy(Runnable.class, {
Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy Tue May 3 21:12:42 2011
@@ -9,9 +9,10 @@ class ToStringTests extends AbstractPlas
def "add toString method to class that does not yet implement it"() {
setup:
- PlasticManager mgr = new PlasticManager()
+ def mgr = PlasticManager.withContextClassLoader().create()
- def o = mgr.createClass (Object.class, { it.addToString "<ToString>" } as PlasticClassTransformer).newInstance()
+ def o = mgr.createClass (Object.class, {
+ it.addToString "<ToString>" } as PlasticClassTransformer).newInstance()
expect:
@@ -23,7 +24,7 @@ class ToStringTests extends AbstractPlas
// Make sure the base class is transformed (and therefore, the existence of the toString() method noted)
- def mgr = new PlasticManager (Thread.currentThread().contextClassLoader, new StandardDelegate(), ["testsubjects"]as Set)
+ def mgr = PlasticManager.withContextClassLoader().delegate(new StandardDelegate()).packages(["testsubjects"]).create()
def o = mgr.createClass (HasToString.class, { it.addToString "<OverrideToString>" } as PlasticClassTransformer).newInstance()
Copied: tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AccessorsAlreadyExistSubject.java (from r1098835, tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AccessorsAlreadyExistSubject.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AccessorsAlreadyExistSubject.java?p2=tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AccessorsAlreadyExistSubject.java&p1=tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AccessorsAlreadyExistSubject.java&r1=1098835&r2=1099253&rev=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AccessorsAlreadyExistSubject.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AccessorsAlreadyExistSubject.java Tue May 3 21:12:42 2011
@@ -1,4 +1,4 @@
-package org.apache.tapestry5.plastic;
+package testsubjects;
import testannotations.Property;
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java Tue May 3 21:12:42 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -132,4 +132,12 @@ public final class InternalConstants
* @since 5.2.0
*/
public static final String CORE_STACK_NAME = "core";
+
+ /**
+ * The names of the standard controlled subpackages.
+ *
+ * @since 5.3.0
+ */
+ public static final String[] SUBPACKAGES =
+ { PAGES_SUBPACKAGE, COMPONENTS_SUBPACKAGE, MIXINS_SUBPACKAGE, BASE_SUBPACKAGE };
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassResolverImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassResolverImpl.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassResolverImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassResolverImpl.java Tue May 3 21:12:42 2011
@@ -35,6 +35,7 @@ import org.apache.tapestry5.ioc.util.Unk
import org.apache.tapestry5.services.ComponentClassResolver;
import org.apache.tapestry5.services.InvalidationListener;
import org.apache.tapestry5.services.LibraryMapping;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
import org.slf4j.Logger;
public class ComponentClassResolverImpl implements ComponentClassResolver, InvalidationListener
@@ -43,8 +44,6 @@ public class ComponentClassResolverImpl
private final Logger logger;
- private final ComponentInstantiatorSource componentInstantiatorSource;
-
private final ClassNameLocator classNameLocator;
private final String startPageName;
@@ -54,6 +53,8 @@ public class ComponentClassResolverImpl
private final Map<String, List<String>> mappings = CollectionFactory.newCaseInsensitiveMap();
+ private final Map<String, ControlledPackageType> packageMappings = CollectionFactory.newMap();
+
// Flag indicating that the maps have been cleared following an invalidation
// and need to be rebuilt. The flag and the four maps below are not synchronized
// because they are only modified inside a synchronized block. That should be strong enough ...
@@ -100,8 +101,6 @@ public class ComponentClassResolverImpl
public ComponentClassResolverImpl(Logger logger,
- ComponentInstantiatorSource componentInstantiatorSource,
-
ClassNameLocator classNameLocator,
@Symbol(SymbolConstants.START_PAGE_NAME)
@@ -110,7 +109,6 @@ public class ComponentClassResolverImpl
Collection<LibraryMapping> mappings)
{
this.logger = logger;
- this.componentInstantiatorSource = componentInstantiatorSource;
this.classNameLocator = classNameLocator;
this.startPageName = startPageName;
@@ -145,16 +143,21 @@ public class ComponentClassResolverImpl
// must be registered with the component instantiator (which is responsible
// for transformation).
- addPackagesToInstantiatorSource(rootPackage);
+ addSubpackagesToPackageMapping(rootPackage);
}
}
- private void addPackagesToInstantiatorSource(String rootPackage)
+ private void addSubpackagesToPackageMapping(String rootPackage)
{
- componentInstantiatorSource.addPackage(rootPackage + "." + InternalConstants.PAGES_SUBPACKAGE);
- componentInstantiatorSource.addPackage(rootPackage + "." + InternalConstants.COMPONENTS_SUBPACKAGE);
- componentInstantiatorSource.addPackage(rootPackage + "." + InternalConstants.MIXINS_SUBPACKAGE);
- componentInstantiatorSource.addPackage(rootPackage + "." + InternalConstants.BASE_SUBPACKAGE);
+ for (String subpackage : InternalConstants.SUBPACKAGES)
+ {
+ packageMappings.put(rootPackage + "." + subpackage, ControlledPackageType.COMPONENT);
+ }
+ }
+
+ public Map<String, ControlledPackageType> getControlledPackageMapping()
+ {
+ return Collections.unmodifiableMap(packageMappings);
}
/**
@@ -313,7 +316,7 @@ public class ComponentClassResolverImpl
// Make the super-stripped name another alias to the class.
// TAP5-1444: Everything else but a start page has precedence
-
+
if (!(lastTerm.equalsIgnoreCase(startPageName) && logicalNameToClassName.containsKey(reducedName)))
{
logicalNameToClassName.put(reducedName, name);
@@ -597,10 +600,9 @@ public class ComponentClassResolverImpl
if (packageName == null)
throw new RuntimeException(
- String
- .format(
- "Package names for library folder '%s' (%s) can not be reduced to a common base package (of at least two terms).",
- folder, InternalUtils.joinSorted(packageNames)));
+ String.format(
+ "Package names for library folder '%s' (%s) can not be reduced to a common base package (of at least two terms).",
+ folder, InternalUtils.joinSorted(packageNames)));
return packageName;
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSource.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSource.java Tue May 3 21:12:42 2011
@@ -14,10 +14,12 @@
package org.apache.tapestry5.internal.services;
+import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
import org.apache.tapestry5.ioc.internal.services.CtClassSource;
import org.apache.tapestry5.ioc.services.ClassFactory;
import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
import org.apache.tapestry5.services.InvalidationEventHub;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
/**
* Creates {@link org.apache.tapestry5.internal.services.Instantiator}s for components, based on component class name.
@@ -29,7 +31,11 @@ import org.apache.tapestry5.services.Inv
* The strategy used is that when <em>any</em> class (in a controlled package) changes, the entire class loader is
* discarded, along with any instances derived from those classes. A new class loader is created, and then invalidation
* events are fired to listeners.
+ * <p>
+ * Starting in Tapestry 5.3, the packages that are loaded are controlled by a configuration that maps package names to
+ * {@link ControlledPackageType}s.
*/
+@UsesMappedConfiguration(key = String.class, value = ControlledPackageType.class)
public interface ComponentInstantiatorSource
{
@@ -46,15 +52,7 @@ public interface ComponentInstantiatorSo
Instantiator getInstantiator(String classname);
/**
- * Adds a controlled package. Only classes within controlled packages are subject to transformation.
- *
- * @param packageName
- * the package name to add (must not be blank)
- */
- void addPackage(String packageName);
-
- /**
- * Checks to see if a fully qualfied class name exists. This method appears to exist only for testing.
+ * Checks to see if a fully qualified class name exists. This method appears to exist only for testing.
*
* @param className
* name of class to check
@@ -77,12 +75,4 @@ public interface ComponentInstantiatorSo
* @since 5.3.0
*/
PlasticProxyFactory getProxyFactory();
-
- /**
- * Invalidation event hub used to notify listeners that component classes have changed.
- *
- * @see org.apache.tapestry5.services.ComponentClasses
- * @since 5.1.0.0
- */
- InvalidationEventHub getInvalidationEventHub();
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java Tue May 3 21:12:42 2011
@@ -18,22 +18,17 @@ import java.util.Map;
import java.util.Set;
import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.InternalConstants;
-import org.apache.tapestry5.internal.event.InvalidationEventHubImpl;
import org.apache.tapestry5.internal.model.MutableComponentModelImpl;
import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
import org.apache.tapestry5.ioc.Invokable;
import org.apache.tapestry5.ioc.LoggerSource;
import org.apache.tapestry5.ioc.OperationTracker;
import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.PostInjection;
import org.apache.tapestry5.ioc.annotations.Primary;
-import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.services.ClassFactoryImpl;
-import org.apache.tapestry5.ioc.internal.services.PlasticClassListenerLogger;
import org.apache.tapestry5.ioc.internal.services.PlasticProxyFactoryImpl;
import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
@@ -58,20 +53,20 @@ import org.apache.tapestry5.plastic.Plas
import org.apache.tapestry5.plastic.PlasticUtils;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.ComponentResourcesAware;
-import org.apache.tapestry5.services.InvalidationEventHub;
+import org.apache.tapestry5.services.InvalidationListener;
import org.apache.tapestry5.services.UpdateListener;
import org.apache.tapestry5.services.UpdateListenerHub;
import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
import org.apache.tapestry5.services.transform.TransformationSupport;
import org.slf4j.Logger;
/**
* A wrapper around a {@link PlasticManager} that allows certain classes to be modified as they are loaded.
*/
-public final class ComponentInstantiatorSourceImpl extends InvalidationEventHubImpl implements
- ComponentInstantiatorSource, UpdateListener, PlasticManagerDelegate, PlasticClassListener
+public final class ComponentInstantiatorSourceImpl implements ComponentInstantiatorSource, UpdateListener,
+ InvalidationListener, PlasticManagerDelegate, PlasticClassListener
{
-
private final Set<String> controlledPackageNames = CollectionFactory.newSet();
private final URLChangeTracker changeTracker;
@@ -88,6 +83,10 @@ public final class ComponentInstantiator
private final OperationTracker tracker;
+ private final InternalComponentInvalidationEventHub invalidationHub;
+
+ // These change whenever the invalidation event hub sends an invalidation notification
+
private ClassFactory classFactory;
private PlasticProxyFactory proxyFactory;
@@ -101,15 +100,7 @@ public final class ComponentInstantiator
private final Map<String, ComponentModel> classToModel = CollectionFactory.newMap();
- private final String[] SUBPACKAGES =
- { "." + InternalConstants.PAGES_SUBPACKAGE + ".", "." + InternalConstants.COMPONENTS_SUBPACKAGE + ".",
- "." + InternalConstants.MIXINS_SUBPACKAGE + ".", "." + InternalConstants.BASE_SUBPACKAGE + "." };
-
- public ComponentInstantiatorSourceImpl(@Inject
- @Symbol(SymbolConstants.PRODUCTION_MODE)
- boolean productionMode,
-
- Logger logger,
+ public ComponentInstantiatorSourceImpl(Logger logger,
LoggerSource loggerSource,
@@ -123,10 +114,10 @@ public final class ComponentInstantiator
ClasspathURLConverter classpathURLConverter,
- OperationTracker tracker)
- {
- super(productionMode);
+ OperationTracker tracker,
+ Map<String, ControlledPackageType> configuration, InternalComponentInvalidationEventHub invalidationHub)
+ {
this.parent = proxyFactory.getClassLoader();
this.transformerChain = transformerChain;
this.logger = logger;
@@ -134,6 +125,12 @@ public final class ComponentInstantiator
this.internalRequestGlobals = internalRequestGlobals;
this.changeTracker = new URLChangeTracker(classpathURLConverter);
this.tracker = tracker;
+ this.invalidationHub = invalidationHub;
+
+ // For now, we just need the keys of the configuration. When there are more types of controlled
+ // packages, we'll need to do more.
+
+ controlledPackageNames.addAll(configuration.keySet());
initializeService();
}
@@ -141,14 +138,20 @@ public final class ComponentInstantiator
@PostInjection
public void listenForUpdates(UpdateListenerHub hub)
{
+ invalidationHub.addInvalidationListener(this);
hub.addUpdateListener(this);
}
public synchronized void checkForUpdates()
{
- if (!changeTracker.containsChanges())
- return;
+ if (changeTracker.containsChanges())
+ {
+ invalidationHub.classInControlledPackageHasChanged();
+ }
+ }
+ public void objectWasInvalidated()
+ {
changeTracker.clear();
classToInstantiator.clear();
@@ -156,11 +159,6 @@ public final class ComponentInstantiator
// Create a new one.
initializeService();
-
- // Tell everyone that the world has changed and they should discard
- // their cache.
-
- fireInvalidationEvent();
}
/**
@@ -169,7 +167,7 @@ public final class ComponentInstantiator
*/
private void initializeService()
{
- manager = new PlasticManager(parent, this, controlledPackageNames);
+ manager = PlasticManager.withClassLoader(parent).delegate(this).packages(controlledPackageNames).create();
manager.addPlasticClassListener(this);
@@ -256,11 +254,6 @@ public final class ComponentInstantiator
return proxyFactory;
}
- public InvalidationEventHub getInvalidationEventHub()
- {
- return this;
- }
-
public void transform(final PlasticClass plasticClass)
{
tracker.run(String.format("Running component class transformations on %s", plasticClass.getClassName()),
@@ -359,9 +352,11 @@ public final class ComponentInstantiator
private String buildSuggestedPackageName(String className)
{
- for (String subpackage : SUBPACKAGES)
+ for (String subpackage : InternalConstants.SUBPACKAGES)
{
- int pos = className.indexOf(subpackage);
+ String term = "." + subpackage + ".";
+
+ int pos = className.indexOf(term);
// Keep the leading '.' in the subpackage name and tack on "base".
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHub.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHub.java?rev=1099253&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHub.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHub.java Tue May 3 21:12:42 2011
@@ -0,0 +1,35 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.InvalidationEventHub;
+import org.apache.tapestry5.services.InvalidationListener;
+
+/**
+ * Split-out implementation of {@link InvalidationEventHub} that seperates it from {@link ComponentInstantiatorSource}.
+ * This was necessary due to some refactoring that made {@link ComponentClassResolver} and ComponentInstantiatorSource
+ * mutually dependent.
+ *
+ * @since 5.3.0
+ */
+public interface InternalComponentInvalidationEventHub extends InvalidationEventHub
+{
+ /**
+ * Invoked when the {@link ComponentInstantiatorSource} notices that
+ * a class file within any of the controlled packages has changed. Fires the
+ * {@link InvalidationListener#objectWasInvalidated()} notification.
+ */
+ void classInControlledPackageHasChanged();
+}
Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java (from r1098835, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ForceDevelopmentModeModule.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ForceDevelopmentModeModule.java&r1=1098835&r2=1099253&rev=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ForceDevelopmentModeModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java Tue May 3 21:12:42 2011
@@ -15,17 +15,20 @@
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.ioc.MappedConfiguration;
-import org.apache.tapestry5.ioc.annotations.Contribute;
-import org.apache.tapestry5.ioc.services.ApplicationDefaults;
-import org.apache.tapestry5.ioc.services.SymbolProvider;
+import org.apache.tapestry5.internal.event.InvalidationEventHubImpl;
+import org.apache.tapestry5.ioc.annotations.Symbol;
-public class ForceDevelopmentModeModule
+public class InternalComponentInvalidationEventHubImpl extends InvalidationEventHubImpl implements
+ InternalComponentInvalidationEventHub
{
- @Contribute(SymbolProvider.class)
- @ApplicationDefaults
- public static void enableDevelopmentMode(MappedConfiguration<String, Object> configuration)
+ public InternalComponentInvalidationEventHubImpl(@Symbol(SymbolConstants.PRODUCTION_MODE)
+ boolean productionMode)
{
- configuration.add(SymbolConstants.PRODUCTION_MODE, false);
+ super(productionMode);
+ }
+
+ public void classInControlledPackageHasChanged()
+ {
+ fireInvalidationEvent();
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java Tue May 3 21:12:42 2011
@@ -14,6 +14,8 @@
package org.apache.tapestry5.internal.services;
+import java.util.Map;
+
import javax.servlet.http.Cookie;
import org.apache.tapestry5.SymbolConstants;
@@ -22,16 +24,19 @@ import org.apache.tapestry5.internal.ser
import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSourceImpl;
+import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.ObjectLocator;
import org.apache.tapestry5.ioc.OrderedConfiguration;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Autobuild;
+import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.annotations.Marker;
import org.apache.tapestry5.ioc.annotations.Primary;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.services.CtClassSource;
import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
import org.apache.tapestry5.ioc.services.PropertyShadowBuilder;
+import org.apache.tapestry5.services.ComponentClassResolver;
import org.apache.tapestry5.services.ComponentClasses;
import org.apache.tapestry5.services.ComponentLayer;
import org.apache.tapestry5.services.ComponentMessages;
@@ -44,6 +49,7 @@ import org.apache.tapestry5.services.Req
import org.apache.tapestry5.services.ResponseCompressionAnalyzer;
import org.apache.tapestry5.services.UpdateListenerHub;
import org.apache.tapestry5.services.templates.ComponentTemplateLocator;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
/**
* {@link org.apache.tapestry5.services.TapestryModule} has gotten too complicated and it is nice to demarkate public
@@ -103,6 +109,7 @@ public class InternalModule
binder.bind(ResourceDigestManager.class, ResourceDigestManagerImpl.class);
binder.bind(RequestPageCache.class, NonPoolingRequestPageCacheImpl.class);
binder.bind(ComponentInstantiatorSource.class);
+ binder.bind(InternalComponentInvalidationEventHub.class);
}
/**
@@ -245,4 +252,19 @@ public class InternalModule
{
configuration.addInstance("LinkDecoration", LinkDecorationListener.class);
}
+
+ /**
+ * Contributes packages identified by {@link ComponentClassResolver#getControlledPackageMapping()}.
+ *
+ * @since 5.3.0
+ */
+ @Contribute(ComponentInstantiatorSource.class)
+ public static void configureControlledPackagesFromComponentClassResolver(
+ MappedConfiguration<String, ControlledPackageType> configuration, ComponentClassResolver resolver)
+ {
+ for (Map.Entry<String, ControlledPackageType> entry : resolver.getControlledPackageMapping().entrySet())
+ {
+ configuration.add(entry.getKey(), entry.getValue());
+ }
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java Tue May 3 21:12:42 2011
@@ -20,6 +20,7 @@ import java.util.Map;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
import org.apache.tapestry5.ioc.services.ClassNameLocator;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
/**
* Resolves page names and component types to fully qualified class names. Pages and components may be provided by the
@@ -122,4 +123,14 @@ public interface ComponentClassResolver
* @see ClasspathAssetAliasManager
*/
Map<String, String> getFolderToPackageMapping();
+
+ /**
+ * Used to identify which packages are controlled packages (from which components are loaded). Future expansion
+ * may allow for additional packages which are live reloaded but not components (or perhaps are transformed, but not
+ * as components).
+ *
+ * @return a mapping from package name to {@link ControlledPackageType}.
+ * @since 5.3.0
+ */
+ Map<String, ControlledPackageType> getControlledPackageMapping();
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=1099253&r1=1099252&r2=1099253&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Tue May 3 21:12:42 2011
@@ -2635,12 +2635,15 @@ public final class TapestryModule
}
/**
+ * Exposes the public portion of the internal {@link InternalComponentInvalidationEventHub} service.
+ *
* @since 5.1.0.0
*/
@Marker(ComponentClasses.class)
- public static InvalidationEventHub buildComponentClassesInvalidationEventHub(ComponentInstantiatorSource source)
+ public static InvalidationEventHub buildComponentClassesInvalidationEventHub(
+ InternalComponentInvalidationEventHub trueHub)
{
- return source.getInvalidationEventHub();
+ return trueHub;
}
/**
@@ -2963,7 +2966,7 @@ public final class TapestryModule
}
/**
- * In production mode, overrides {@link UpdateListenerHub} to be an empty placeholder.
+ * In production mode, override {@link UpdateListenerHub} to be an empty placeholder.
*/
@Contribute(ServiceOverride.class)
public static void productionModeOverrides(MappedConfiguration<Class, Object> configuration,
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/transform/ControlledPackageType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/transform/ControlledPackageType.java?rev=1099253&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/transform/ControlledPackageType.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/transform/ControlledPackageType.java Tue May 3 21:12:42 2011
@@ -0,0 +1,18 @@
+package org.apache.tapestry5.services.transform;
+
+/**
+ * Defines how a particular controlled package is processed. Currently there is only one option, but further options
+ * (to allow a package to be reloaded but not transformed, and to allow a package to be transformed but not as
+ * components)
+ * may be supported in the future.
+ *
+ * @since 5.3.0
+ */
+public enum ControlledPackageType
+{
+ /**
+ * Top-level classes within the packages are components, that are transformed according to
+ * {@link ComponentClassTransformWorker2}. All top-level classes must be components.
+ */
+ COMPONENT;
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AddTransformPagesToCISModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AddTransformPagesToCISModule.java?rev=1099253&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AddTransformPagesToCISModule.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AddTransformPagesToCISModule.java Tue May 3 21:12:42 2011
@@ -0,0 +1,14 @@
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.ioc.MappedConfiguration;
+import org.apache.tapestry5.ioc.annotations.Contribute;
+import org.apache.tapestry5.services.transform.ControlledPackageType;
+
+public class AddTransformPagesToCISModule
+{
+ @Contribute(ComponentInstantiatorSource.class)
+ public static void setupPackageForReload(MappedConfiguration<String, ControlledPackageType> configuration)
+ {
+ configuration.add("org.apache.tapestry5.internal.transform.pages", ControlledPackageType.COMPONENT);
+ }
+}