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);
+    }
+}