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 2010/01/31 20:03:37 UTC

svn commit: r905099 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/services/ main/java/org/apache/tapestry5/services/ test/java/org/apache/tapestry5/internal/services/ test/java/org/apache/tapestry5/internal/t...

Author: hlship
Date: Sun Jan 31 19:03:37 2010
New Revision: 905099

URL: http://svn.apache.org/viewvc?rev=905099&view=rev
Log:
Rename TransformMethod.advice() to TransformMethod.addAdvice(), start work on making comnponent methods accessible (MethodAccess)

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java   (with props)
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentMethodAdvice.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethodSignature.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,36 @@
+// Copyright 2010 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.MethodAccess;
+import org.apache.tapestry5.services.MethodInvocationResult;
+
+/**
+ * Base class used for dynamically-created subclasses that implement {@link MethodAccess}
+ * 
+ * @since 5.2.0
+ */
+public abstract class AbstractMethodAccess implements MethodAccess
+{
+    protected MethodInvocationResult success(Object result)
+    {
+        return new MethodInvocationSuccessfulResult(result);
+    }
+
+    protected MethodInvocationResult fail(Throwable exception)
+    {
+        return new MethodInvocationFailResult(exception);
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractMethodAccess.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java Sun Jan 31 19:03:37 2010
@@ -43,14 +43,7 @@
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.model.MutableComponentModel;
 import org.apache.tapestry5.runtime.Component;
-import org.apache.tapestry5.services.ComponentMethodAdvice;
-import org.apache.tapestry5.services.ComponentValueProvider;
-import org.apache.tapestry5.services.FieldFilter;
-import org.apache.tapestry5.services.MethodFilter;
-import org.apache.tapestry5.services.TransformField;
-import org.apache.tapestry5.services.TransformMethod;
-import org.apache.tapestry5.services.TransformMethodSignature;
-import org.apache.tapestry5.services.TransformUtils;
+import org.apache.tapestry5.services.*;
 import org.slf4j.Logger;
 
 /**
@@ -58,6 +51,9 @@
  */
 public final class InternalClassTransformationImpl implements InternalClassTransformation
 {
+    public static final MethodSignature INVOKE_SIGNATURE = new MethodSignature(
+            MethodInvocationResult.class, "invoke", new Class[]
+            { Object.class, Object[].class }, null);
 
     private static final int INIT_BUFFER_SIZE = 100;
 
@@ -87,6 +83,8 @@
 
         private ComponentMethodInvocationBuilder builder;
 
+        private MethodAccess access;
+
         TransformMethodImpl(CtMethod method, boolean added)
         {
             this.method = method;
@@ -113,7 +111,7 @@
             return sig;
         }
 
-        public void advise(ComponentMethodAdvice advice)
+        public void addAdvice(ComponentMethodAdvice advice)
         {
             failIfFrozen();
 
@@ -125,10 +123,105 @@
             builder.addAdvice(advice);
         }
 
+        public MethodAccess getAccess()
+        {
+            failIfFrozen();
+
+            if (access == null)
+                access = createMethodAccess();
+
+            return access;
+        }
+
+        private MethodAccess createMethodAccess()
+        {
+            if (isPublic())
+                return createPublicMethodAccess();
+
+            return null;
+        }
+
+        private boolean isPublic()
+        {
+            return Modifier.isPublic(sig.getModifiers());
+        }
+
+        private MethodAccess createPublicMethodAccess()
+        {
+
+            ClassFab cf = classFactory
+                    .newClass(ClassFabUtils.generateClassName(MethodAccess.class),
+                            AbstractMethodAccess.class);
+
+            boolean isVoid = sig.getReturnType().equals("void");
+
+            BodyBuilder builder = new BodyBuilder().begin();
+
+            builder.addln("%s instance = (%<s) $1;", getClassName());
+
+            builder.addln("try").begin();
+
+            if (!isVoid)
+            {
+                builder.add("return success(($w) ");
+            }
+
+            // Call the instance method, even if its void.
+
+            builder.add("instance.%s(", sig.getMethodName());
+
+            int p = 0;
+
+            for (String type : sig.getParameterTypes())
+            {
+                if (p != 0)
+                    builder.add(", ");
+
+                String ref = String.format("$2[%d]", p++);
+                builder.add(ClassFabUtils.castReference(ref, type));
+                p++;
+            }
+
+            // Balance the call to success()
+            if (!isVoid)
+                builder.add(")");
+
+            builder.addln(");");
+
+            if (isVoid)
+                builder.addln("return success(null);");
+
+            builder.end(); // try
+            builder.addln("catch (java.lang.RuntimeException ex) { throw ex; }");
+            builder.addln("catch (java.lang.Exception ex) { return fail(ex); }");
+
+            builder.end();
+
+            cf.addMethod(Modifier.PUBLIC, INVOKE_SIGNATURE, builder.toString());
+
+            cf.addToString(String.format("MethodAccess[method %s of class %s]", sig
+                    .getMediumDescription(), getClassName()));
+
+            Class accessClass = cf.createClass();
+
+            try
+            {
+                Object accessInstance = accessClass.newInstance();
+
+                return (MethodAccess) accessInstance;
+            }
+            catch (Exception ex)
+            {
+                throw new RuntimeException(ex);
+            }
+        }
+
         public void extend(String body)
         {
             failIfFrozen();
 
+            Defense.notBlank(body, "body");
+
             try
             {
                 method.insertAfter(body);
@@ -1519,7 +1612,7 @@
 
     public void advise(TransformMethodSignature methodSignature, ComponentMethodAdvice advice)
     {
-        getMethod(methodSignature).advise(advice);
+        getMethod(methodSignature).addAdvice(advice);
     }
 
     public boolean isMethodOverride(TransformMethodSignature methodSignature)

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,56 @@
+// Copyright 2010 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.MethodInvocationResult;
+
+/**
+ * Implementation of {@link MethodInvocationResult} for failed
+ * invocations (where a checked exception was thrown).
+ * 
+ * @since 5.2.0
+ */
+public class MethodInvocationFailResult implements MethodInvocationResult
+{
+    private final Throwable thrown;
+
+    public MethodInvocationFailResult(Throwable thrown)
+    {
+        this.thrown = thrown;
+    }
+
+    public Object getReturnValue()
+    {
+        return null;
+    }
+
+    public <T extends Throwable> T getThrown(Class<T> throwableClass)
+    {
+        if (throwableClass.isInstance(thrown))
+            return throwableClass.cast(thrown);
+
+        return null;
+    }
+
+    public boolean isFail()
+    {
+        return true;
+    }
+
+    public void rethrow()
+    {
+        throw new RuntimeException(thrown);
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationFailResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,53 @@
+// Copyright 2010 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.MethodInvocationResult;
+
+/**
+ * Implementation of {@link MethodInvocationResult} for successful
+ * method invocations.
+ * 
+ * @since 5.2.0
+ */
+public class MethodInvocationSuccessfulResult implements MethodInvocationResult
+{
+    private final Object returnValue;
+
+    public MethodInvocationSuccessfulResult(Object returnValue)
+    {
+        this.returnValue = returnValue;
+    }
+
+    public Object getReturnValue()
+    {
+        return returnValue;
+    }
+
+    public <T extends Throwable> T getThrown(Class<T> throwableClass)
+    {
+        return null;
+    }
+
+    public boolean isFail()
+    {
+        return false;
+    }
+
+    public void rethrow()
+    {
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MethodInvocationSuccessfulResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java Sun Jan 31 19:03:37 2010
@@ -532,7 +532,7 @@
     /**
      * Adds method advice for the indicated method.
      * 
-     * @deprecated Use {@link TransformMethod#advise(ComponentMethodAdvice)} instead
+     * @deprecated Use {@link TransformMethod#addAdvice(ComponentMethodAdvice)} instead
      */
     void advise(TransformMethodSignature methodSignature, ComponentMethodAdvice advice);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentMethodAdvice.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentMethodAdvice.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentMethodAdvice.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentMethodAdvice.java Sun Jan 31 19:03:37 2010
@@ -19,7 +19,7 @@
  * method parameters. After invoking {@link org.apache.tapestry5.services.ComponentMethodInvocation#proceed()}, the
  * advice may query and override thrown exceptions or the return value of the invocation.
  * 
- * @see TransformMethod#advise(ComponentMethodAdvice)
+ * @see TransformMethod#addAdvice(ComponentMethodAdvice)
  */
 public interface ComponentMethodAdvice
 {

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,37 @@
+// Copyright 2010 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.services;
+
+/**
+ * Represents a bridge to an object method, when that method may not be public. A MethodAccess object
+ * encapsulates the approach for invoking the method and capturing the result (either the return value,
+ * or the checked exception that is thrown).
+ * 
+ * @since 5.2.0
+ */
+public interface MethodAccess
+{
+    /**
+     * Invoke the method on the target, passing a number of arguments to the method.
+     * If the method throws a RuntimeException, that is passed through unchanged.
+     * If the method throws a checked exception, that will be reflected in the invocation result.
+     * 
+     * @param target
+     *            object on which to invoke a method
+     * @param arguments
+     *            arguments to pass to the method
+     */
+    MethodInvocationResult invoke(Object target, Object... arguments);
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,52 @@
+// Copyright 2010 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.services;
+
+/**
+ * Captures the result of invoking a method.
+ * 
+ * @since 5.2.0
+ */
+public interface MethodInvocationResult
+{
+    /**
+     * The return value from the method invocation. This will be null if the method returns null,
+     * is a void method, or if a checked exception was thrown by the method.
+     */
+    Object getReturnValue();
+
+    /**
+     * If true, then the method invocation ended with a checked exception being thrown.
+     */
+    boolean isFail();
+
+    /**
+     * If the invocation threw a checked exception, this method will wrap that exception in a
+     * RuntimeException and throw that. For most code that doesn't specifically care about
+     * the thrown exception, this method should be invoked before continuing on to
+     * examine {@link #getReturnValue()}.
+     */
+    void rethrow();
+
+    /**
+     * If {@link #isFail()} is true, this method provides access to the actual checked exception that was thrown.
+     * 
+     * @param throwableClass
+     *            the type of exception to match
+     * @return the exception, if the method invocation threw a checked exception, and the exception is assignable to
+     *         the provided type. In other cases, null is returned.
+     */
+    <T extends Throwable> T getThrown(Class<T> throwableClass);
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodInvocationResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java Sun Jan 31 19:03:37 2010
@@ -43,24 +43,31 @@
      * The extended method is considered <em>new</em>. New methods <em>are not</em> scanned for removed fields, field
      * access changes, etc.
      * <p>
-     * This method will eventually be removed, using {@link #advise(ComponentMethodAdvice)} or some other alternative is
+     * This method will eventually be removed, using {@link #addAdvice(ComponentMethodAdvice)} or some other alternative is
      * preferred.
      * 
      * @param body
      *            the body of Javassist psuedo-code
      * @throws RuntimeException
      *             if the provided Javassist method body can not be compiled
+     * @deprecated Use {@link #addAdvice(ComponentMethodAdvice)} instead
      */
     void extend(String body);
 
     /**
+     * Returns an object that can be used to invoke the method on an instance of the component class (regardless
+     * of the actual visibility of the method).
+     */
+    MethodAccess getAccess();
+
+    /**
      * Add advice for the method; the advice will be threaded into method invocations of the indicated method.
-     * A method may be given multiple advice; each advice will recieve control in turn (assuming
+     * A method may be given multiple advice; each advice will receive control in turn (assuming
      * the previous advice invokes {@link ComponentMethodInvocation#proceed()}) in the order the advice
      * is added. The last advice will proceed to the original method implementation.
      * 
      * @param advice
      *            to receive control when the method is invoked
      */
-    void advise(ComponentMethodAdvice advice);
+    void addAdvice(ComponentMethodAdvice advice);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethodSignature.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethodSignature.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethodSignature.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethodSignature.java Sun Jan 31 19:03:37 2010
@@ -16,17 +16,19 @@
 
 import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
 
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 import org.apache.tapestry5.internal.InternalConstants;
+import org.apache.tapestry5.ioc.services.ClassFabUtils;
 
 /**
  * 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 signature is used with
- * {@link ClassTransformation} (which operates on as-yet unloaded classes).
+ * Types are stored as class names (or primitive names) because the signature is used with {@link ClassTransformation}
+ * (which operates on as-yet unloaded classes).
  */
 public class TransformMethodSignature implements Comparable<TransformMethodSignature>
 {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java?rev=905099&r1=905098&r2=905099&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java Sun Jan 31 19:03:37 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 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
+// 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,
@@ -20,7 +20,11 @@
 import java.lang.annotation.Documented;
 import java.lang.annotation.Target;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
 
@@ -41,8 +45,10 @@
 import org.apache.tapestry5.internal.transform.InheritedAnnotation;
 import org.apache.tapestry5.internal.transform.TestPackageAwareLoader;
 import org.apache.tapestry5.internal.transform.pages.*;
+import org.apache.tapestry5.internal.util.Holder;
 import org.apache.tapestry5.ioc.internal.services.ClassFactoryClassPool;
 import org.apache.tapestry5.ioc.internal.services.ClassFactoryImpl;
+import org.apache.tapestry5.ioc.internal.services.CtClassSourceImpl;
 import org.apache.tapestry5.ioc.services.ClassFactory;
 import org.apache.tapestry5.ioc.services.PropertyAccess;
 import org.apache.tapestry5.ioc.util.BodyBuilder;
@@ -50,7 +56,13 @@
 import org.apache.tapestry5.runtime.Component;
 import org.apache.tapestry5.runtime.ComponentResourcesAware;
 import org.apache.tapestry5.services.ClassTransformation;
+import org.apache.tapestry5.services.ComponentClassTransformWorker;
+import org.apache.tapestry5.services.ComponentMethodAdvice;
+import org.apache.tapestry5.services.ComponentMethodInvocation;
+import org.apache.tapestry5.services.MethodAccess;
 import org.apache.tapestry5.services.MethodFilter;
+import org.apache.tapestry5.services.MethodInvocationResult;
+import org.apache.tapestry5.services.TransformMethod;
 import org.apache.tapestry5.services.TransformMethodSignature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,7 +74,7 @@
 /**
  * The tests share a number of resources, and so are run sequentially.
  */
-@Test(sequential = true)
+@Test
 public class InternalClassTransformationImplTest extends InternalBaseTestCase
 {
     private static final String STRING_CLASS_NAME = "java.lang.String";
@@ -77,6 +89,8 @@
 
     private ClassFactoryClassPool classFactoryClassPool;
 
+    private CtClassSourceImpl classSource;
+
     @BeforeClass
     public void setup_access()
     {
@@ -96,11 +110,11 @@
     @BeforeMethod
     public void setup_classpool()
     {
-        //  _classPool = new ClassPool();
+        ClassLoader threadDeadlockBuffer = new URLClassLoader(new URL[0], contextClassLoader);
 
-        classFactoryClassPool = new ClassFactoryClassPool(contextClassLoader);
+        classFactoryClassPool = new ClassFactoryClassPool(threadDeadlockBuffer);
 
-        loader = new TestPackageAwareLoader(contextClassLoader, classFactoryClassPool);
+        loader = new TestPackageAwareLoader(threadDeadlockBuffer, classFactoryClassPool);
 
         // Inside Maven Surefire, the system classpath is not sufficient to find all
         // the necessary files.
@@ -109,6 +123,42 @@
         Logger logger = LoggerFactory.getLogger(InternalClassTransformationImplTest.class);
 
         classFactory = new ClassFactoryImpl(loader, classFactoryClassPool, logger);
+
+        classSource = new CtClassSourceImpl(classFactoryClassPool, loader);
+    }
+
+    private Object transform(Class componentClass, ComponentClassTransformWorker worker)
+            throws Exception
+    {
+        InternalComponentResources resources = mockInternalComponentResources();
+
+        CtClass targetObjectCtClass = findCtClass(componentClass);
+
+        Logger logger = mockLogger();
+        MutableComponentModel model = mockMutableComponentModel(logger);
+
+        replay();
+
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, new ComponentClassCacheImpl(classFactory), model, classSource);
+
+        worker.transform(ct, model);
+
+        ct.finish();
+
+        Instantiator instantiator = ct.createInstantiator();
+
+        Component instance = instantiator.newInstance(resources);
+
+        verify();
+
+        expect(resources.getComponent()).andReturn(instance).anyTimes();
+
+        replay();
+
+        // Return the instance for further testing
+
+        return instance;
     }
 
     private CtClass findCtClass(Class targetClass) throws NotFoundException
@@ -203,8 +253,9 @@
         }
         catch (RuntimeException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Class org.apache.tapestry5.internal.transform.pages.ParentClass does not contain a field named 'unknownField'.");
+            assertEquals(
+                    ex.getMessage(),
+                    "Class org.apache.tapestry5.internal.transform.pages.ParentClass does not contain a field named 'unknownField'.");
         }
 
         verify();
@@ -331,8 +382,9 @@
         }
         catch (RuntimeException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Field _field4 of class org.apache.tapestry5.internal.transform.pages.ClaimedFields is already claimed by Fred and can not be claimed by Barney.");
+            assertEquals(
+                    ex.getMessage(),
+                    "Field _field4 of class org.apache.tapestry5.internal.transform.pages.ClaimedFields is already claimed by Fred and can not be claimed by Barney.");
         }
 
         verify();
@@ -393,7 +445,8 @@
 
         replay();
 
-        ClassTransformation ct = createClassTransformation(ChildClassInheritsAnnotation.class, logger);
+        ClassTransformation ct = createClassTransformation(ChildClassInheritsAnnotation.class,
+                logger);
 
         InheritedAnnotation ia = ct.getAnnotation(InheritedAnnotation.class);
 
@@ -412,7 +465,8 @@
 
         replay();
 
-        ClassTransformation ct = createClassTransformation(ChildClassInheritsAnnotation.class, logger);
+        ClassTransformation ct = createClassTransformation(ChildClassInheritsAnnotation.class,
+                logger);
 
         Meta meta = ct.getAnnotation(Meta.class);
 
@@ -449,7 +503,8 @@
     }
 
     @Test
-    public void ensure_javassist_does_not_show_interface_methods_on_abstract_class() throws Exception
+    public void ensure_javassist_does_not_show_interface_methods_on_abstract_class()
+            throws Exception
     {
         CtClass ctClass = findCtClass(AbstractFoo.class);
 
@@ -469,7 +524,8 @@
     }
 
     @Test
-    public void ensure_javassist_does_not_show_extended_interface_methods_on_interface() throws Exception
+    public void ensure_javassist_does_not_show_extended_interface_methods_on_interface()
+            throws Exception
     {
         CtClass ctClass = findCtClass(FooBarInterface.class);
 
@@ -481,6 +537,147 @@
         assertEquals(methods.length, 0);
     }
 
+    public static final TransformMethodSignature RUN = new TransformMethodSignature("run");
+
+    @Test
+    public void access_to_public_void_no_args_method() throws Exception
+    {
+        Object instance = transform(MethodAccessSubject.class, new ComponentClassTransformWorker()
+        {
+            public void transform(ClassTransformation transformation, MutableComponentModel model)
+            {
+                transformation.addImplementedInterface(Runnable.class);
+
+                TransformMethodSignature targetMethodSignature = new TransformMethodSignature(
+                        "publicVoidNoArgs");
+                TransformMethod pvna = transformation.getMethod(targetMethodSignature);
+
+                final MethodAccess pvnaAccess = pvna.getAccess();
+
+                transformation.getMethod(RUN).addAdvice(new ComponentMethodAdvice()
+                {
+                    public void advise(ComponentMethodInvocation invocation)
+                    {
+                        invocation.proceed();
+
+                        MethodInvocationResult invocationResult = pvnaAccess.invoke(invocation
+                                .getInstance());
+
+                        assertFalse(invocationResult.isFail(),
+                                "fail should be false, no checked exception thrown");
+                    }
+                });
+            }
+        });
+
+        Runnable r = (Runnable) instance;
+
+        r.run();
+
+        assertEquals(access.get(r, "marker"), "publicVoidNoArgs");
+    }
+
+    @Test
+    public void access_to_public_void_throws_exception() throws Exception
+    {
+        Object instance = transform(MethodAccessSubject.class, new ComponentClassTransformWorker()
+        {
+            public void transform(ClassTransformation transformation, MutableComponentModel model)
+            {
+                transformation.addImplementedInterface(Runnable.class);
+
+                TransformMethodSignature targetMethodSignature = new TransformMethodSignature(
+                        Modifier.PUBLIC, "void", "publicVoidThrowsException", null, new String[]
+                        { SQLException.class.getName() });
+                TransformMethod targetMethod = transformation.getMethod(targetMethodSignature);
+
+                final MethodAccess targetAccess = targetMethod.getAccess();
+
+                transformation.getMethod(RUN).addAdvice(new ComponentMethodAdvice()
+                {
+                    public void advise(ComponentMethodInvocation invocation)
+                    {
+                        invocation.proceed();
+
+                        MethodInvocationResult invocationResult = targetAccess.invoke(invocation
+                                .getInstance());
+
+                        assertTrue(invocationResult.isFail(),
+                                "fail should be true; checked exception thrown");
+
+                        SQLException ex = invocationResult.getThrown(SQLException.class);
+
+                        assertNotNull(ex);
+                        assertEquals(ex.getMessage(), "From publicVoidThrowsException()");
+                    }
+                });
+            }
+        });
+
+        Runnable r = (Runnable) instance;
+
+        r.run();
+
+        assertEquals(access.get(r, "marker"), "publicVoidThrowsException");
+    }
+
+    public interface ProcessInteger
+    {
+        int operate(int input);
+    }
+
+    @Test
+    public void access_to_public_method_with_argument_and_return_value() throws Exception
+    {
+        Object instance = transform(MethodAccessSubject.class, new ComponentClassTransformWorker()
+        {
+            public void transform(ClassTransformation transformation, MutableComponentModel model)
+            {
+                transformation.addImplementedInterface(ProcessInteger.class);
+
+                TransformMethod incrementer = transformation
+                        .getMethod(new TransformMethodSignature(Modifier.PUBLIC, "int",
+                                "incrementer", new String[]
+                                { "int" }, null));
+
+                final MethodAccess incrementerAccess = incrementer.getAccess();
+
+                TransformMethodSignature operateSig = new TransformMethodSignature(Modifier.PUBLIC,
+                        "int", "operate", new String[]
+                        { "int" }, null);
+
+                TransformMethod operate = transformation.getMethod(operateSig);
+
+                operate.addAdvice(new ComponentMethodAdvice()
+                {
+                    public void advise(ComponentMethodInvocation invocation)
+                    {
+                        // This advice *replaces* the original do-nothing method, because
+                        // it never calls invocation.proceed().
+
+                        // This kind of advice always needs some special knowledge of
+                        // the parameters to the original method, so that they can be mapped
+                        // to some other method (including a MethodAccess).
+
+                        Integer parameter = (Integer) invocation.getParameter(0);
+
+                        MethodInvocationResult result = incrementerAccess.invoke(invocation
+                                .getInstance(), parameter);
+
+                        invocation.overrideResult(result.getReturnValue());
+                    }
+                });
+            }
+        });
+
+        ProcessInteger pi = (ProcessInteger) instance;
+
+        assertEquals(pi.operate(99), 100);
+
+        assertEquals(access.get(instance, "marker"), "incrementer(99)");
+
+    }
+
     @Test
     public void add_injected_field() throws Exception
     {
@@ -493,8 +690,8 @@
 
         replay();
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         // Default behavior is to add an injected field for the InternalComponentResources object,
         // so we'll just check that.
@@ -526,8 +723,8 @@
 
         replay();
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         String parentFieldName = ct.addInjectedField(String.class, "_value", value);
 
@@ -550,8 +747,8 @@
 
         // This proves the the field is protected and can be used in subclasses.
 
-        ct.addMethod(new TransformMethodSignature(Modifier.PUBLIC, "java.lang.String", "getValue", null, null),
-                     "return " + subclassFieldName + ";");
+        ct.addMethod(new TransformMethodSignature(Modifier.PUBLIC, "java.lang.String", "getValue",
+                null, null), "return " + subclassFieldName + ";");
 
         ct.finish();
 
@@ -578,8 +775,8 @@
 
         replay();
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         ct.addImplementedInterface(FooInterface.class);
         ct.addImplementedInterface(GetterMethodsInterface.class);
@@ -590,7 +787,8 @@
 
         Class[] interfaces = transformed.getInterfaces();
 
-        assertEquals(interfaces, new Class[] { Component.class, FooInterface.class, GetterMethodsInterface.class });
+        assertEquals(interfaces, new Class[]
+        { Component.class, FooInterface.class, GetterMethodsInterface.class });
 
         Object target = ct.createInstantiator().newInstance(resources);
 
@@ -626,8 +824,8 @@
 
         CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         ct.makeReadOnly("_value");
 
@@ -645,7 +843,7 @@
             // The PropertyAccess layer adds a wrapper exception around the real one.
 
             assertEquals(ex.getCause().getMessage(),
-                         "Field org.apache.tapestry5.internal.transform.pages.ReadOnlyBean._value is read-only.");
+                    "Field org.apache.tapestry5.internal.transform.pages.ReadOnlyBean._value is read-only.");
         }
 
         verify();
@@ -661,8 +859,8 @@
 
         CtClass targetObjectCtClass = findCtClass(RemoveFieldBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(null, targetObjectCtClass, null, model,
-                                                                             null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(null,
+                targetObjectCtClass, null, model, null);
 
         ct.removeField("_barney");
 
@@ -683,8 +881,8 @@
 
         CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         ct.extendConstructor("_value = \"from constructor\";");
 
@@ -709,8 +907,8 @@
 
         CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         ct.injectField("_value", "Tapestry");
 
@@ -730,7 +928,7 @@
             // The PropertyAccess layer adds a wrapper exception around the real one.
 
             assertEquals(ex.getCause().getMessage(),
-                         "Field org.apache.tapestry5.internal.transform.pages.ReadOnlyBean._value is read-only.");
+                    "Field org.apache.tapestry5.internal.transform.pages.ReadOnlyBean._value is read-only.");
         }
 
         verify();
@@ -752,8 +950,8 @@
 
         CtClass targetObjectCtClass = findCtClass(FieldAccessBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         replaceAccessToField(ct, "foo");
         replaceAccessToField(ct, "bar");
@@ -804,20 +1002,21 @@
         String fieldName = "_" + baseName;
         String readMethodName = "_read_" + baseName;
 
-        TransformMethodSignature readMethodSignature = new TransformMethodSignature(Modifier.PRIVATE, STRING_CLASS_NAME,
-                                                                                    readMethodName, null, null);
+        TransformMethodSignature readMethodSignature = new TransformMethodSignature(
+                Modifier.PRIVATE, STRING_CLASS_NAME, readMethodName, null, null);
 
-        ct.addMethod(readMethodSignature, String.format("throw new RuntimeException(\"read %s\");", baseName));
+        ct.addMethod(readMethodSignature, String.format("throw new RuntimeException(\"read %s\");",
+                baseName));
 
         ct.replaceReadAccess(fieldName, readMethodName);
 
         String writeMethodName = "_write_" + baseName;
 
-        TransformMethodSignature writeMethodSignature = new TransformMethodSignature(Modifier.PRIVATE, "void",
-                                                                                     writeMethodName,
-                                                                                     new String[] { STRING_CLASS_NAME },
-                                                                                     null);
-        ct.addMethod(writeMethodSignature, String.format("throw new RuntimeException(\"write %s\");", baseName));
+        TransformMethodSignature writeMethodSignature = new TransformMethodSignature(
+                Modifier.PRIVATE, "void", writeMethodName, new String[]
+                { STRING_CLASS_NAME }, null);
+        ct.addMethod(writeMethodSignature, String.format(
+                "throw new RuntimeException(\"write %s\");", baseName));
 
         ct.replaceWriteAccess(fieldName, writeMethodName);
     }
@@ -932,8 +1131,8 @@
         }
         catch (RuntimeException ex)
         {
-            assertMessageContains(ex, "Class " + VisibilityBean.class.getName() + " contains field(s)",
-                                  "_$myPackagePrivate", "_$myProtected", "_$myPublic");
+            assertMessageContains(ex, "Class " + VisibilityBean.class.getName()
+                    + " contains field(s)", "_$myPackagePrivate", "_$myProtected", "_$myPublic");
         }
 
         verify();
@@ -948,7 +1147,8 @@
 
         ClassTransformation ct = createClassTransformation(EventHandlerTarget.class, logger);
 
-        OnEvent annotation = ct.getMethodAnnotation(new TransformMethodSignature("handler"), OnEvent.class);
+        OnEvent annotation = ct.getMethodAnnotation(new TransformMethodSignature("handler"),
+                OnEvent.class);
 
         // Check that the attributes of the annotation match the expectation.
 
@@ -974,8 +1174,9 @@
         }
         catch (IllegalArgumentException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Class org.apache.tapestry5.internal.transform.pages.ParentClass does not declare method 'public void foo()'.");
+            assertEquals(
+                    ex.getMessage(),
+                    "Class org.apache.tapestry5.internal.transform.pages.ParentClass does not declare method 'public void foo()'.");
         }
 
         verify();
@@ -985,8 +1186,8 @@
     public void prefix_method() throws Exception
     {
         Logger logger = mockLogger();
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int", "getParentField", null,
-                                                                    null);
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int",
+                "getParentField", null, null);
 
         replay();
 
@@ -1008,7 +1209,6 @@
         {
         }
 
-
         verify();
     }
 
@@ -1016,8 +1216,8 @@
     public void fields_in_prefixed_methods_are_transformed() throws Exception
     {
         Logger logger = mockLogger();
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int", "getTargetValue", null,
-                                                                    null);
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int",
+                "getTargetValue", null, null);
         Runnable runnable = mockRunnable();
 
         runnable.run();
@@ -1030,8 +1230,8 @@
 
         // Transform the field.
 
-        TransformMethodSignature reader = new TransformMethodSignature(Modifier.PRIVATE, "int", "read_target_value",
-                                                                       null, null);
+        TransformMethodSignature reader = new TransformMethodSignature(Modifier.PRIVATE, "int",
+                "read_target_value", null, null);
 
         ct.addMethod(reader, "return 66;");
 
@@ -1051,7 +1251,7 @@
     }
 
     private Component instantiate(Class<?> expectedClass, InternalClassTransformation ct,
-                                  InternalComponentResources resources) throws Exception
+            InternalComponentResources resources) throws Exception
     {
         Instantiator ins = ct.createInstantiator();
 
@@ -1062,8 +1262,8 @@
     public void extend_existing_method_fields_are_transformed() throws Exception
     {
         Logger logger = mockLogger();
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int", "getTargetValue", null,
-                                                                    null);
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int",
+                "getTargetValue", null, null);
         Runnable runnable = mockRunnable();
 
         runnable.run();
@@ -1076,8 +1276,8 @@
 
         // Transform the field.
 
-        TransformMethodSignature reader = new TransformMethodSignature(Modifier.PRIVATE, "int", "read_target_value",
-                                                                       null, null);
+        TransformMethodSignature reader = new TransformMethodSignature(Modifier.PRIVATE, "int",
+                "read_target_value", null, null);
 
         ct.addMethod(reader, "return 66;");
 
@@ -1106,8 +1306,8 @@
     public void invalid_code() throws Exception
     {
         Logger logger = mockLogger();
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int", "getParentField", null,
-                                                                    null);
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, "int",
+                "getParentField", null, null);
 
         replay();
 
@@ -1126,7 +1326,6 @@
         verify();
     }
 
-
     @Test
     public void remove_field() throws Exception
     {
@@ -1137,8 +1336,8 @@
 
         CtClass targetObjectCtClass = findCtClass(FieldRemoval.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory, targetObjectCtClass, null,
-                                                                             model, null);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(classFactory,
+                targetObjectCtClass, null, model, null);
 
         ct.removeField("_fieldToRemove");
 
@@ -1170,8 +1369,9 @@
 
         TransformMethodSignature sig = sigs.get(0);
 
-        assertEquals(ct.getMethodIdentifier(sig),
-                     "org.apache.tapestry5.internal.transform.pages.MethodIdentifier.makeWaves(java.lang.String, int[]) (at MethodIdentifier.java:24)");
+        assertEquals(
+                ct.getMethodIdentifier(sig),
+                "org.apache.tapestry5.internal.transform.pages.MethodIdentifier.makeWaves(java.lang.String, int[]) (at MethodIdentifier.java:24)");
 
         verify();
     }
@@ -1202,7 +1402,6 @@
             assertFalse(ct.isMethodOverride(sig));
         }
 
-
         verify();
     }
 
@@ -1224,8 +1423,9 @@
         }
         catch (IllegalArgumentException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Method public void methodDoesNotExist() is not implemented by transformed class org.apache.tapestry5.internal.services.SimpleBean.");
+            assertEquals(
+                    ex.getMessage(),
+                    "Method public void methodDoesNotExist() is not implemented by transformed class org.apache.tapestry5.internal.services.SimpleBean.");
         }
 
         verify();
@@ -1239,21 +1439,21 @@
 
         replay();
 
-        InternalClassTransformation parentTransform = createClassTransformation(SimpleBean.class, logger);
+        InternalClassTransformation parentTransform = createClassTransformation(SimpleBean.class,
+                logger);
 
         parentTransform.finish();
 
         CtClass childClass = findCtClass(SimpleBeanSubclass.class);
 
         ClassTransformation childTransform = parentTransform.createChildTransformation(childClass,
-                                                                                       stubMutableComponentModel(
-                                                                                               logger));
+                stubMutableComponentModel(logger));
 
         assertFalse(childTransform.isMethodOverride(new TransformMethodSignature("notOverridden")));
 
-        assertTrue(childTransform.isMethodOverride(
-                new TransformMethodSignature(Modifier.PUBLIC, "void", "setAge", new String[] { "int" }, null)));
+        assertTrue(childTransform.isMethodOverride(new TransformMethodSignature(Modifier.PUBLIC,
+                "void", "setAge", new String[]
+                { "int" }, null)));
     }
 
-
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java?rev=905099&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java Sun Jan 31 19:03:37 2010
@@ -0,0 +1,59 @@
+// Copyright 2010 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.transform.pages;
+
+import java.sql.SQLException;
+
+import org.apache.tapestry5.internal.services.InternalClassTransformationImplTest;
+
+/**
+ * Used by {@link InternalClassTransformationImplTest} for a number of tests related to
+ * method access.
+ */
+public class MethodAccessSubject
+{
+    private String marker;
+
+    public String getMarker()
+    {
+        return marker;
+    }
+
+    public void publicVoidNoArgs()
+    {
+        marker = "publicVoidNoArgs";
+    }
+
+    public void publicVoidNoArgsFail()
+    {
+        marker = "publicVoidNoArgsFail";
+
+        throw new RuntimeException("Fail inside pvnoaf.");
+    }
+
+    public int incrementer(int input)
+    {
+        marker = "incrementer(" + input + ")";
+
+        return input + 1;
+    }
+
+    public void publicVoidThrowsException() throws SQLException
+    {
+        marker = "publicVoidThrowsException";
+
+        throw new SQLException("From publicVoidThrowsException()");
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/pages/MethodAccessSubject.java
------------------------------------------------------------------------------
    svn:eol-style = native