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/11/23 06:24:14 UTC

svn commit: r478469 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/internal/services/ test/conf/ test/java/org/apache/tapestry/internal/services/

Author: hlship
Date: Wed Nov 22 21:24:11 2006
New Revision: 478469

URL: http://svn.apache.org/viewvc?view=rev&rev=478469
Log:
Run tests in parallel.
Add support for listeners (that are notified whenever a new Link object is created by the LinkFactory).

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryListener.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java?view=diff&rev=478469&r1=478468&r2=478469
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java Wed Nov 22 21:24:11 2006
@@ -12,40 +12,44 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import org.apache.tapestry.Link;
-import org.apache.tapestry.internal.structure.ComponentPageElement;
-import org.apache.tapestry.internal.structure.Page;
-
-/**
- * A source for {@link Link} objects.
- */
-public interface LinkFactory
-{
-    /**
-     * Creates a stateful action link. Action links are built for components. Action links are
-     * encoded by the current request (that is, bound to the current request's session, if any).
-     * 
-     * @param component
-     *            the component for which an action link is to be generated
-     * @param action
-     *            a name associated with the action
-     * @param forForm
-     *            true if the link is for a form, false otherwise
-     * @param context
-     *            Additional path data, each value will be converted to a string and appended to the
-     *            URI
-     * @return a link
-     */
-    Link createActionLink(ComponentPageElement component, String action, boolean forForm,
-            Object... context);
-
-    /**
-     * Creates a link to a page. TODO: What about context? Additional query parameters?
-     * 
-     * @param page
-     * @return
-     */
-    Link createPageLink(Page page);
-}
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.Link;
+import org.apache.tapestry.internal.structure.ComponentPageElement;
+import org.apache.tapestry.internal.structure.Page;
+
+/**
+ * A source for {@link Link} objects.
+ * 
+ * @see LinkFactoryListener
+ */
+public interface LinkFactory
+{
+    /**
+     * Creates a stateful action link. Action links are built for components. Action links are
+     * encoded by the current request (that is, bound to the current request's session, if any).
+     * 
+     * @param component
+     *            the component for which an action link is to be generated
+     * @param action
+     *            a name associated with the action
+     * @param forForm
+     *            true if the link is for a form, false otherwise
+     * @param context
+     *            Additional path data, each value will be converted to a string and appended to the
+     *            URI
+     * @return a link
+     */
+    Link createActionLink(ComponentPageElement component, String action, boolean forForm,
+            Object... context);
+
+    /**
+     * Creates a link to a page. TODO: What about context? Additional query parameters?
+     * 
+     * @param page
+     * @return
+     */
+    Link createPageLink(Page page);
+
+    void addListener(LinkFactoryListener listener);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java?view=diff&rev=478469&r1=478468&r2=478469
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java Wed Nov 22 21:24:11 2006
@@ -16,6 +16,7 @@
 
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newThreadSafeList;
 
 import java.util.Collection;
 import java.util.List;
@@ -41,13 +42,15 @@
 
     private final ComponentClassResolver _componentClassResolver;
 
+    private final List<LinkFactoryListener> _listeners = newThreadSafeList();
+
+    private final StrategyRegistry<PassivateContextHandler> _registry;
+
     private interface PassivateContextHandler<T>
     {
         void handle(T result, List context);
     }
 
-    private final StrategyRegistry<PassivateContextHandler> _registry;
-
     public LinkFactoryImpl(WebRequest request, WebResponse response,
             ComponentClassResolver componentClassResolver)
     {
@@ -89,6 +92,11 @@
         _registry = StrategyRegistry.newInstance(PassivateContextHandler.class, registrations);
     }
 
+    public void addListener(LinkFactoryListener listener)
+    {
+        _listeners.add(listener);
+    }
+
     public Link createActionLink(ComponentPageElement component, String action, boolean forForm,
             Object... context)
     {
@@ -117,10 +125,15 @@
             builder.append(id.toString());
         }
 
+        Link link = new LinkImpl(_response, builder.toString());
+
+        for (LinkFactoryListener listener : _listeners)
+            listener.createdActionLink(link);
+
         // TODO: Much more: query parameter for case where active page != component page.
         // Letting listeners add extra parameters.
 
-        return new LinkImpl(_response, builder.toString());
+        return link;
     }
 
     public Link createPageLink(final Page page)
@@ -163,6 +176,14 @@
             builder.append(id.toString());
         }
 
-        return new LinkImpl(_response, builder.toString());
+        Link link = new LinkImpl(_response, builder.toString());
+
+        for (LinkFactoryListener listener : _listeners)
+            listener.createdPageLink(link);
+
+        // TODO: Much more: query parameter for case where active page != component page.
+        // Letting listeners add extra parameters.
+
+        return link;
     }
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryListener.java?view=auto&rev=478469
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryListener.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryListener.java Wed Nov 22 21:24:11 2006
@@ -0,0 +1,28 @@
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.Link;
+
+/** Listener interface for objects that need to be notified about newly created links. */
+
+public interface LinkFactoryListener
+{
+    /**
+     * Invoked when a page link (a link that renders a page) is created. The listener may decide to
+     * encode additional query parameters into the link (via
+     * {@link Link#addParameter(String, String)}).
+     * 
+     * @param link
+     *            the newly created link
+     */
+    void createdPageLink(Link link);
+
+    /**
+     * Invoked when an action link (a link that asks a component to perform an action) is created.
+     * The listener may decide to encode additional query parameters into the link (via
+     * {@link Link#addParameter(String, String)}).
+     * 
+     * @param link
+     *            the newly created link
+     */
+    void createdActionLink(Link link);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?view=diff&rev=478469&r1=478468&r2=478469
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Wed Nov 22 21:24:11 2006
@@ -15,7 +15,7 @@
    limitations under the License.
 -->
 
-<suite name="Tapestry Core" parallel="false" thread-count="10" annotations="1.5" verbose="2">
+<suite name="Tapestry Core" parallel="true" thread-count="10" annotations="1.5" verbose="2">
   <test name="Tapestry Core">
     <packages>
       <package name="org.apache.tapestry.integration"/>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java?view=diff&rev=478469&r1=478468&r2=478469
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java Wed Nov 22 21:24:11 2006
@@ -20,6 +20,7 @@
 import org.apache.tapestry.internal.structure.ComponentPageElement;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.internal.util.Holder;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.WebRequest;
 import org.apache.tapestry.services.WebResponse;
@@ -72,6 +73,9 @@
         ComponentClassResolver resolver = newComponentClassResolver();
         Page page = newPage();
         ComponentPageElement rootElement = newComponentPageElement();
+        LinkFactoryListener listener = newLinkFactoryListener();
+
+        final Holder<Link> holder = new Holder<Link>();
 
         train_getName(page, PAGE_CLASS_NAME);
         train_resolvePageClassNameToPageName(resolver, PAGE_CLASS_NAME, PAGE_LOGICAL_NAME);
@@ -81,7 +85,7 @@
 
         // Answer for triggerEvent() which returns a boolean.
 
-        IAnswer<Boolean> answer = new IAnswer<Boolean>()
+        IAnswer<Boolean> triggerEventAnswer = new IAnswer<Boolean>()
         {
             public Boolean answer() throws Throwable
             {
@@ -95,31 +99,57 @@
             }
         };
 
+        IAnswer<Void> createdPageLinkAnswer = new IAnswer<Void>()
+        {
+            public Void answer() throws Throwable
+            {
+                Link link = (Link) EasyMock.getCurrentArguments()[0];
+
+                holder.put(link);
+
+                return null;
+            }
+        };
+
         // Intercept the call to handle component event, and let the IAnswer
         // do the work.
 
-        rootElement.triggerEvent(
-                EasyMock.eq(TapestryConstants.PASSIVATE_EVENT),
-                (Object[]) EasyMock.isNull(),
-                EasyMock.isA(ComponentEventHandler.class));
-        getMocksControl().andAnswer(answer);
+        expect(
+                rootElement.triggerEvent(
+                        EasyMock.eq(TapestryConstants.PASSIVATE_EVENT),
+                        (Object[]) EasyMock.isNull(),
+                        EasyMock.isA(ComponentEventHandler.class))).andAnswer(triggerEventAnswer);
 
         train_encodeRedirectURL(
                 response,
                 "/barney/" + PAGE_LOGICAL_NAME + ".html/foo/bar",
                 "*encoded*");
 
+        listener.createdPageLink(EasyMock.isA(Link.class));
+        getMocksControl().andAnswer(createdPageLinkAnswer);
+
         replay();
 
         LinkFactory factory = new LinkFactoryImpl(request, response, resolver);
+        factory.addListener(listener);
 
         Link link = factory.createPageLink(page);
 
         assertEquals(link.toRedirectURI(), "*encoded*");
 
+        // Make sure the link was passed to the LinkFactoryListener
+
+        assertSame(link, holder.get());
+
         verify();
     }
 
+    protected final LinkFactoryListener newLinkFactoryListener()
+    {
+        return newMock(LinkFactoryListener.class);
+    }
+
+    @SuppressWarnings("unchecked")
     private void run(String pageClassName, String logicalPageName, String nestedId,
             String contextPath, String expectedURI, Object... context)
     {
@@ -128,6 +158,21 @@
         ComponentClassResolver resolver = newComponentClassResolver();
         ComponentPageElement element = newComponentPageElement();
         Page page = newPage();
+        LinkFactoryListener listener = newLinkFactoryListener();
+
+        final Holder<Link> holder = new Holder<Link>();
+
+        IAnswer<Void> createActionLinkAnswer = new IAnswer<Void>()
+        {
+            public Void answer() throws Throwable
+            {
+                Link link = (Link) EasyMock.getCurrentArguments()[0];
+
+                holder.put(link);
+
+                return null;
+            }
+        };
 
         train_getContainingPage(element, page);
         train_getName(page, pageClassName);
@@ -135,15 +180,20 @@
         train_getContextPath(request, contextPath);
         train_getNestedId(element, nestedId);
 
+        listener.createdActionLink(EasyMock.isA(Link.class));
+        getMocksControl().andAnswer(createActionLinkAnswer);
+
         train_encodeURL(response, expectedURI, "*encoded*");
 
         replay();
 
         LinkFactory factory = new LinkFactoryImpl(request, response, resolver);
+        factory.addListener(listener);
 
         Link link = factory.createActionLink(element, "someaction", false, context);
 
         assertEquals(link.toURI(), "*encoded*");
+        assertSame(link, holder.get());
 
         verify();
     }