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/07/24 04:17:54 UTC

svn commit: r1150252 - in /tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5: internal/transform/PageResetAnnotationWorker.java services/TapestryModule.java services/TransformConstants.java

Author: hlship
Date: Sun Jul 24 02:17:53 2011
New Revision: 1150252

URL: http://svn.apache.org/viewvc?rev=1150252&view=rev
Log:
TAP5-1508: Record PageResetAnnotationWorker to implement CCTW2

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java?rev=1150252&r1=1150251&r2=1150252&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageResetAnnotationWorker.java Sun Jul 24 02:17:53 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2011 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,133 +14,123 @@
 
 package org.apache.tapestry5.internal.transform;
 
-import java.util.List;
-
 import org.apache.tapestry5.annotations.PageReset;
-import org.apache.tapestry5.func.Predicate;
+import org.apache.tapestry5.func.*;
 import org.apache.tapestry5.internal.InternalComponentResources;
 import org.apache.tapestry5.internal.structure.PageResetListener;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.model.MutableComponentModel;
-import org.apache.tapestry5.runtime.Component;
-import org.apache.tapestry5.services.*;
+import org.apache.tapestry5.plastic.*;
+import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
+import org.apache.tapestry5.services.transform.TransformationSupport;
 
 /**
  * Implementation of the {@link PageReset} annotation. Makes the component implement {@link PageResetListener}.
- * 
+ *
  * @since 5.2.0
  */
-public class PageResetAnnotationWorker implements ComponentClassTransformWorker
+public class PageResetAnnotationWorker implements ComponentClassTransformWorker2
 {
     private static final String META_KEY = "tapestry.page-reset-listener";
 
-    private static final TransformMethodSignature CONTAINING_PAGE_DID_RESET = new TransformMethodSignature(
-            "containingPageDidReset");
-
-    private final ComponentMethodAdvice registerAsListenerAdvice = new ComponentMethodAdvice()
+    private final MethodAdvice REGISTER_AS_LISTENER = new MethodAdvice()
     {
-        public void advise(ComponentMethodInvocation invocation)
+        public void advise(MethodInvocation invocation)
         {
             invocation.proceed();
 
-            InternalComponentResources icr = (InternalComponentResources) invocation.getComponentResources();
+            InternalComponentResources resources = invocation.getInstanceContext().get(InternalComponentResources.class);
 
-            icr.addPageResetListener((PageResetListener) invocation.getInstance());
+            resources.addPageResetListener((PageResetListener) invocation.getInstance());
         }
     };
 
-    public void transform(final ClassTransformation transformation, MutableComponentModel model)
+    private final Predicate<PlasticMethod> METHOD_MATCHER = new Predicate<PlasticMethod>()
     {
-        List<TransformMethod> methods = matchPageResetMethods(transformation);
+        public boolean accept(PlasticMethod method)
+        {
+            return method.getDescription().methodName.equalsIgnoreCase("pageReset") ||
+                    method.hasAnnotation(PageReset.class);
+        }
+    };
 
-        if (methods.isEmpty())
-            return;
+    private final Worker<PlasticMethod> METHOD_VALIDATOR = new Worker<PlasticMethod>()
+    {
+        public void work(PlasticMethod method)
+        {
+            boolean valid = method.isVoid() && method.getParameters().isEmpty();
 
-        makeComponentRegisterAsPageResetListenerAtPageLoad(transformation, model);
+            if (!valid)
+            {
+                throw new RuntimeException(
+                        String.format(
+                                "Method %s is invalid: methods with the @PageReset annotation must return void, and have no parameters.",
+                                method.getMethodIdentifier()));
+            }
+        }
+    };
 
-        adviseContainingPageDidResetMethod(transformation, methods);
-    }
+    private final Mapper<PlasticMethod, MethodHandle> TO_HANDLE = new Mapper<PlasticMethod, MethodHandle>()
+    {
+        public MethodHandle map(PlasticMethod method)
+        {
+            return method.getHandle();
+        }
+    };
 
-    private void adviseContainingPageDidResetMethod(ClassTransformation transformation, List<TransformMethod> methods)
+    public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model)
     {
-        List<MethodAccess> methodAccess = convertToMethodAccess(methods);
+        Flow<PlasticMethod> methods = findResetMethods(plasticClass);
 
-        ComponentInstanceOperation advice = createMethodAccessAdvice(methodAccess);
+        if (!methods.isEmpty())
+        {
+            registerAsPageResetListenerAtPageLoad(plasticClass, model);
 
-        transformation.getOrCreateMethod(CONTAINING_PAGE_DID_RESET).addOperationAfter(advice);
+            invokeMethodsOnPageReset(plasticClass, methods);
+        }
     }
 
-    private ComponentInstanceOperation createMethodAccessAdvice(final List<MethodAccess> methodAccess)
+    private void invokeMethodsOnPageReset(PlasticClass plasticClass, Flow<PlasticMethod> methods)
     {
-        return new ComponentInstanceOperation()
-        {
+        final MethodHandle[] handles = methods.map(TO_HANDLE).toArray(MethodHandle.class);
 
-            public void invoke(Component instance)
+        plasticClass.introduceMethod(TransformConstants.CONTAINING_PAGE_DID_RESET_DESCRIPTION).addAdvice(new MethodAdvice()
+        {
+            public void advise(MethodInvocation invocation)
             {
-                for (MethodAccess access : methodAccess)
-                {
-                    MethodInvocationResult result = access.invoke(instance);
+                invocation.proceed();
 
-                    result.rethrow();
+                Object instance = invocation.getInstance();
+
+                for (MethodHandle handle : handles)
+                {
+                    handle.invoke(instance);
                 }
             }
-        };
+        });
     }
 
-    private List<MethodAccess> convertToMethodAccess(List<TransformMethod> methods)
+    private void registerAsPageResetListenerAtPageLoad(PlasticClass plasticClass, MutableComponentModel model)
     {
-        List<MethodAccess> result = CollectionFactory.newList();
-
-        for (TransformMethod method : methods)
-        {
-            result.add(toMethodAccess(method));
-        }
 
-        return result;
-    }
-
-    private void makeComponentRegisterAsPageResetListenerAtPageLoad(final ClassTransformation transformation,
-            MutableComponentModel model)
-    {
         // The meta key tracks whether this has already occurred; it is only necessary for a base class
         // (subclasses, even if they include pageReset methods, do not need to re-register if the base class
         // already has).
 
         if (model.getMeta(META_KEY) != null)
+        {
             return;
+        }
 
-        transformation.addImplementedInterface(PageResetListener.class);
+        plasticClass.introduceInterface(PageResetListener.class);
 
-        transformation.getOrCreateMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE).addAdvice(
-                registerAsListenerAdvice);
+        plasticClass.introduceMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_DESCRIPTION).addAdvice(REGISTER_AS_LISTENER);
 
         model.setMeta(META_KEY, "true");
     }
 
-    private List<TransformMethod> matchPageResetMethods(final ClassTransformation transformation)
+    private Flow<PlasticMethod> findResetMethods(PlasticClass plasticClass)
     {
-        return transformation.matchMethods(new Predicate<TransformMethod>()
-        {
-            public boolean accept(TransformMethod method)
-            {
-                return method.getName().equalsIgnoreCase("pageReset") || method.getAnnotation(PageReset.class) != null;
-            }
-        });
-    }
-
-    private MethodAccess toMethodAccess(TransformMethod method)
-    {
-        TransformMethodSignature sig = method.getSignature();
-
-        boolean valid = sig.getParameterTypes().length == 0 && sig.getReturnType().equals("void");
-
-        if (!valid)
-            throw new RuntimeException(
-                    String
-                            .format(
-                                    "Method %s is invalid: methods with the @PageReset annotation must return void, and have no parameters.",
-                                    method.getMethodIdentifier()));
-
-        return method.getAccess();
+        return F.flow(plasticClass.getMethods()).filter(METHOD_MATCHER).each(METHOD_VALIDATOR);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=1150252&r1=1150251&r2=1150252&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Sun Jul 24 02:17:53 2011
@@ -518,6 +518,9 @@ public final class TapestryModule
      * <dt>PageActivationContext</dt> <dd>Support for {@link PageActivationContext} annotation</dd>
      * <dt>DiscardAfter</dt> <dd>Support for {@link DiscardAfter} method annotation </dd>
      * <dt>MixinAfter</dt> <dd>Support for the {@link MixinAfter} mixin class annotation</dd>
+     * <dt>PageReset</dt>
+     * <dd>Checks for the {@link PageReset} annotation</dd>
+     * <p/>
      * <dt>Cached</dt>
      * <dd>Checks for the {@link org.apache.tapestry5.annotations.Cached} annotation</dd>
      * </dl>
@@ -575,6 +578,8 @@ public final class TapestryModule
 
         configuration.addInstance("DiscardAfter", DiscardAfterWorker.class);
 
+        configuration.addInstance("PageReset", PageResetAnnotationWorker.class);
+
         // This one is always last. Any additional private fields that aren't
         // annotated will
         // be converted to clear out at the end of the request.
@@ -606,8 +611,6 @@ public final class TapestryModule
      * <dd>Converts fields that reference application state objects
      * <dt>Log</dt>
      * <dd>Checks for the {@link org.apache.tapestry5.annotations.Log} annotation</dd>
-     * <dt>PageReset
-     * <dd>Checks for the {@link PageReset} annotation
      * <dt>HeartbeatDeferred
      * <dd>Support for the {@link HeartbeatDeferred} annotation
      * <dt>ActivationRequestParameter
@@ -641,8 +644,6 @@ public final class TapestryModule
 
         configuration.addInstance("Log", LogWorker.class);
 
-        configuration.addInstance("PageReset", PageResetAnnotationWorker.class);
-
         configuration.addInstance("SessionAttribute", SessionAttributeWorker.class);
 
         configuration.addInstance("HeartbeatDeferred", HeartbeatDeferredWorker.class, "after:RenderPhase");

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java?rev=1150252&r1=1150251&r2=1150252&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java Sun Jul 24 02:17:53 2011
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.services;
 
 import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.internal.structure.PageResetListener;
 import org.apache.tapestry5.plastic.MethodDescription;
 import org.apache.tapestry5.plastic.PlasticUtils;
 import org.apache.tapestry5.runtime.Component;
@@ -83,6 +84,16 @@ public final class TransformConstants
             PageLifecycleListener.class, "containingPageDidLoad");
 
     /**
+     * Description for {@link org.apache.tapestry5.internal.structure.PageResetListener#containingPageDidReset()}. Note that the {@link PageResetListener}
+     * interface is not automatically implemeneted by components. ]
+     *
+     * @see org.apache.tapestry5.annotations.PageReset
+     * @see org.apache.tapestry5.internal.transform.PageResetAnnotationWorker
+     * @since 5.3
+     */
+    public static final MethodDescription CONTAINING_PAGE_DID_RESET_DESCRIPTION = PlasticUtils.getMethodDescription(PageResetListener.class, "containingPageDidReset");
+
+    /**
      * Signature for {@link org.apache.tapestry5.runtime.Component#postRenderCleanup()}.
      */
     public static final TransformMethodSignature POST_RENDER_CLEANUP_SIGNATURE = new TransformMethodSignature(