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 2008/03/04 19:52:34 UTC
svn commit: r633583 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry/dom/ main/java/org/apache/tapestry/internal/
main/java/org/apache/tapestry/internal/services/ test/app3/
test/java/org/apache/tapestry/integration/ test...
Author: hlship
Date: Tue Mar 4 10:52:30 2008
New Revision: 633583
URL: http://svn.apache.org/viewvc?rev=633583&view=rev
Log:
TAPESTRY-2226: Requests for the root index page that include a page activation context fail with a 404 error
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Index.tml
- copied, changed from r633150, tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Start.tml
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/AdditionalIntegrationTests.java
- copied, changed from r633150, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/RootPathRedirectTest.java
Removed:
tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Start.tml
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/RootPathRedirectTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app3/pages/Index.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java Tue Mar 4 10:52:30 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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,6 +14,7 @@
package org.apache.tapestry.dom;
+import org.apache.tapestry.internal.TapestryInternalUtils;
import org.apache.tapestry.ioc.internal.util.CollectionFactory;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newLinkedList;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
@@ -417,7 +418,7 @@
Element search = this;
- for (String name : path.split("/"))
+ for (String name : TapestryInternalUtils.splitPath(path))
{
search = search.findChildWithElementName(name);
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java Tue Mar 4 10:52:30 2008
@@ -570,4 +570,12 @@
return left.equals(right);
}
+
+ /**
+ * Splits a path at each slash.
+ */
+ public static String[] splitPath(String path)
+ {
+ return SLASH_PATTERN.split(path);
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java Tue Mar 4 10:52:30 2008
@@ -91,10 +91,6 @@
private static final int EVENT_NAME = 9;
private static final int CONTEXT = 11;
- // Used to split a context into individual chunks.
-
- private final Pattern SLASH_PATTERN = Pattern.compile("/");
-
public boolean dispatch(Request request, Response response) throws IOException
{
Matcher matcher = PATH_PATTERN.matcher(request.getPath());
@@ -117,7 +113,7 @@
// (TAPESTRY-1605)
_requestEncodingInitializer.initializeRequestEncoding(activePageName);
-
+
EventContext activationContext = decodeContext(request.getParameter(InternalConstants.PAGE_CONTEXT_NAME));
// The event type is often omitted, and defaults to "action".
@@ -146,7 +142,7 @@
{
if (input == null) return _emptyContext;
- String[] values = SLASH_PATTERN.split(input);
+ String[] values = TapestryInternalUtils.splitPath(input);
for (int i = 0; i < values.length; i++)
{
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java Tue Mar 4 10:52:30 2008
@@ -44,41 +44,53 @@
public boolean dispatch(Request request, final Response response) throws IOException
{
- // Rememeber that the path starts with a leading slash that is not part of the logical page
- // name.
+
+ // The extended name may include a page activation context. The trick is
+ // to figure out where the logical page name stops and where the
+ // activation context begins. Further, strip out the leading slash.
String path = request.getPath();
- // TAPESTRY-1343: This can happen in Tomcat (but not in Jetty) for URL such as
- // http://.../context (with no trailing slash).
- if (path.equals("")) return false;
+ // TAPESTRY-1343: Sometimes path is the empty string (it should always be at least a slash,
+ // but Tomcat may return the empty string for a root context request).
+
+ String extendedName = path.length() == 0 ? path : path.substring(1);
- int nextslashx = path.length();
- String pageName;
+ // Ignore trailing slashes in the path.
+ while (extendedName.endsWith("/"))
+ extendedName = extendedName.substring(0, extendedName.length() - 1);
+
+ int slashx = extendedName.length();
boolean atEnd = true;
- while (true)
+ while (slashx > 0)
{
- // TAPESTRY-2150: Look for the longest match, for situations where
- // you have some overlap between a class name and a package name.
- pageName = path.substring(1, nextslashx);
+ String pageName = extendedName.substring(0, slashx);
+ String pageActivationContext = atEnd ? "" :
+ extendedName.substring(slashx + 1);
- if (!pageName.endsWith("/") && _componentClassResolver.isPageName(pageName)) break;
+ if (process(pageName, pageActivationContext)) return true;
- nextslashx = path.lastIndexOf('/', nextslashx - 1);
+ // Work backwards, splitting at the next slash.
+ slashx = extendedName.lastIndexOf('/', slashx - 1);
atEnd = false;
-
- if (nextslashx <= 1) return false;
}
+ // OK, maybe its all page activation context for the root Index page.
+
+ return process("", extendedName);
+ }
+
+ private boolean process(String pageName, String pageActivationContext) throws IOException
+ {
+ if (!_componentClassResolver.isPageName(pageName)) return false;
- String[] context = atEnd ? new String[0] : convertActivationContext(path
- .substring(nextslashx + 1));
+ String[] values = convertActivationContext(pageActivationContext);
EventContext activationContext
- = new URLEventContext(_contextValueEncoder, context);
+ = new URLEventContext(_contextValueEncoder, values);
PageRenderRequestParameters parameters = new PageRenderRequestParameters(pageName, activationContext);
@@ -92,14 +104,12 @@
* activation context) into an array of strings. LinkFactory and friends URL encode each value, so we URL decode the
* value (we assume that page names are "URL safe").
*
- * @param extraPath
- * @return
*/
private String[] convertActivationContext(String extraPath)
{
if (extraPath.length() == 0) return new String[0];
- String[] context = extraPath.split("/");
+ String[] context = TapestryInternalUtils.splitPath(extraPath);
for (int i = 0; i < context.length; i++)
{
Copied: tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Index.tml (from r633150, tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Start.tml)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Index.tml?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Index.tml&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Start.tml&r1=633150&r2=633583&rev=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Start.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app3/Index.tml Tue Mar 4 10:52:30 2008
@@ -1,12 +1,13 @@
<html>
<head>
- <title>Start</title>
+ <title>Index</title>
</head>
<body>
- <h1>Start page</h1>
+ <h1>Index</h1>
<p>
- The Start page should not be visible, because of the onActivate() event handler method.
+ Message:
+ <span id="message">${message}</span>
</p>
</body>
</html>
Copied: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/AdditionalIntegrationTests.java (from r633150, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/RootPathRedirectTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/AdditionalIntegrationTests.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/AdditionalIntegrationTests.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/RootPathRedirectTest.java&r1=633150&r2=633583&rev=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/RootPathRedirectTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/AdditionalIntegrationTests.java Tue Mar 4 10:52:30 2008
@@ -17,11 +17,14 @@
import org.apache.tapestry.test.AbstractIntegrationTestSuite;
import org.testng.annotations.Test;
+/**
+ * Additional integration tests that do not fit with the main group due to the need for special configuration.
+ */
@Test(timeOut = 50000, sequential = true, groups = { "integration" })
-public class RootPathRedirectTest extends AbstractIntegrationTestSuite
+public class AdditionalIntegrationTests extends AbstractIntegrationTestSuite
{
- public RootPathRedirectTest()
+ public AdditionalIntegrationTests()
{
super("src/test/app3");
}
@@ -48,4 +51,18 @@
assertText("//div[@class='t-beandisplay-value no']", "Nay");
assertText("//div[@class='t-beandisplay-value yes']", "Yea");
}
+
+ /**
+ * TAPESTRY-2226
+ */
+ @Test
+ public void activation_context_for_root_index_page()
+ {
+ open(BASE_URL + "it worked");
+
+ assertText("//h1", "Index");
+
+ assertText("message", "it worked");
+ }
+
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app3/pages/Index.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app3/pages/Index.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app3/pages/Index.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app3/pages/Index.java Tue Mar 4 10:52:30 2008
@@ -14,15 +14,31 @@
package org.apache.tapestry.integration.app3.pages;
+import org.apache.tapestry.annotations.GenerateAccessors;
import org.apache.tapestry.annotations.InjectPage;
+import org.apache.tapestry.annotations.Persist;
public class Index
{
@InjectPage
private Login _login;
+ @Persist
+ @GenerateAccessors
+ private String _message;
+
+ boolean onActivate(String message)
+ {
+ _message = message;
+
+ // Terminate the event before it gets to the no-args onActivate().
+
+ return true;
+ }
+
Object onActivate()
{
+
// Perform a redirect to the login page.
return _login;
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java?rev=633583&r1=633582&r2=633583&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java Tue Mar 4 10:52:30 2008
@@ -71,6 +71,8 @@
train_getPath(request, "");
+ train_isPageName(resolver, "", false);
+
replay();
Dispatcher d = new PageRenderDispatcher(resolver, handler, null);
@@ -79,6 +81,47 @@
verify();
}
+
+ /**
+ * TAPESTRY-2226
+ */
+ @Test
+ public void page_activation_context_for_root_index_page() throws Exception
+ {
+ ComponentClassResolver resolver = mockComponentClassResolver();
+ Request request = mockRequest();
+ Response response = mockResponse();
+ Page page = mockPage();
+ ComponentPageElement rootElement = mockComponentPageElement();
+ PageResponseRenderer renderer = mockPageResponseRenderer();
+ RequestPageCache cache = mockRequestPageCache();
+ ComponentEventResultProcessor processor = newComponentEventResultProcessor();
+
+ train_getPath(request, "/foo/bar");
+
+ train_isPageName(resolver, "foo/bar", false);
+ train_isPageName(resolver, "foo", false);
+ train_isPageName(resolver, "", true);
+
+ train_get(cache, "", page);
+
+ train_getRootElement(page, rootElement);
+
+ train_triggerContextEvent(rootElement, TapestryConstants.ACTIVATE_EVENT, new Object[] { "foo", "bar" }, false);
+
+ renderer.renderPageResponse(page);
+
+ replay();
+
+ PageRenderRequestHandler handler = new PageRenderRequestHandlerImpl(cache, processor, renderer);
+
+ Dispatcher d = new PageRenderDispatcher(resolver, handler, _contextValueEncoder);
+
+ assertTrue(d.dispatch(request, response));
+
+ verify();
+ }
+
@Test
public void no_extra_context_without_final_slash() throws Exception