You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2011/04/10 03:54:37 UTC

svn commit: r1090730 - in /tapestry/tapestry5/trunk/plastic/src: main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java main/java/org/apache/tapestry5/plastic/PlasticClass.java test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy

Author: hlship
Date: Sun Apr 10 01:54:37 2011
New Revision: 1090730

URL: http://svn.apache.org/viewvc?rev=1090730&view=rev
Log:
TAP5-853: Add a new method for creating a private method with a unique name (frequently used when creating proxy objects)

Modified:
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
    tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java?rev=1090730&r1=1090729&r2=1090730&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java Sun Apr 10 01:54:37 2011
@@ -1690,6 +1690,22 @@ public class PlasticClassImpl extends Lo
         return unclaimedFields;
     }
 
+    public PlasticMethod introducePrivateMethod(String typeName, String suggestedName, String[] argumentTypes,
+            String[] exceptionTypes)
+    {
+        check();
+
+        assert PlasticInternalUtils.isNonBlank(typeName);
+        assert PlasticInternalUtils.isNonBlank(suggestedName);
+
+        String name = makeUnique(methodNames, suggestedName);
+
+        MethodDescription description = new MethodDescription(Modifier.PRIVATE, typeName, name, argumentTypes,
+                exceptionTypes);
+
+        return introduceMethod(description);
+    }
+
     public PlasticField introduceField(String className, String suggestedName)
     {
         check();
@@ -1762,6 +1778,8 @@ public class PlasticClassImpl extends Lo
             description2method.put(description, result);
         }
 
+        methodNames.add(description.methodName);
+        
         // Note that is it not necessary to add the new MethodNode to
         // fieldTransformMethods (the default implementations provided by introduceMethod() do not
         // ever access instance fields) ... unless the caller invokes changeImplementation().

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java?rev=1090730&r1=1090729&r2=1090730&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java Sun Apr 10 01:54:37 2011
@@ -79,6 +79,22 @@ public interface PlasticClass extends An
     PlasticField introduceField(Class fieldType, String suggestedName);
 
     /**
+     * Introduces a new private method into the class, ensuring that the method name is unique.
+     * 
+     * @param typeName
+     *            return type of method
+     * @param suggestedName
+     *            suggested name for the method; the actual method name may be modified to ensure uniqueness
+     * @param argumentTypes
+     *            types of any arguments (may be null)
+     * @param exceptionTypes
+     *            type of any checked exceptions (may be null)
+     * @return new method, with default implementation
+     */
+    PlasticMethod introducePrivateMethod(String typeName, String suggestedName, String[] argumentTypes,
+            String[] exceptionTypes);
+
+    /**
      * Matches methods with the given annotation.
      * 
      * @return Unmodifiable list of methods, in sorted order.

Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy?rev=1090730&r1=1090729&r2=1090730&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ProxyCreation.groovy Sun Apr 10 01:54:37 2011
@@ -7,7 +7,7 @@ import testinterfaces.AnnotationTransfer
 import testsubjects.AnnotationTransferImpl
 
 class ProxyCreation extends Specification {
-    def "create a proxy"() {
+    def "create a field delegating proxy"() {
         setup:
 
         def mgr = new PlasticManager()
@@ -37,6 +37,49 @@ class ProxyCreation extends Specificatio
         r.run()
     }
 
+    def "create a method delegating proxy"() {
+        setup:
+        "Each method of the interface delegates through a method that returns the new target for the method."
+        
+        def mgr = new PlasticManager()
+
+        Runnable r = Mock(Runnable)
+
+        def ins = mgr.createProxy(Runnable.class, {
+            PlasticClass pc ->
+            def f = pc.introduceField(Runnable.class, "delegate").inject(r)
+
+            PlasticMethod dm = pc.introducePrivateMethod(Runnable.class.name, "run", null, null)
+
+            assert dm.description.methodName != "run"
+
+            dm.changeImplementation({
+                it.loadThis().getField(f).returnResult()
+            } as InstructionBuilderCallback)
+
+            Runnable.class.methods.each( { m -> pc.introduceMethod(m).delegateTo(dm) })
+
+            pc.introduceMethod(new MethodDescription("void", "run")).delegateTo(f)
+        } as PlasticClassTransformer)
+
+        when:
+
+        def proxy = ins.newInstance()
+
+        then:
+
+        assert proxy instanceof Runnable
+
+        when:
+
+        proxy.run()
+
+        then:
+
+        r.run()
+    }
+
+
     def "type must be an interface"() {
         setup:
         def mgr = new PlasticManager()