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 2005/04/19 04:25:48 UTC
cvs commit: jakarta-tapestry/framework/src/descriptor/META-INF tapestry.url.xml
hlship 2005/04/18 19:25:48
Modified: . status.xml
src/documentation/content/xdocs/UsersGuide friendly-urls.xml
examples/Workbench/src/context/WEB-INF web.xml
hivemodule.xml
framework/src/java/org/apache/tapestry/engine/encoders
DirectServiceEncoder.java
framework/src/descriptor/META-INF tapestry.url.xml
Added: framework/src/test/org/apache/tapestry/engine/encoders
TestDirectServiceEncoder.java
Log:
Add DirectServiceEncoder.
Revision Changes Path
1.88 +1 -0 jakarta-tapestry/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/status.xml,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -r1.87 -r1.88
--- status.xml 18 Apr 2005 17:22:26 -0000 1.87
+++ status.xml 19 Apr 2005 02:25:48 -0000 1.88
@@ -68,6 +68,7 @@
<action type="add" dev="HLS"> Enhance listener methods, allowing them to include the request cycle optionally, and also optionally accept listener parameters. </action>
<action type="update" dev="HLS"> Replace references to release 3.1 with release 4.0. </action>
<action type="update" dev="HLS"> Upgrade to Javassist 3.0. </action>
+ <action type="add" dev="HLS"> Add DirectServiceEncoder. </action>
</release>
<release version="3.0.3" date="Mar 26 2005">
<action type="fix" dev="PF" fixes-bug="TAPESTRY-278"> Fixes security flaw in asset service. </action>
1.1 jakarta-tapestry/framework/src/test/org/apache/tapestry/engine/encoders/TestDirectServiceEncoder.java
Index: TestDirectServiceEncoder.java
===================================================================
// Copyright 2005 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.tapestry.engine.encoders;
import org.apache.hivemind.test.HiveMindTestCase;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.ServiceEncoding;
import org.apache.tapestry.services.ServiceConstants;
import org.easymock.MockControl;
/**
* Tests for {@link org.apache.tapestry.engine.encoders.DirectServiceEncoder}.
*
* @author Howard M. Lewis Ship
* @since 4.0
*/
public class TestDirectServiceEncoder extends HiveMindTestCase
{
private ServiceEncoding newEncoding(String servletPath)
{
MockControl control = newControl(ServiceEncoding.class);
ServiceEncoding encoding = (ServiceEncoding) control.getMock();
encoding.getServletPath();
control.setReturnValue(servletPath);
return encoding;
}
private void train(MockControl control, ServiceEncoding encoding, String parameterName,
String parameterValue)
{
encoding.getParameterValue(parameterName);
control.setReturnValue(parameterValue);
}
public void testEncodeWrongService()
{
MockControl control = newControl(ServiceEncoding.class);
ServiceEncoding encoding = (ServiceEncoding) control.getMock();
train(control, encoding, ServiceConstants.SERVICE, "foo");
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.encode(encoding);
verifyControls();
}
public void testEncodePageInNamespace()
{
MockControl control = newControl(ServiceEncoding.class);
ServiceEncoding encoding = (ServiceEncoding) control.getMock();
train(control, encoding, ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
train(control, encoding, ServiceConstants.PAGE, "foo:Bar");
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.encode(encoding);
verifyControls();
}
public void testEncodeStateless()
{
MockControl control = newControl(ServiceEncoding.class);
ServiceEncoding encoding = (ServiceEncoding) control.getMock();
train(control, encoding, ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
train(control, encoding, ServiceConstants.PAGE, "admin/Menu");
train(control, encoding, ServiceConstants.SESSION, null);
train(control, encoding, ServiceConstants.COMPONENT, "border.link");
encoding.setServletPath("/admin/Menu,border.link.direct");
encoding.setParameterValue(ServiceConstants.SERVICE, null);
encoding.setParameterValue(ServiceConstants.PAGE, null);
encoding.setParameterValue(ServiceConstants.SESSION, null);
encoding.setParameterValue(ServiceConstants.COMPONENT, null);
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.setStatelessExtension("direct");
encoder.encode(encoding);
verifyControls();
}
public void testEncodeStateful()
{
MockControl control = newControl(ServiceEncoding.class);
ServiceEncoding encoding = (ServiceEncoding) control.getMock();
train(control, encoding, ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
train(control, encoding, ServiceConstants.PAGE, "admin/Menu");
train(control, encoding, ServiceConstants.SESSION, "T");
train(control, encoding, ServiceConstants.COMPONENT, "border.link");
encoding.setServletPath("/admin/Menu,border.link.sdirect");
encoding.setParameterValue(ServiceConstants.SERVICE, null);
encoding.setParameterValue(ServiceConstants.PAGE, null);
encoding.setParameterValue(ServiceConstants.SESSION, null);
encoding.setParameterValue(ServiceConstants.COMPONENT, null);
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.setStatefulExtension("sdirect");
encoder.encode(encoding);
verifyControls();
}
public void testDecodeWrongExtension()
{
ServiceEncoding encoding = newEncoding("/foo.svc");
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.setStatelessExtension("direct");
encoder.setStatefulExtension("sdirect");
encoder.decode(encoding);
verifyControls();
}
public void testDecodeStateless()
{
ServiceEncoding encoding = newEncoding("/admin/Menu,border.link.direct");
encoding.setParameterValue(ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
encoding.setParameterValue(ServiceConstants.PAGE, "admin/Menu");
encoding.setParameterValue(ServiceConstants.SESSION, null);
encoding.setParameterValue(ServiceConstants.COMPONENT, "border.link");
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.setStatelessExtension("direct");
encoder.setStatefulExtension("sdirect");
encoder.decode(encoding);
verifyControls();
}
public void testDecodeStateful()
{
ServiceEncoding encoding = newEncoding("/admin/Menu,border.link.sdirect");
encoding.setParameterValue(ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
encoding.setParameterValue(ServiceConstants.PAGE, "admin/Menu");
encoding.setParameterValue(ServiceConstants.SESSION, "T");
encoding.setParameterValue(ServiceConstants.COMPONENT, "border.link");
replayControls();
DirectServiceEncoder encoder = new DirectServiceEncoder();
encoder.setStatelessExtension("direct");
encoder.setStatefulExtension("sdirect");
encoder.decode(encoding);
verifyControls();
}
}
1.6 +51 -10 jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/friendly-urls.xml
Index: friendly-urls.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/friendly-urls.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- friendly-urls.xml 18 Apr 2005 17:09:03 -0000 1.5
+++ friendly-urls.xml 19 Apr 2005 02:25:48 -0000 1.6
@@ -61,7 +61,7 @@
</p>
<p>
- Friendly URLs are divided into two aspects:
+ Friendly URLs are divided into two concerns:
</p>
<ul>
@@ -72,7 +72,7 @@
<p>
For example, the ugly URL <code>/app?page=news/Thread&service=page</code> may be converted into
the friendly URL <code>/news/Threads.html</code>. In this case, the <code>page=news/Thread</code> query parameter
- becamethe <code>news/Thread</code> portion of the URL, and the <code>service=page</code> query parameter
+ became the <code>news/Thread</code> portion of the URL, and the <code>service=page</code> query parameter
became the <code>.html</code> extension to the URL.
</p>
@@ -118,7 +118,7 @@
</dt>
<dd>
- Stores service parameters passed in the URL (used by &DirectLink;).
+ Stores listener parameters passed in the URL (used by &DirectLink; and passed into &listener-method;s, the "sp" is a holdover from 3.0).
</dd>
</dl>
@@ -189,6 +189,46 @@
</section>
<section>
+ <title>direct-service-encoder</title>
+
+ <p>A specialized encoder used <em>exclusively</em>
+ with the direct service. Encodes the page name into the
+ servlet path, then a comma, then the nested id for the component. One of two extensions
+ is used, depending on whether the URL is stateful (an HttpSession existed when the link was rendered), or
+ stateless.</p>
+
+ <p>
+ A typical URL might be:
+ <code>/admin/Menu,border.link.direct</code>. This indicates a page name of <code>admin/Menu</code> and
+ a component id of <code>border.link</code>. By convention, the ".direct" extension is for stateless URLs.
+ </p>
+
+ <p>The hivemodule.xml contribution:</p>
+
+<source><![CDATA[
+<contribution configuration-id="tapestry.url.ServiceEncoders">
+ <direct-service-encoder id="direct" stateless-extension="direct" stateful-extension="sdirect"/>
+</contribution>
+]]></source>
+
+<p>
+ In addition, the <code>*.direct</code> and <code>*.sdirect</code> mappings must be added to web.xml:
+</p>
+
+<source><![CDATA[
+<servlet-mapping>
+ <servlet-name>myapp</servlet-name>
+ <url-pattern>*.direct</url-pattern>
+</servlet-mapping>
+
+<servlet-mapping>
+ <servlet-name>myapp</servlet-name>
+ <url-pattern>*.sdirect</url-pattern>
+</servlet-mapping> ]]></source>
+
+ </section>
+
+ <section>
<title>asset-encoder</title>
<p>
@@ -210,9 +250,9 @@
</p>
<source><![CDATA[
- <contribution configuration-id="tapestry.url.ServiceEncoders">
- <asset-encoder id="asset" path="/assets/"/>
- </contribution>]]></source>
+<contribution configuration-id="tapestry.url.ServiceEncoders">
+ <asset-encoder id="asset" path="/assets/"/>
+</contribution>]]></source>
<p>
This contribution will encode asset URLs using the given path. The provided path, <code>/assets/</code> comes first,
@@ -223,10 +263,11 @@
In addition you must add a mapping to web.xml:
</p>
-<source><![CDATA[ <servlet-mapping>
- <servlet-name>myapp</servlet-name>
- <url-pattern>/assets/*</url-pattern>
- </servlet-mapping>]]></source>
+<source><![CDATA[
+<servlet-mapping>
+ <servlet-name>myapp</servlet-name>
+ <url-pattern>/assets/*</url-pattern>
+</servlet-mapping>]]></source>
<p>
1.8 +10 -0 jakarta-tapestry/examples/Workbench/src/context/WEB-INF/web.xml
Index: web.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/examples/Workbench/src/context/WEB-INF/web.xml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- web.xml 12 Mar 2005 20:49:16 -0000 1.7
+++ web.xml 19 Apr 2005 02:25:48 -0000 1.8
@@ -48,11 +48,21 @@
<servlet-mapping>
<servlet-name>workbench</servlet-name>
+ <url-pattern>*.external</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>workbench</servlet-name>
<url-pattern>*.direct</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>workbench</servlet-name>
+ <url-pattern>*.sdirect</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>workbench</servlet-name>
<url-pattern>*.svc</url-pattern>
</servlet-mapping>
1.10 +2 -1 jakarta-tapestry/examples/Workbench/src/context/WEB-INF/hivemodule.xml
Index: hivemodule.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/examples/Workbench/src/context/WEB-INF/hivemodule.xml,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- hivemodule.xml 25 Mar 2005 20:36:59 -0000 1.9
+++ hivemodule.xml 19 Apr 2005 02:25:48 -0000 1.10
@@ -23,8 +23,9 @@
</contribution>
<contribution configuration-id="tapestry.url.ServiceEncoders">
- <page-service-encoder id="direct" extension="direct" service="direct"/>
+ <direct-service-encoder id="direct" stateless-extension="direct" stateful-extension="sdirect"/>
<page-service-encoder id="page" extension="page" service="page"/>
+ <page-service-encoder id="external" extension="external" service="external"/>
<asset-encoder id="asset" path="/assets/"/>
<extension-encoder id="ext" extension="svc" after="*"/>
</contribution>
1.2 +85 -2 jakarta-tapestry/framework/src/java/org/apache/tapestry/engine/encoders/DirectServiceEncoder.java
Index: DirectServiceEncoder.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/engine/encoders/DirectServiceEncoder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DirectServiceEncoder.java 18 Apr 2005 17:06:41 -0000 1.1
+++ DirectServiceEncoder.java 19 Apr 2005 02:25:48 -0000 1.2
@@ -1,22 +1,105 @@
+// Copyright 2005 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.tapestry.engine.encoders;
+import org.apache.tapestry.INamespace;
+import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.ServiceEncoder;
import org.apache.tapestry.engine.ServiceEncoding;
+import org.apache.tapestry.services.ServiceConstants;
-/**
+/**
+ * A specialized encoder for the {@link org.apache.tapestry.engine.DirectService direct service}
+ * that encodes the page name and component id path into the servlet path, and encodes the
+ * stateful flag by choosing one of two extensions.
*
* @author Howard M. Lewis Ship
* @since 4.0
*/
public class DirectServiceEncoder implements ServiceEncoder
{
+ private String _statelessExtension;
+
+ private String _statefulExtension;
public void encode(ServiceEncoding encoding)
{
+ String service = encoding.getParameterValue(ServiceConstants.SERVICE);
+ if (!service.equals(Tapestry.DIRECT_SERVICE))
+ return;
+
+ String pageName = encoding.getParameterValue(ServiceConstants.PAGE);
+
+ // Only handle pages in the application namespace (not from a library).
+
+ if (pageName.indexOf(INamespace.SEPARATOR) >= 0)
+ return;
+
+ String stateful = encoding.getParameterValue(ServiceConstants.SESSION);
+ String componentIdPath = encoding.getParameterValue(ServiceConstants.COMPONENT);
+
+ StringBuffer buffer = new StringBuffer("/");
+ buffer.append(pageName);
+
+ buffer.append(",");
+ buffer.append(componentIdPath);
+
+ buffer.append(".");
+ buffer.append(stateful != null ? _statefulExtension : _statelessExtension);
+
+ encoding.setServletPath(buffer.toString());
+
+ encoding.setParameterValue(ServiceConstants.SERVICE, null);
+ encoding.setParameterValue(ServiceConstants.PAGE, null);
+ encoding.setParameterValue(ServiceConstants.SESSION, null);
+ encoding.setParameterValue(ServiceConstants.COMPONENT, null);
}
public void decode(ServiceEncoding encoding)
{
+ String servletPath = encoding.getServletPath();
+
+ int dotx = servletPath.lastIndexOf('.');
+ if (dotx < 0)
+ return;
+
+ String extension = servletPath.substring(dotx + 1);
+
+ if (!(extension.equals(_statefulExtension) || extension.equals(_statelessExtension)))
+ return;
+
+ int commax = servletPath.lastIndexOf(',');
+
+ String pageName = servletPath.substring(1, commax);
+ String componentIdPath = servletPath.substring(commax + 1, dotx);
+
+ encoding.setParameterValue(ServiceConstants.SERVICE, Tapestry.DIRECT_SERVICE);
+ encoding.setParameterValue(ServiceConstants.PAGE, pageName);
+ encoding.setParameterValue(
+ ServiceConstants.SESSION,
+ extension.equals(_statefulExtension) ? "T" : null);
+ encoding.setParameterValue(ServiceConstants.COMPONENT, componentIdPath);
}
-}
+ public void setStatefulExtension(String statefulExtension)
+ {
+ _statefulExtension = statefulExtension;
+ }
+
+ public void setStatelessExtension(String statelessExtension)
+ {
+ _statelessExtension = statelessExtension;
+ }
+}
\ No newline at end of file
1.15 +35 -0 jakarta-tapestry/framework/src/descriptor/META-INF/tapestry.url.xml
Index: tapestry.url.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/descriptor/META-INF/tapestry.url.xml,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- tapestry.url.xml 18 Apr 2005 17:07:50 -0000 1.14
+++ tapestry.url.xml 19 Apr 2005 02:25:48 -0000 1.15
@@ -72,6 +72,41 @@
</conversion>
</element>
+ <element name="direct-service-encoder">
+
+ An encoder specialized for the direct service; it encodes the page name
+ and the component id into the servlet path, and uses one of two
+ extensions to indicate whether the link is stateful or stateless.
+
+ <attribute name="id" required="true" unique="true">
+ Unique id for this encoder, used when ordering encoder order.
+ </attribute>
+ <attribute name="before">
+ List of ids of encoders that must come before this encoder.
+ </attribute>
+ <attribute name="after">
+ List of ids of encoders that must follow this encoder.
+ </attribute>
+ <attribute name="stateless-extension" required="true">
+ The path extension to use for stateless links.
+ </attribute>
+ <attribute name="stateful-extension" required="true">
+ The path extension to use for stateful links.
+ </attribute>
+
+ <rules>
+ <create-object class="impl.ServiceEncoderContribution"/>
+ <read-attribute attribute="id" property="id"/>
+ <read-attribute attribute="before" property="before"/>
+ <read-attribute attribute="after" property="after"/>
+ <invoke-parent method="addElement"/>
+
+ <create-object class="org.apache.tapestry.engine.encoders.DirectServiceEncoder"/>
+ <read-attribute attribute="stateless-extension" property="statelessExtension"/>
+ <read-attribute attribute="stateful-extension" property="statefulExtension"/>
+ <invoke-parent method="setEncoder"/>
+ </rules>
+ </element>
<element name="page-service-encoder">
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org