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 2006/04/21 17:19:15 UTC

svn commit: r395912 [2/3] - in /tapestry/tapestry5/tapestry-core/trunk: ./ .settings/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/tapestry/ src/main/java/org/apache/tapestry/annotations/ src/main/...

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformConstants.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformConstants.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformConstants.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformConstants.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,40 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+import org.apache.tapestry.transform.MethodSignature;
+
+/**
+ * Constants used by various transformations.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class TransformConstants
+{
+    /** Signature for {@link org.apache.tapestry.events.ComponentLifecycle#containingPageDidLoad()}. */
+    public static final MethodSignature CONTAINING_PAGE_DID_LOAD_SIGNATURE = new MethodSignature(
+            "containingPageDidLoad");
+
+    /**
+     * Signature for {@link org.apache.tapestry.events.ComponentLifecycle#containingPageDidDetach()}.
+     */
+    public static final MethodSignature CONTAINING_PAGE_DID_DETACH = new MethodSignature(
+            "containingPageDidDetach");
+
+    /** Prevent instantiation. */
+    private TransformConstants()
+    {
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,55 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+import javassist.CtClass;
+
+import org.apache.hivemind.Messages;
+import org.apache.hivemind.impl.MessageFormatter;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+final class TransformMessages
+{
+    private static final Messages MESSAGES = new MessageFormatter(TransformMessages.class);
+
+    /** Prevent instantiation. */
+    private TransformMessages()
+    {
+    }
+
+    static String noConstructorFound(Class instanceClass)
+    {
+        return MESSAGES.format("no-constructor-found", instanceClass.getName());
+    }
+
+    static String missingDeclaredField(CtClass ctClass, String fieldName)
+    {
+        return MESSAGES.format("missing-declared-field", ctClass.getName(), fieldName);
+    }
+
+    static String errorAddingMethod(CtClass ctClass, String methodName, Throwable cause)
+    {
+        return MESSAGES.format("error-adding-method", ctClass.getName(), methodName, cause);
+    }
+
+    static String fieldAlreadyClaimed(String fieldName, CtClass ctClass, Object existingTag,
+            Object newTag)
+    {
+        return MESSAGES.format("field-already-claimed", new Object[]
+        { fieldName, ctClass.getName(), existingTag, newTag });
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/RetainWorker.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/RetainWorker.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/RetainWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/RetainWorker.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,48 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.worker;
+
+import java.util.List;
+
+import org.apache.tapestry.annotations.Retain;
+import org.apache.tapestry.internal.transform.ClassTransformWorker;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.transform.ClassTransformation;
+
+/**
+ * Identifies fields with the {@link org.apache.tapestry.annotations.Retain} annotation, and
+ * "claims" them so that no special work will occur on them.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class RetainWorker implements ClassTransformWorker
+{
+    /**
+     * Claims each field with the {@link org.apache.tapestry.annotations.Retain} annotation,
+     * claiming it using the annotation as the tag.
+     */
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        List<String> fieldNames = transformation.findFieldsWithAnnotation(Retain.class);
+
+        for (String fieldName : fieldNames)
+        {
+            Retain annotation = transformation.getFieldAnnotation(fieldName, Retain.class);
+
+            transformation.claimField(fieldName, annotation);
+        }
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/UnclaimedFieldWorker.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/UnclaimedFieldWorker.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/UnclaimedFieldWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/worker/UnclaimedFieldWorker.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,78 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.worker;
+
+import java.lang.reflect.Modifier;
+
+import org.apache.hivemind.service.BodyBuilder;
+import org.apache.tapestry.events.ComponentLifecycle;
+import org.apache.tapestry.internal.transform.ClassTransformWorker;
+import org.apache.tapestry.internal.transform.TransformConstants;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.transform.ClassTransformation;
+
+/**
+ * Designed to be just about the last worker in the pipeline. Its job is to add cleanup code that
+ * restores transient fields back to their initial (null) value.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class UnclaimedFieldWorker implements ClassTransformWorker
+{
+
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        String[] fieldNames = transformation.findUnclaimedFields();
+
+        for (String fieldName : fieldNames)
+        {
+            transformField(fieldName, transformation);
+        }
+    }
+
+    private void transformField(String fieldName, ClassTransformation transformation)
+    {
+        String type = transformation.getFieldType(fieldName);
+
+        String defaultFieldName = transformation.newField(Modifier.PRIVATE, type, fieldName
+                + "Default");
+
+        // Add the the interface and an implementation that squirrels away the
+        // initial value of the field.
+        transformation.addImplementedInterface(ComponentLifecycle.class);
+
+        BodyBuilder builder = new BodyBuilder();
+        builder.begin();
+        builder.addln("$proceed($$);");
+        builder.addln("{0} = {1};", defaultFieldName, fieldName);
+        builder.end();
+
+        transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
+                .toString());
+
+        // At the end of the request, we want to move the default value back over the
+        // active field value. This will most often be null.
+
+        builder.clear();
+
+        builder.begin();
+        builder.addln("$proceed($$);");
+        builder.addln("{0} = {1};", fieldName, defaultFieldName);
+        builder.end();
+
+        transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_DETACH, builder
+                .toString());
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,28 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.model;
+
+/**
+ * Defines a component in terms of its capabilities, parameters, sub-components, etc. During
+ * <em>runtime</em>, the component model is immutable. During <em>construction</em> time, when
+ * the class is being transformed a loaded, the model is mutable.
+ * 
+ * @author Howard M. Lewis Ship
+ * @see
+ */
+public interface ComponentModel
+{
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,26 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.model;
+
+/**
+ * Mutable version of {@link org.apache.tapestry.model.ComponentModel} used during the
+ * transformation phase.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface MutableComponentModel extends ComponentModel
+{
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,58 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.test;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+import org.apache.tapestry.annotations.Retain;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.transform.ClassTransformation;
+
+/**
+ * Base test case that adds a number of convienience factory and training methods to
+ * {@link org.apache.tapestry.test.TestBase}.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public abstract class BaseTestCase extends TestBase
+{
+
+    protected final void trainFindFieldsWithAnnotation(ClassTransformation transformation,
+            Class<? extends Annotation> annotationClass, List<String> fieldNames)
+    {
+        transformation.findFieldsWithAnnotation(annotationClass);
+        setReturnValue(fieldNames);
+    }
+
+    protected final <T extends Annotation> void trainGetFieldAnnotation(
+            ClassTransformation transformation, String fieldName,
+            Class<? extends Annotation> annotationClass, T annotation)
+    {
+        transformation.getFieldAnnotation(fieldName, annotationClass);
+        setReturnValue(annotation);
+    }
+
+    protected final MutableComponentModel newMutableComponentModel()
+    {
+        return newMock(MutableComponentModel.class);
+    }
+
+    protected final ClassTransformation newClassTransformation()
+    {
+        return newMock(ClassTransformation.class);
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,111 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.test;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.testng.annotations.Configuration;
+
+import static org.easymock.EasyMock.expectLastCall;
+import static org.testng.Assert.fail;
+
+/**
+ * Manages a set of EasyMock mock objects. Used as a base class for test cases.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class TestBase
+{
+    private IMocksControl _control;
+
+    /**
+     * Discards any mock objects created during the test.
+     */
+    @Configuration(afterTestMethod = true, alwaysRun = true)
+    protected final void tearDown()
+    {
+        // TestNG reuses the same class instance across all tests methods within that class, so if
+        // we don't clear out the mocks, they will tend to accumulate (which isn't the end of the
+        // world, but it's nice to save unneccessary cycles even inside a test case).
+        _control = null;
+    }
+
+    /**
+     * Creates a new mock object of the indicated type. Creates a <em>strict</em> mock, which
+     * enforces an exact order of method invocation.
+     * 
+     * @param <T>
+     *            the type of the mock object
+     * @param mockClass
+     *            the class to mock
+     * @return the mock object, ready for training
+     */
+    protected final <T> T newMock(Class<T> mockClass)
+    {
+        if (_control == null)
+            _control = EasyMock.createStrictControl();
+
+        return _control.createMock(mockClass);
+    }
+
+    /**
+     * Replay's each mock object created by {@link #newMock(Class)}. .
+     */
+    protected final void replay()
+    {
+        _control.replay();
+    }
+
+    /**
+     * Verifies each created mock object, then resets the mock for additional training.
+     */
+    protected final void verify()
+    {
+        _control.verify();
+        _control.reset();
+    }
+
+    /**
+     * Sets the return value for the most recent method call upon the mock.
+     * 
+     * @param returnValue
+     *            value to be returned from the method call
+     */
+    protected final void setReturnValue(Object returnValue)
+    {
+        expectLastCall().andReturn(returnValue);
+    }
+
+    /**
+     * Trains a mock object to throw an exception (for the most recent method call).
+     * 
+     * @param throwable
+     *            the exception to be thrown by the most recent method call on the mock
+     */
+    protected final void setThrowable(Throwable throwable)
+    {
+        expectLastCall().andThrow(throwable);
+    }
+
+    /**
+     * unreachable().
+     */
+
+    protected final void unreachable()
+    {
+        fail("This code should not be reachable.");
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,161 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.transform;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+/**
+ * Contains class-specific information used when transforming an raw class into an executable class.
+ * Much of this information is somewhat like ordinary reflection, but applies to a class that has
+ * not yet been loaded.
+ * <p>
+ * Transformation is primarily about identifying annotations on fields and on methods and changing
+ * the class, adding new interfaces, fields and methods, and deleting some existing fields.
+ * <p>
+ * A ClassTransformation contains all the state data specific to a particular class being
+ * transformed. A number of <em>workers</em> will operate upon the ClassTransformation to effect
+ * the desired changes before the true class is loaded into memory.
+ * <p>
+ * The majority of methods concern the <em>declared</em> members (field and methods) of a specific
+ * class, rather than any fields or methods inherited from a base class.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface ClassTransformation
+{
+
+    /**
+     * Returns the name of a new member (field or method). Ensures that the resulting name does not
+     * conflict with any existing member (declared by the underlying class, or inherited from a base
+     * class).
+     * <p>
+     * TODO: This method may be removed (see {@link #newField(int, String, String)})
+     * 
+     * @param suggested
+     *            the suggested value for the member
+     * @return a unique name for the member
+     */
+    String newMemberName(String suggested);
+
+    /**
+     * Generates a list of the names of declared instance fields that have the indicated annotation.
+     */
+    List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
+
+    /**
+     * Finds an annotation for the class itself. TODO: Deal with the fact that Javassist does not
+     * handled Inherited annotations properly.
+     * 
+     * @param <T>
+     * @param annotationClass
+     *            the type of annotation to access
+     * @return the annotation if present, or null otherwise
+     */
+    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+
+    /**
+     * Finds an annotation on a declared instance field.
+     * 
+     * @param <T>
+     *            constrains parameter and return value to Annotation types
+     * @param fieldName
+     *            the name of the field, which must exist
+     * @param annotationClass
+     *            the type of annotation to access
+     * @return the annotation if present, or null otherwise
+     * @throws IllegalArgumentException
+     *             if the fieldName does not correspond to a declared field
+     */
+    <T extends Annotation> T getFieldAnnotation(String fieldName, Class<T> annotationClass);
+
+    /**
+     * Claims a field so as to ensure that only a single annotation is applied to any single field.
+     * When a transformation occurs (driven by a field annotation), the first thing that occurs is
+     * to claim the field, on behalf of the annotation.
+     * 
+     * @param fieldName
+     *            the name of the field that is being claimed
+     * @param tag
+     *            a non-null object that represents why the field is being tagged (this is typically
+     *            a specific annotation on the field)
+     * @throws IllegalArgumentException
+     *             if the fieldName does not correspond to a declared instance field
+     * @throws IllegalStateException
+     *             if the field is already claimed for some other tag
+     */
+    void claimField(String fieldName, Object tag);
+
+    /**
+     * Finds any declared <em>instance</em> fields that have not been claimed (via
+     * {@link #claimField(String, Object)}) and returns the names of those fields. May return an
+     * empty array.
+     */
+    String[] findUnclaimedFields();
+
+    /**
+     * Obtains the type of a declared instance field.
+     * 
+     * @param fieldName
+     * @return the type of the field, as a string
+     * @throws IllegalArgumentException
+     *             if the fieldName does not correspond to a declared instance field
+     */
+    String getFieldType(String fieldName);
+
+    /**
+     * Defines a new declared field for the class. The suggestedName may be modified to ensure
+     * uniqueness.
+     * 
+     * @param modifiers
+     *            modifiers for the field (typically, {@link java.lang.reflect.Modifier#PRIVATE})
+     * @param type
+     *            the type for the field, as a string
+     * @param suggestedName
+     *            the desired name for the field, which may be modified (for uniqueness) when
+     *            returned
+     * @return the (uniqued) name for the field
+     */
+    String newField(int modifiers, String type, String suggestedName);
+
+    /**
+     * Transforms the class to implement the indicated interface. If the class (or its super class)
+     * does not already implement the interface, then the interface is added, and default
+     * implementations of any methods of the interface are added.
+     * <p>
+     * TODO: Checking that the names of methods in the interface do not conflict with the names of
+     * methods present in the (unmodified) class.
+     * 
+     * @param interfaceClass
+     *            the interface to be implemented by the class
+     * @throws IllegalArgumentException
+     *             if the interfaceClass argument does not represent an interface
+     */
+    void addImplementedInterface(Class interfaceClass);
+
+    /**
+     * Extends an existing method. The body of the method is replaced with the provided body.
+     * However, a call to the Javassist pseudo-method $proceed() is required.
+     * 
+     * @param signature
+     *            the signature of the method to extend
+     * @param methodBody
+     *            the body of code
+     * @throws IllegalArgumentException
+     *             if the method body does not include a call to $proceed, or if the provided
+     *             Javassist method body can not be compiled
+     */
+    void extendMethod(MethodSignature methodSignature, String methodBody);
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,192 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.transform;
+
+import static org.apache.tapestry.util.Defense.notBlank;
+import static org.apache.tapestry.util.Defense.notNull;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * A representation of a method signature, which consists of its name, modifiers (primarily,
+ * visibility), return type, parameter types, and declared exception types.
+ * <p>
+ * Types are stored as class names (or primitive names) because the MethodSignature is often used in
+ * situations where the actual class has not been loaded yet.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class MethodSignature
+{
+
+    private int _hashCode = -1;
+
+    private final int _modifiers;
+
+    private final String _returnType;
+
+    private final String _methodName;
+
+    private final String[] _parameterTypes;
+
+    private final String[] _exceptionTypes;
+
+    private static final String[] EMPTY_STRINGS = new String[0];
+
+    /** Convienience for adding a public void method with no parameters or exception types. */
+
+    public MethodSignature(String name)
+    {
+        this(Modifier.PUBLIC, "void", name, EMPTY_STRINGS, EMPTY_STRINGS);
+    }
+
+    public MethodSignature(int modifiers, String type, String name, String[] parameterTypes,
+            String[] exceptionTypes)
+    {
+        _modifiers = modifiers;
+
+        _returnType = notBlank(type, "type");
+        _methodName = notBlank(name, "name");
+
+        // TODO: Checks that no element within the two arrays
+        // is null or blank.
+
+        _parameterTypes = notNull(parameterTypes, "parameterTypes");
+        _exceptionTypes = notNull(exceptionTypes, "exceptionTypes");
+    }
+
+    /**
+     * Returns a non-null array of the names of each declared exception type thrown by the method.
+     * Calling code should not modify the array.
+     */
+    public String[] getExceptionTypes()
+    {
+        return _exceptionTypes;
+    }
+
+    /** Returns the name of the method. */
+    public String getMethodName()
+    {
+        return _methodName;
+    }
+
+    /**
+     * Returns the set of modifier flags for this method.
+     * 
+     * @see java.lang.reflect.Modifier
+     */
+    public int getModifiers()
+    {
+        return _modifiers;
+    }
+
+    /**
+     * Returns an array of the type name for each parameter. Calling code should not modify the
+     * array.
+     */
+    public String[] getParameterTypes()
+    {
+        return _parameterTypes;
+    }
+
+    /** Return the type name of the return type of the method. */
+    public String getReturnType()
+    {
+        return _returnType;
+    }
+
+    public int hashCode()
+    {
+        if (_hashCode == -1)
+        {
+            _hashCode = 17 * _modifiers;
+            _hashCode += 31 * _returnType.hashCode();
+            _hashCode += 31 * _methodName.hashCode();
+
+            for (String parameterType : _parameterTypes)
+            {
+                _hashCode += 31 * parameterType.hashCode();
+            }
+
+            for (String exceptionType : _exceptionTypes)
+            {
+                _hashCode += 31 * exceptionType.hashCode();
+            }
+        }
+
+        return _hashCode;
+    }
+
+    public boolean equals(Object other)
+    {
+        if (other == null || !(other instanceof MethodSignature))
+            return false;
+
+        MethodSignature ms = (MethodSignature) other;
+
+        return _modifiers == ms._modifiers && _returnType.equals(ms._returnType)
+                && _methodName.equals(ms._methodName)
+                && matches(_parameterTypes, ms._parameterTypes)
+                && matches(_exceptionTypes, ms._exceptionTypes);
+    }
+
+    private boolean matches(String[] values, String[] otherValues)
+    {
+        if (values.length != otherValues.length)
+            return false;
+
+        for (int i = 0; i < values.length; i++)
+        {
+            if (!values[i].equals(otherValues[i]))
+                return false;
+        }
+
+        return true;
+    }
+
+    public String toString()
+    {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(Modifier.toString(_modifiers));
+        builder.append(' ');
+        builder.append(_returnType);
+        builder.append(' ');
+        builder.append(_methodName);
+        builder.append('(');
+
+        for (int i = 0; i < _parameterTypes.length; i++)
+        {
+            if (i > 0)
+                builder.append(", ");
+
+            builder.append(_parameterTypes[i]);
+        }
+
+        builder.append(')');
+
+        for (int i = 0; i < _exceptionTypes.length; i++)
+        {
+            if (i == 0)
+                builder.append(" throws ");
+            else
+                builder.append(", ");
+
+            builder.append(_exceptionTypes[i]);
+        }
+
+        return builder.toString();
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,83 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Static factory methods to ease the creation of new collection types (when using generics). Most
+ * of these method leverage the compiler's ability to match generic types by return value. Typical
+ * usage:
+ * 
+ * <pre>
+ * Map&lt;Foo, Bar&gt; map = newMap();
+ * </pre>
+ * 
+ * <p>
+ * This is a replacement for:
+ * 
+ * <pre>
+ * Map&lt;Foo, Bar&gt; map = new HashMap&lt;Foo, Bar&gt;();
+ * </pre>
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class CollectionFactory
+{
+
+    /** Prevent instantiation. */
+    private CollectionFactory()
+    {
+    }
+
+    /** Constructs and returns a generic {@link HashMap} instance. */
+    public static <K, V> Map<K, V> newMap()
+    {
+        return new HashMap<K, V>();
+    }
+
+    /** Constructs and returns a generic {@link java.util.HashSet} instance. */
+    public static <T> Set<T> newSet()
+    {
+        return new HashSet<T>();
+    }
+
+    /**
+     * Constructs a new {@link java.util.HashMap} instance from an existing Map instance.
+     */
+
+    public static <K, V> Map<K, V> copyMap(Map<K, V> map)
+    {
+        return new HashMap<K, V>(map);
+    }
+
+    /** Contructs and returns a new generic {@link java.util.ArrayList} instance. */
+    public static <T> List<T> newList()
+    {
+        return new ArrayList<T>();
+    }
+
+    /** Easy way to convert a list of like-typed values into a list. */
+    public static <T> List<T> newList(T... values)
+    {
+        return Arrays.asList(values);
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/Defense.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/Defense.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/Defense.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/Defense.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,72 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.util;
+
+/**
+ * Static utility methods for defensive programming.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class Defense
+{
+
+    /**
+     * Checks that a method parameter value is not null, and returns it.
+     * 
+     * @param <T>
+     *            the value type
+     * @param value
+     *            the value (which is checked to ensure non-nullness)
+     * @param parameterName
+     *            the name of the parameter, used for exception messages
+     * @return the value
+     * @throws NullPointerException
+     *             if the value is null
+     */
+    public static <T> T notNull(T value, String parameterName)
+    {
+        if (value == null) throw new NullPointerException(UtilMessages.parameterWasNull(parameterName));
+
+        return value;
+    }
+
+    /** Prevent instantiation. */
+    private Defense()
+    {
+    }
+
+    /**
+     * Checks that a parameter value is not null and not empty.
+     * 
+     * @param value
+     *            value to check (which is returned)
+     * @param parameterName
+     *            the name of the parameter, used for exception messages
+     * @return the value, trimmed, if non-blank
+     * @throws IllegalArgumentException
+     *             if the value is null or empty
+     */
+    public static String notBlank(String value, String parameterName)
+    {
+        if (value != null)
+        {
+            String trimmedValue = value.trim();
+
+            if (!trimmedValue.equals("")) return trimmedValue;
+        }
+        
+        throw new IllegalArgumentException(UtilMessages.parameterWasBlank(parameterName));
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/IdAllocator.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/IdAllocator.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/IdAllocator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/IdAllocator.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,160 @@
+// Copyright 2004, 2005, 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.util;
+
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+import static org.apache.tapestry.util.Defense.notNull;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * Used to "uniquify" names within a given context. A base name is passed in, and the return value
+ * is the base name, or the base name extended with a suffix to make it unique.
+ * 
+ * @author Howard Lewis Ship
+ * @since 3.0
+ */
+
+public final class IdAllocator
+{
+    private static final String SEPARATOR = "_";
+
+    private final Map<String, NameGenerator> _generatorMap;
+
+    private final String _namespace;
+
+    /** Generates unique names with a particular prefix. */
+    private static class NameGenerator implements Cloneable
+    {
+        private final String _baseId;
+
+        private int _index;
+
+        NameGenerator(String baseId)
+        {
+            _baseId = baseId + SEPARATOR;
+        }
+
+        public String nextId()
+        {
+            return _baseId + _index++;
+        }
+
+        /** Clones this instance, returning an equivalent but seperate copy. */
+        public NameGenerator clone()
+        {
+            try
+            {
+                return (NameGenerator) super.clone();
+            }
+            catch (CloneNotSupportedException ex)
+            {
+                // Unreachable!
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    /** Creates a new allocator with no namespace. */
+    public IdAllocator()
+    {
+        this("");
+    }
+
+    /** Creates a new allocator with the provided namespace. */
+    public IdAllocator(String namespace)
+    {
+        this(namespace, new HashMap<String, NameGenerator>());
+    }
+
+    private IdAllocator(String namespace, Map<String, NameGenerator> generatorMap)
+    {
+        _namespace = notNull(namespace, "namespace");
+        _generatorMap = generatorMap;
+    }
+
+    /**
+     * Creates a clone of this IdAllocator instance, copying the allocator's namespace and key map.
+     */
+    public IdAllocator clone()
+    {
+        // Copying the _generatorMap is tricky; multiple keys will point to the same NameGenerator
+        // instance.
+        // We need to clone the NameGenerators, then buld a new map around the clones.
+
+        IdentityHashMap<NameGenerator, NameGenerator> transformMap = new IdentityHashMap<NameGenerator, NameGenerator>();
+
+        for (NameGenerator original : _generatorMap.values())
+        {
+            NameGenerator copy = original.clone();
+
+            transformMap.put(original, copy);
+        }
+
+        Map<String, NameGenerator> mapCopy = newMap();
+
+        for (String key : _generatorMap.keySet())
+        {
+            NameGenerator original = _generatorMap.get(key);
+            NameGenerator copy = transformMap.get(original);
+
+            mapCopy.put(key, copy);
+        }
+
+        return new IdAllocator(_namespace, mapCopy);
+    }
+
+    /**
+     * Allocates the id. Repeated calls for the same name will return "name", "name_0", "name_1",
+     * etc.
+     */
+
+    public String allocateId(String name)
+    {
+        String key = name + _namespace;
+
+        NameGenerator g = _generatorMap.get(key);
+        String result = null;
+
+        if (g == null)
+        {
+            g = new NameGenerator(key);
+            result = key;
+        }
+        else
+            result = g.nextId();
+
+        // Handle the degenerate case, where a base name of the form "foo_0" has been
+        // requested. Skip over any duplicates thus formed.
+
+        while (_generatorMap.containsKey(result))
+            result = g.nextId();
+
+        _generatorMap.put(result, g);
+
+        return result;
+    }
+
+    /**
+     * Clears the allocator, resetting it to freshly allocated state.
+     */
+
+    public void clear()
+    {
+        _generatorMap.clear();
+    }
+}
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/UtilMessages.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/UtilMessages.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/UtilMessages.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/UtilMessages.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,44 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.util;
+
+import org.apache.hivemind.Messages;
+import org.apache.hivemind.impl.MessageFormatter;
+
+/**
+ * Static messages
+ * 
+ * @author Howard M. Lewis Ship
+ */
+final class UtilMessages
+{
+
+    private static final Messages MESSAGES = new MessageFormatter(UtilMessages.class);
+
+    /** Prevent instantiaton. */
+    private UtilMessages()
+    {
+    }
+
+    static String parameterWasNull(String parameterName)
+    {
+        return MESSAGES.format("parameter-was-null", parameterName);
+    }
+
+    static String parameterWasBlank(String parameterName)
+    {
+        return MESSAGES.format("parameter-was-blank", parameterName);
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties Fri Apr 21 08:19:11 2006
@@ -0,0 +1,18 @@
+# Copyright 2006 The Howard M. Lewis Ship
+#
+# 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.
+
+no-constructor-found=Unable to find an applicable constructor for class {0}.
+missing-declared-field=Class {0} does not contain a field named ''{1}''.
+error-adding-method=Error adding method {1} to class {0}: {2} 
+field-already-claimed=Field {0} of class {1} is already claimed by {2} and can not be claimed by {3}.
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/util/UtilStrings.properties
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/util/UtilStrings.properties?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/util/UtilStrings.properties (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/util/UtilStrings.properties Fri Apr 21 08:19:11 2006
@@ -0,0 +1,16 @@
+# Copyright 2006 The Howard M. Lewis Ship
+#
+# 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.
+
+parameter-was-null=Parameter {0} was null.
+parameter-was-blank=Parameter {0} was null or contained only whitespace.
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Fri Apr 21 08:19:11 2006
@@ -0,0 +1,27 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<!-- 
+   Copyright 2006 The Howard M. Lewis Ship
+
+   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.
+-->
+
+<suite name="Tapestry 5">
+  <test verbose="2" name="General" annotations="1.5">
+    <packages>
+      <package name="org.apache.tapestry.transform"/>
+      <package name="org.apache.tapestry.internal.transform"/>
+      <package name="org.apache.tapestry.internal.transform.worker"/>
+      <package name="org.apache.tapestry.util"/>
+    </packages>
+  </test>   
+</suite>

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/BarInterface.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/BarInterface.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/BarInterface.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/BarInterface.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,20 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+public interface BarInterface
+{
+    void bar();
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,64 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+import static java.lang.Thread.currentThread;
+import static org.testng.Assert.assertEquals;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.transform.ComponentInstantiatorSourceImpl;
+import org.apache.tapestry.test.TestBase;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for {@link org.apache.tapestry.internal.transform.ComponentInstantiatorSourceImpl}.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class ComponentInstantiatorSourceImplTest extends TestBase
+{
+    private final ClassLoader _defaultClassLoader = currentThread().getContextClassLoader();
+
+    protected final Log newLog()
+    {
+        return newMock(Log.class);
+    }
+
+    @Test
+    public void controlledPackagesTest() throws Exception
+    {
+        ComponentInstantiatorSourceImpl e = new ComponentInstantiatorSourceImpl(_defaultClassLoader);
+
+        assertEquals(e.inControlledPackage("foo.bar.Baz"), false);
+
+        // Check that classes in the default package are never controlled
+
+        assertEquals(e.inControlledPackage("Biff"), false);
+
+        // Now add a controlled package
+
+        e.addPackage("foo.bar");
+
+        assertEquals(e.inControlledPackage("foo.bar.Baz"), true);
+
+        // Sub-packages of controlled packages are controlled as well
+
+        assertEquals(e.inControlledPackage("foo.bar.biff.Pop"), true);
+
+        // Parents of controlled packages are not controlled
+
+        assertEquals(e.inControlledPackage("foo.Gloop"), false);
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooBarInterface.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooBarInterface.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooBarInterface.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooBarInterface.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,20 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+public interface FooBarInterface extends FooInterface, BarInterface
+{
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooInterface.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooInterface.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooInterface.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/FooInterface.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,23 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public interface FooInterface
+{
+    void foo();
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/GetterMethodsInterface.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/GetterMethodsInterface.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/GetterMethodsInterface.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/GetterMethodsInterface.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,41 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public interface GetterMethodsInterface
+{
+    boolean getBoolean();
+
+    byte getByte();
+
+    short getShort();
+
+    int getInt();
+
+    long getLong();
+
+    float getFloat();
+
+    double getDouble();
+
+    String getString();
+
+    int[] getIntArray();
+
+    Object[] getObjectArray();
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,357 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.Loader;
+import javassist.NotFoundException;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Retain;
+import org.apache.tapestry.internal.transform.pages.AbstractFoo;
+import org.apache.tapestry.internal.transform.pages.BarImpl;
+import org.apache.tapestry.internal.transform.pages.ChildClassInheritsAnnotation;
+import org.apache.tapestry.internal.transform.pages.ClaimedFields;
+import org.apache.tapestry.internal.transform.pages.ParentClass;
+import org.apache.tapestry.internal.transform.pages.TargetObject;
+import org.apache.tapestry.test.TestBase;
+import org.apache.tapestry.transform.ClassTransformation;
+import org.testng.annotations.Configuration;
+import org.testng.annotations.Test;
+
+import static java.lang.Thread.currentThread;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class InternalClassTransformationImplTest extends TestBase
+{
+    private ClassPool _classPool;
+
+    private final ClassLoader _contextClassLoader = currentThread().getContextClassLoader();
+
+    /**
+     * We need a new ClassPool for each individual test, since many of the tests will end up
+     * modifying one or more CtClass instances.
+     */
+    @Configuration(beforeTestMethod = true)
+    public void setupClassPool()
+    {
+        _classPool = new ClassPool();
+        _classPool.appendSystemPath();
+    }
+
+    private CtClass findCtClass(Class targetClass) throws NotFoundException
+    {
+        return _classPool.get(targetClass.getName());
+    }
+
+    @Test
+    public void newMemberNameTest() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        assertEquals(ct.newMemberName("fred"), "_$fred");
+        assertEquals(ct.newMemberName("fred"), "_$fred_0");
+
+        // Here we're exposing a bit of the internal algorithm, which strips
+        // of '$' and '_' before tacking "_$" in front.
+
+        assertEquals(ct.newMemberName("_fred"), "_$fred_1");
+        assertEquals(ct.newMemberName("_$fred"), "_$fred_2");
+        assertEquals(ct.newMemberName("__$___$____$_fred"), "_$fred_3");
+
+        // Here we're trying to force conflicts with existing declared
+        // fields and methods of the class.
+
+        assertEquals(ct.newMemberName("_parentField"), "_$parentField");
+        assertEquals(ct.newMemberName("conflictField"), "_$conflictField_0");
+        assertEquals(ct.newMemberName("conflictMethod"), "_$conflictMethod_0");
+    }
+
+    private ClassTransformation createClassTransformation(Class targetClass)
+            throws NotFoundException
+    {
+        CtClass ctClass = findCtClass(targetClass);
+        return new InternalClassTransformationImpl(ctClass);
+    }
+
+    @Test
+    public void findAnnotationOnUnknownField() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        try
+        {
+            ct.getFieldAnnotation("unknownField", Retain.class);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "Class org.apache.tapestry.internal.transform.pages.ParentClass does not contain a field named 'unknownField'.");
+        }
+    }
+
+    @Test
+    public void findFieldAnnotation() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        Retain retain = ct.getFieldAnnotation("_annotatedField", Retain.class);
+
+        assertNotNull(retain);
+    }
+
+    @Test
+    public void findMissingFieldAnnotation() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        // Field with annotations, but not that annotation
+        assertNull(ct.getFieldAnnotation("_annotatedField", Override.class));
+
+        // Field with no annotations
+        assertNull(ct.getFieldAnnotation("_parentField", Override.class));
+    }
+
+    @Test
+    public void fieldsWithAnnotation() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        List<String> fields = ct.findFieldsWithAnnotation(Retain.class);
+
+        assertEquals(fields.size(), 1);
+        assertEquals(fields.get(0), "_annotatedField");
+    }
+
+    @Test
+    public void noFieldsWithAnnotation() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        List<String> fields = ct.findFieldsWithAnnotation(Documented.class);
+
+        assertTrue(fields.isEmpty());
+    }
+
+    @Test
+    public void claimFields() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ClaimedFields.class);
+
+        String[] unclaimed = ct.findUnclaimedFields();
+
+        assertEquals(Arrays.asList(unclaimed), newList("_field1", "_field4", "_zzfield"));
+
+        ct.claimField("_field4", "Fred");
+
+        unclaimed = ct.findUnclaimedFields();
+
+        assertEquals(Arrays.asList(unclaimed), newList("_field1", "_zzfield"));
+
+        try
+        {
+            ct.claimField("_field4", "Barney");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "Field _field4 of class org.apache.tapestry.internal.transform.pages.ClaimedFields is already claimed by Fred and can not be claimed by Barney.");
+        }
+
+    }
+
+    @Test
+    public void claimFieldsOmitsAddedFields() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ClaimedFields.class);
+
+        ct.newField(Modifier.PRIVATE, "int", "newField");
+
+        String[] unclaimed = ct.findUnclaimedFields();
+
+        assertEquals(Arrays.asList(unclaimed), newList("_field1", "_field4", "_zzfield"));
+    }
+
+    @Test
+    public void findAnnotationsOnClass() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(ParentClass.class);
+
+        ComponentClass cc = ct.getAnnotation(ComponentClass.class);
+
+        assertNotNull(cc);
+
+        // Try again (the annotations will be cached). Use an annotation
+        // that will not be present.
+
+        Target t = ct.getAnnotation(Target.class);
+
+        assertNull(t);
+    }
+
+    /**
+     * More a test of how Javassist works. Javassist does not honor the Inherited annotation for
+     * classes (this kind of makes sense, since it won't necessarily have the super-class in
+     * memory). Eventually we'll sort that out inside of InternalClassTransformationImpl. In the
+     * meantime, we just make sure Javassist works the way we think it does (in case a later
+     * Javassist changes this behavior).
+     */
+    @Test
+    public void ensureSubclassesDoNotInheritAnnotations() throws Exception
+    {
+        // The Java runtime does honor @Inherited
+        assertNotNull(ChildClassInheritsAnnotation.class.getAnnotation(ComponentClass.class));
+
+        ClassTransformation ct = createClassTransformation(ChildClassInheritsAnnotation.class);
+
+        ComponentClass cc = ct.getAnnotation(ComponentClass.class);
+
+        // But Javassist does not.
+        assertNull(cc);
+    }
+
+    /**
+     * These tests are really to assert my understanding of Javassist's API. I guess we should keep
+     * them around to make sure that future versions of Javassist work the same as our expectations.
+     */
+    @Test
+    public void javassistGetInterfacesDoesNotIncludeInheritedInterfaces() throws Exception
+    {
+        CtClass ctClass = findCtClass(BarImpl.class);
+
+        CtClass[] interfaces = ctClass.getInterfaces();
+
+        // Just the interfaces implemented by this particular class, not
+        // inherited interfaces.
+
+        assertEquals(interfaces.length, 1);
+
+        assertEquals(interfaces[0].getName(), BarInterface.class.getName());
+
+        CtClass parentClass = ctClass.getSuperclass();
+
+        interfaces = parentClass.getInterfaces();
+
+        assertEquals(interfaces.length, 1);
+
+        assertEquals(interfaces[0].getName(), FooInterface.class.getName());
+    }
+
+    @Test
+    public void javassistGetInterfacesOnAbstractClass() throws Exception
+    {
+        CtClass ctClass = findCtClass(AbstractFoo.class);
+
+        CtClass[] interfaces = ctClass.getInterfaces();
+
+        assertEquals(interfaces.length, 1);
+
+        assertEquals(interfaces[0].getName(), FooInterface.class.getName());
+
+        // In some cases, Java reflection on an abstract class implementing an interface
+        // will show the interface methods as abstract methods on the class. This seems
+        // to vary from JVM to JVM. I believe Javassist is more consistent here.
+
+        CtMethod[] methods = ctClass.getDeclaredMethods();
+
+        assertEquals(methods.length, 0);
+    }
+
+    @Test
+    public void javassistMethodsOnSubInterface() throws Exception
+    {
+        CtClass ctClass = findCtClass(FooBarInterface.class);
+
+        // Just want to check that an interface that extends other interfaces
+        // doesn't show those other interface's methods.
+
+        CtMethod[] methods = ctClass.getDeclaredMethods();
+
+        assertEquals(methods.length, 0);
+    }
+
+    @Test
+    public void addImplementedInterface() throws Exception
+    {
+        ClassLoader childLoader = new Loader(_contextClassLoader, _classPool);
+
+        CtClass targetObjectCtClass = findCtClass(TargetObject.class);
+
+        ClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+
+        ct.addImplementedInterface(FooInterface.class);
+        ct.addImplementedInterface(GetterMethodsInterface.class);
+
+        // Inside this test case, we're a bit limited, because
+        // when the modified version of the TargetObject class is loaded,
+        // the FooInterface and GetterMethodsInterface classes are also loaded
+        // into the child class loader. Therefore, we need to use reflection
+        // to check that the methods are implemented correctly.
+
+        Class modified = _classPool.toClass(targetObjectCtClass, childLoader);
+
+        Class[] interfaces = modified.getInterfaces();
+
+        assertEquals(interfaces.length, 2);
+        assertEquals(FooInterface.class.getName(), interfaces[0].getName());
+        assertEquals(GetterMethodsInterface.class.getName(), interfaces[1].getName());
+
+        Object target = modified.newInstance();
+
+        invoke(target, "foo");
+
+        assertEquals(invoke(target, "getBoolean"), false);
+        assertEquals(invoke(target, "getByte"), (byte) 0);
+        assertEquals(invoke(target, "getShort"), (short) 0);
+        assertEquals(invoke(target, "getInt"), 0);
+        assertEquals(invoke(target, "getLong"), 0l);
+        assertEquals(invoke(target, "getFloat"), 0.0f);
+        assertEquals(invoke(target, "getDouble"), 0.0d);
+        assertNull(invoke(target, "getString"));
+        assertNull(invoke(target, "getObjectArray"));
+        assertNull(invoke(target, "getIntArray"));
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T invoke(Object target, String methodName) throws Exception
+    {
+        Class targetClass = target.getClass();
+
+        Method method = targetClass.getMethod(methodName);
+
+        return (T) method.invoke(target);
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/AbstractFoo.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/AbstractFoo.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/AbstractFoo.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/AbstractFoo.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,25 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.pages;
+
+import org.apache.tapestry.internal.transform.FooInterface;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public abstract class AbstractFoo implements FooInterface
+{
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/BarImpl.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/BarImpl.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/BarImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/BarImpl.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,29 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.pages;
+
+import org.apache.tapestry.internal.transform.BarInterface;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class BarImpl extends FooImpl implements BarInterface
+{
+
+    public void bar()
+    {
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ChildClassInheritsAnnotation.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ChildClassInheritsAnnotation.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ChildClassInheritsAnnotation.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ChildClassInheritsAnnotation.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,12 @@
+package org.apache.tapestry.internal.transform.pages;
+
+/**
+ * Used to check that Javassist does make child classes inherit class annotations.
+ * 
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class ChildClassInheritsAnnotation extends ParentClass
+{
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ClaimedFields.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ClaimedFields.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ClaimedFields.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ClaimedFields.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,92 @@
+package org.apache.tapestry.internal.transform.pages;
+
+public class ClaimedFields
+{
+    // Make sure results are sorted by putting this first
+    // but expecting them last.
+    
+    private int _zzfield;
+    
+    private int _field1;
+
+    private static int field2;
+
+    public int _field3;
+
+    private String _field4;
+
+    protected boolean _field5;
+
+    long _field6;
+
+    public static final int getField2()
+    {
+        return field2;
+    }
+
+    public static final void setField2(int field2)
+    {
+        field2 = field2;
+    }
+
+    public final int getField1()
+    {
+        return _field1;
+    }
+
+    public final void setField1(int field1)
+    {
+        _field1 = field1;
+    }
+
+    public final int getField3()
+    {
+        return _field3;
+    }
+
+    public final void setField3(int field3)
+    {
+        _field3 = field3;
+    }
+
+    public final String getField4()
+    {
+        return _field4;
+    }
+
+    public final void setField4(String field4)
+    {
+        _field4 = field4;
+    }
+
+    public final boolean isField5()
+    {
+        return _field5;
+    }
+
+    public final void setField5(boolean field5)
+    {
+        _field5 = field5;
+    }
+
+    public final long getField6()
+    {
+        return _field6;
+    }
+
+    public final void setField6(long field6)
+    {
+        _field6 = field6;
+    }
+
+    public final int getZzfield()
+    {
+        return _zzfield;
+    }
+
+    public final void setZzfield(int zzfield)
+    {
+        _zzfield = zzfield;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/FooImpl.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/FooImpl.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/FooImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/FooImpl.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,29 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.pages;
+
+import org.apache.tapestry.internal.transform.FooInterface;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class FooImpl implements FooInterface
+{
+
+    public void foo()
+    {
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,48 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Retain;
+
+/**
+ * Test class used with
+ * {@link org.apache.tapestry.internal.transform.InternalClassTransformationImplTest}
+ * 
+ * @author Howard M. Lewis Ship
+ */
+@ComponentClass
+public class ParentClass
+{
+    public int _parentField;
+
+    // Named so that we can force a name conflict
+
+    public String _$conflictField;
+
+    @Retain
+    public boolean _annotatedField;
+
+    public void doNothingParentMethod()
+    {
+
+    }
+
+    public void _$conflictMethod()
+    {
+
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObject.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObject.java?rev=395912&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObject.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObject.java Fri Apr 21 08:19:11 2006
@@ -0,0 +1,25 @@
+// Copyright 2006 The Howard M. Lewis Ship
+//
+// 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.tapestry.internal.transform.pages;
+
+/**
+ * An empty object to which fields, methods and interfaces are added.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class TargetObject
+{
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org