Author: julien_viet
Date: 2010-11-04 07:22:09 -0400 (Thu, 04 Nov 2010)
New Revision: 4941
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/PathParamDescriptor.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/EncodingMode.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternParamDef.java
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURLRenderContext.java
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/gatein_router_1_0.xsd
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/ControllerContext.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/QualifiedName.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/DescriptorBuilder.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/RouteDescriptor.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternRoute.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RenderContext.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/SimpleRenderContext.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestBuildRoute.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestDescriptorBuilder.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestLegacyPortal.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortalConfiguration.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/router.xml
portal/branches/navcontroller/portlet/exoadmin/src/main/webapp/groovy/admintoolbar/webui/component/UIUserToolBarGroupPortlet.gtmpl
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/default-router.xml
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/proto-router-1.xml
portal/branches/navcontroller/web/portal/src/main/webapp/groovy/webui/core/UISitemapTree.gtmpl
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURL.java
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplication.java
Log:
improve encoding of char in request path and url path
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/gatein_router_1_0.xsd
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/gatein_router_1_0.xsd 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/gatein_router_1_0.xsd 2010-11-04
11:22:09 UTC (rev 4941)
@@ -39,6 +39,7 @@
<xs:complexType name="routeType">
<xs:sequence>
<xs:element name="param" type="paramType"
minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="path-param" type="pathParamType"
minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="request-param" type="requestParamType"
minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="route" type="routeType"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
@@ -50,6 +51,19 @@
<xs:attribute name="value" type="xs:string"
use="required"/>
</xs:complexType>
+ <xs:complexType name="pathParamType">
+ <xs:attribute name="name" type="xs:string"
use="required"/>
+ <xs:attribute name="pattern" type="xs:string"
use="optional"/>
+ <xs:attribute name="encoding" use="optional">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="default-form"/>
+ <xs:enumeration value="preserve-path"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+
<xs:complexType name="requestParamType">
<xs:attribute name="name" type="xs:string"
use="required"/>
<xs:attribute name="matchName" type="xs:string"
use="required"/>
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/ControllerContext.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/ControllerContext.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/ControllerContext.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -49,6 +49,9 @@
/** . */
private SimpleRenderContext renderContext;
+ /** . */
+ private final String contextName;
+
public ControllerContext(
WebAppController controller,
HttpServletRequest request,
@@ -60,6 +63,7 @@
this.response = response;
this.parameters = parameters;
this.renderContext = null;
+ this.contextName = request.getContextPath().substring(1);
}
public WebAppController getController()
@@ -84,9 +88,12 @@
public void renderURL(Map<QualifiedName, String> parameters, RenderContext
renderContext)
{
- renderContext.appendPath(request.getContextPath());
+ renderContext.appendPath('/', false);
//
+ renderContext.appendPath(contextName, true);
+
+ //
controller.router.render(parameters, renderContext);
}
@@ -102,9 +109,12 @@
}
//
- renderContext.appendPath(request.getContextPath());
+ renderContext.appendPath('/', false);
//
+ renderContext.appendPath(contextName, true);
+
+ //
controller.router.render(parameters, renderContext);
//
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/QualifiedName.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/QualifiedName.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/QualifiedName.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -33,13 +33,10 @@
{
if (qname.length() > 0)
{
- if (qname.charAt(0) == '{')
+ int index = qname.indexOf(':');
+ if (index > -1)
{
- int index = qname.indexOf('}', 1);
- if (index != -1)
- {
- return new QualifiedName(qname.substring(1, index), qname.substring(index
+ 1));
- }
+ return new QualifiedName(qname.substring(0, index), qname.substring(index +
1));
}
}
return new QualifiedName(qname);
@@ -101,7 +98,7 @@
}
else
{
- return "{" + qualifier + "}" + name;
+ return qualifier + ":" + name;
}
}
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/DescriptorBuilder.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/DescriptorBuilder.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/DescriptorBuilder.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -20,6 +20,7 @@
package org.exoplatform.web.controller.metadata;
import org.exoplatform.web.controller.QualifiedName;
+import org.exoplatform.web.controller.router.EncodingMode;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
@@ -43,10 +44,11 @@
/** . */
private static final QName requestParamQN = new
QName("http://www.gatein.org/xml/ns/gatein_router_1_0",
"request-param");
+ /** . */
+ private static final QName pathParamQN = new
QName("http://www.gatein.org/xml/ns/gatein_router_1_0",
"path-param");
+
public RouterDescriptor build(XMLStreamReader reader) throws Exception
{
- System.out.println("reader = " + reader);
- System.out.println("reader = " + reader.getClass().getName());
RouterDescriptor routerDesc = new RouterDescriptor();
//
@@ -103,6 +105,14 @@
String optional = reader.getAttributeValue(null, "required");
routeDesc.addRequestParam(QualifiedName.parse(name), matchName,
matchValue, "true".equals(optional));
}
+ else if (pathParamQN.equals(reader.getName()))
+ {
+ String name = reader.getAttributeValue(null, "name");
+ String pattern = reader.getAttributeValue(null, "pattern");
+ String encoded = reader.getAttributeValue(null, "encoding");
+ EncodingMode encodingMode = "preserve-path".equals(encoded) ?
EncodingMode.PRESERVE_PATH : EncodingMode.DEFAULT_FORM;
+ routeDesc.addPathParam(QualifiedName.parse(name), pattern, encodingMode);
+ }
else if (routeQN.equals(reader.getName()))
{
build(reader, routeDesc.getChildren());
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/PathParamDescriptor.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/PathParamDescriptor.java
(rev 0)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/PathParamDescriptor.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.metadata;
+
+import org.exoplatform.web.controller.QualifiedName;
+import org.exoplatform.web.controller.router.EncodingMode;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public class PathParamDescriptor
+{
+
+ /** . */
+ private final QualifiedName name;
+
+ /** . */
+ private final String pattern;
+
+ /** . */
+ private final EncodingMode encodingMode;
+
+ public PathParamDescriptor(QualifiedName name, String pattern, EncodingMode
encodingMode)
+ {
+ if (name == null)
+ {
+ throw new NullPointerException("No null name accepted");
+ }
+ if (pattern == null)
+ {
+ throw new NullPointerException("No null pattern accepted");
+ }
+
+ //
+ this.name = name;
+ this.pattern = pattern;
+ this.encodingMode = encodingMode;
+ }
+
+ public QualifiedName getName()
+ {
+ return name;
+ }
+
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ public EncodingMode getEncodingMode()
+ {
+ return encodingMode;
+ }
+}
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/RouteDescriptor.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/RouteDescriptor.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/metadata/RouteDescriptor.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -20,6 +20,7 @@
package org.exoplatform.web.controller.metadata;
import org.exoplatform.web.controller.QualifiedName;
+import org.exoplatform.web.controller.router.EncodingMode;
import java.util.ArrayList;
import java.util.HashMap;
@@ -42,6 +43,9 @@
private final Map<QualifiedName, String> params;
/** . */
+ private final Map<QualifiedName, PathParamDescriptor> pathParams;
+
+ /** . */
private final Map<String, RequestParamDescriptor> requestParams;
/** . */
@@ -51,6 +55,7 @@
{
this.path = path;
this.params = new HashMap<QualifiedName, String>();
+ this.pathParams = new HashMap<QualifiedName, PathParamDescriptor>();
this.requestParams = new HashMap<String, RequestParamDescriptor>();
this.children = new ArrayList<RouteDescriptor>();
}
@@ -87,11 +92,27 @@
return this;
}
+ public RouteDescriptor addPathParam(QualifiedName name, String pattern, EncodingMode
encodingMode)
+ {
+ return addRequestParam(new PathParamDescriptor(name, pattern, encodingMode));
+ }
+
+ public RouteDescriptor addRequestParam(PathParamDescriptor requestParam)
+ {
+ pathParams.put(requestParam.getName(), requestParam);
+ return this;
+ }
+
public Map<String, RequestParamDescriptor> getRequestParams()
{
return requestParams;
}
+ public Map<QualifiedName, PathParamDescriptor> getPathParams()
+ {
+ return pathParams;
+ }
+
public RouteDescriptor addRoute(RouteDescriptor child)
{
children.add(child);
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/EncodingMode.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/EncodingMode.java
(rev 0)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/EncodingMode.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.router;
+
+/**
+ * Specifies how a string value should be encoded in an URL.
+ *
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public enum EncodingMode
+{
+
+ /**
+ * DEFAULT_FORM encodes the whole string with the
<code>x-www-form-urlencoded</code> also known as
+ * <i>default form</i>. For instance the string /a/b is encoded to
%2Fa%2Fb.
+ */
+ DEFAULT_FORM,
+
+ /**
+ * PRESERVE_PATH encodes the whole string like the {@link #DEFAULT_FORM} but preserve
the path separators. For
+ * instance the string /a b is enocded to /a+b
+ */
+ PRESERVE_PATH
+
+}
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternParamDef.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternParamDef.java
(rev 0)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternParamDef.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.router;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+class PatternParamDef
+{
+
+ /** . */
+ final EncodingMode encodingMode;
+
+ /** . */
+ final Pattern pattern;
+
+ PatternParamDef(EncodingMode encodingMode, Pattern pattern)
+ {
+ this.encodingMode = encodingMode;
+ this.pattern = pattern;
+ }
+}
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternRoute.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternRoute.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/PatternRoute.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -38,7 +38,7 @@
final List<QualifiedName> parameterNames;
/** . */
- final List<Pattern> parameterPatterns;
+ final List<PatternParamDef> parameterPatterns;
/** . */
final List<String> chunks;
@@ -46,7 +46,7 @@
PatternRoute(
Pattern pattern,
List<QualifiedName> parameterNames,
- List<Pattern> parameterPatterns,
+ List<PatternParamDef> parameterPatterns,
List<String> chunks)
{
if (chunks.size() != parameterNames.size() + 1)
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RenderContext.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RenderContext.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RenderContext.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -34,14 +34,14 @@
*
* @param c the char to append
*/
- void appendPath(char c);
+ void appendPath(char c, boolean escape);
/**
* Append a string to the path.
*
* @param s the string to append.
*/
- void appendPath(String s);
+ void appendPath(String s, boolean escape);
/**
* Append a query parameter to the parameter set. Note that the query parameters are
ordered
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -20,6 +20,7 @@
package org.exoplatform.web.controller.router;
import org.exoplatform.web.controller.QualifiedName;
+import org.exoplatform.web.controller.metadata.PathParamDescriptor;
import org.exoplatform.web.controller.metadata.RequestParamDescriptor;
import org.exoplatform.web.controller.metadata.RouteDescriptor;
@@ -42,6 +43,9 @@
class Route
{
+ /** Julien : make that configurable. */
+ private static final char slashEscape = '~';
+
/** . */
private Route parent;
@@ -107,28 +111,48 @@
if (this instanceof SegmentRoute)
{
SegmentRoute sr = (SegmentRoute)this;
- renderContext.appendPath('/');
- renderContext.appendPath(sr.name);
+ renderContext.appendPath('/', false);
+ renderContext.appendPath(sr.name, true);
}
else if (this instanceof PatternRoute)
{
PatternRoute pr = (PatternRoute)this;
- renderContext.appendPath('/');
+ renderContext.appendPath('/', false);
int i = 0;
while (i < pr.parameterNames.size())
{
- renderContext.appendPath(pr.chunks.get(i));
+ renderContext.appendPath(pr.chunks.get(i), true);
String value = blah.get(pr.parameterNames.get(i));
- renderContext.appendPath(value);
+ PatternParamDef def = pr.parameterPatterns.get(i);
+
+ //
+ int from = 0;
+ while (true)
+ {
+ int to = value.indexOf('/', from);
+ if (to == -1)
+ {
+ break;
+ }
+ else
+ {
+ renderContext.appendPath(value.substring(from, to), true);
+ renderContext.appendPath(def.encodingMode == EncodingMode.PRESERVE_PATH
? '/' : slashEscape, false);
+ from = to +1;
+ }
+ }
+ renderContext.appendPath(value.substring(from), false);
+
+ //
i++;
}
- renderContext.appendPath(pr.chunks.get(i));
+ renderContext.appendPath(pr.chunks.get(i), false);
}
else
{
if (!hasChildren)
{
- renderContext.appendPath("/");
+ renderContext.appendPath('/', false);
}
}
}
@@ -182,9 +206,31 @@
for (int i = 0;i < prt.parameterNames.size();i++)
{
QualifiedName qd = prt.parameterNames.get(i);
+ PatternParamDef ppd = prt.parameterPatterns.get(i);
String s = blah.get(qd);
- if (s != null && prt.parameterPatterns.get(i).matcher(s).matches())
+ boolean matched = false;
+ if (s != null)
{
+ switch (ppd.encodingMode)
+ {
+ case DEFAULT_FORM:
+
+ // JULIEN
+ // TEMPORARY WORD AROUND
+ // FIX ME
+ s = s.replace('/', '~');
+
+ matched = ppd.pattern.matcher(s).matches();
+ break;
+ case PRESERVE_PATH:
+ matched = ppd.pattern.matcher(s).matches();
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+ if (matched)
+ {
abc.remove(qd);
}
else
@@ -226,6 +272,7 @@
}
/**
+ *
* @param path the path
* @param requestParams the query parameters
* @return null or the parameters when it matches
@@ -344,9 +391,15 @@
{
// Append parameters
int group = 1;
- for (QualifiedName parameterName : route.parameterNames)
+ for (int i = 0;i < route.parameterNames.size();i++)
{
- response.put(parameterName, matcher.group(group++));
+ QualifiedName parameterName = route.parameterNames.get(i);
+ String value = matcher.group(group++);
+ if (route.parameterPatterns.get(i).encodingMode ==
EncodingMode.DEFAULT_FORM)
+ {
+ value = value.replace(slashEscape, '/');
+ }
+ response.put(parameterName, value);
}
//
@@ -387,9 +440,6 @@
return ret;
}
- /** . */
- private static final Pattern PARAMETER_REGEX =
Pattern.compile("^(?:\\{([^\\}]*)\\})?(.*)$");
-
final <R extends Route> R add(R route)
{
if (route.parent != null)
@@ -454,7 +504,7 @@
final Route append(RouteDescriptor descriptor)
{
- Route route = append(descriptor.getPath());
+ Route route = append(descriptor.getPathParams(), descriptor.getPath());
//
route.terminal = true;
@@ -476,10 +526,11 @@
}
final Route append(
+ Map<QualifiedName, PathParamDescriptor> pathParamDescriptors,
String path,
Map<QualifiedName, String> parameters)
{
- Route route = append(path);
+ Route route = append(pathParamDescriptors, path);
route.terminal = true;
route.routeParameters.putAll(parameters);
return route;
@@ -488,10 +539,11 @@
/**
* Append a path, creates the necessary routes and returns the last route added.
*
+ * @param pathParamDescriptors the path param descriptors
* @param path the path to append
* @return the last route added
*/
- private Route append(String path)
+ private Route append(Map<QualifiedName, PathParamDescriptor>
pathParamDescriptors, String path)
{
int pos = path.length();
int level = 0;
@@ -548,48 +600,33 @@
PatternBuilder builder = new PatternBuilder();
builder.expr("^");
List<String> chunks = new ArrayList<String>();
- List<Pattern> parameterPatterns = new ArrayList<Pattern>();
+ List<PatternParamDef> parameterPatterns = new
ArrayList<PatternParamDef>();
int previous = 0;
for (int i = 0;i < start.size();i++)
{
builder.litteral(path, previous, start.get(i));
chunks.add(path.substring(previous, start.get(i)));
- String parameterDef = path.substring(start.get(i) + 1, end.get(i));
- int colon = parameterDef.indexOf(':');
- String regex;
- String parameterName;
- if (colon == -1)
- {
- regex = "[^/]+";
- parameterName = parameterDef;
- }
- else
- {
- regex = parameterDef.substring(colon + 1);
- parameterName = parameterDef.substring(0, colon);
- }
+ String parameterName = path.substring(start.get(i) + 1, end.get(i));
//
- QualifiedName parameterQName;
- Matcher parameterMatcher = PARAMETER_REGEX.matcher(parameterName);
- if (parameterMatcher.matches())
+ QualifiedName parameterQName = QualifiedName.parse(parameterName);
+
+ // Now get path param metadata
+ PathParamDescriptor parameterDescriptor =
pathParamDescriptors.get(parameterQName);
+ String regex = "[^/]+";
+ EncodingMode encodingMode = EncodingMode.DEFAULT_FORM;
+ if (parameterDescriptor != null)
{
- String qualifier = parameterMatcher.group(1);
- String name = parameterMatcher.group(2);
- parameterQName = new QualifiedName(qualifier == null ? "" :
qualifier, name);
+ regex = parameterDescriptor.getPattern();
+ encodingMode = parameterDescriptor.getEncodingMode();
}
- else
- {
- throw new AssertionError();
- }
-
//
builder.expr("(");
builder.expr(regex);
builder.expr(")");
parameterNames.add(parameterQName);
- parameterPatterns.add(Pattern.compile("^" + regex +
"$"));
+ parameterPatterns.add(new PatternParamDef(encodingMode,
Pattern.compile("^" + regex + "$")));
previous = end.get(i) + 1;
}
builder.litteral(path, previous, pos);
@@ -614,7 +651,7 @@
//
if (pos < path.length())
{
- return next.append(path.substring(pos + 1));
+ return next.append(pathParamDescriptors, path.substring(pos + 1));
}
else
{
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/SimpleRenderContext.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/SimpleRenderContext.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/SimpleRenderContext.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -19,6 +19,8 @@
package org.exoplatform.web.controller.router;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -72,24 +74,34 @@
}
}
- public void appendPath(char c)
+ public void appendPath(char c, boolean escape)
{
- if (sb == null)
- {
- sb = new StringBuilder();
- }
- sb.append(c);
+ appendPath(String.valueOf(c), escape);
}
- public void appendPath(String s)
+ public void appendPath(String s, boolean escape)
{
+ //To change body of implemented methods use File | Settings | File Templates.
if (sb == null)
{
sb = new StringBuilder();
}
- sb.append(s);
+ if (escape)
+ {
+ try
+ {
+ sb.append(URLEncoder.encode(s, "UTF-8"));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new AssertionError(e);
+ }
+ }
+ else
+ {
+ sb.append(s);
+ }
}
-
public void appendQueryParameter(String parameterName, String paramaterValue)
{
if (queryParams == EMPTY)
@@ -98,5 +110,4 @@
}
queryParams.put(parameterName, paramaterValue);
}
-
}
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestBuildRoute.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestBuildRoute.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestBuildRoute.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -76,7 +76,8 @@
assertEquals("^([^/]+)", patternRoute.pattern.toString());
assertEquals(Collections.singletonList(new QualifiedName("a")),
patternRoute.parameterNames);
assertEquals(1, patternRoute.parameterPatterns.size());
- assertEquals("^[^/]+$",
patternRoute.parameterPatterns.get(0).toString());
+ assertEquals("^[^/]+$",
patternRoute.parameterPatterns.get(0).pattern.toString());
+ assertEquals(EncodingMode.DEFAULT_FORM,
patternRoute.parameterPatterns.get(0).encodingMode);
assertEquals(2, patternRoute.chunks.size());
assertEquals("", patternRoute.chunks.get(0));
assertEquals("", patternRoute.chunks.get(1));
@@ -85,7 +86,7 @@
public void testQualifiedParameterSegment()
{
- String[] paths = {"/{{q}a}","{{q}a}"};
+ String[] paths = {"/{q:a}","{q:a}"};
for (String path : paths)
{
RouterDescriptor routerMD = new RouterDescriptor();
@@ -99,7 +100,8 @@
assertEquals("^([^/]+)", patternRoute.pattern.toString());
assertEquals(Collections.singletonList(new QualifiedName("q",
"a")), patternRoute.parameterNames);
assertEquals(1, patternRoute.parameterPatterns.size());
- assertEquals("^[^/]+$",
patternRoute.parameterPatterns.get(0).toString());
+ assertEquals("^[^/]+$",
patternRoute.parameterPatterns.get(0).pattern.toString());
+ assertEquals(EncodingMode.DEFAULT_FORM,
patternRoute.parameterPatterns.get(0).encodingMode);
assertEquals(2, patternRoute.chunks.size());
assertEquals("", patternRoute.chunks.get(0));
assertEquals("", patternRoute.chunks.get(1));
@@ -108,11 +110,11 @@
public void testPatternSegment()
{
- String[] paths = {"/{a:.*}","{a:.*}"};
+ String[] paths = {"/{a}","{a}"};
for (String path : paths)
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor(path));
+ routerMD.addRoute(new
RouteDescriptor(path).addPathParam(QualifiedName.parse("a"), ".*",
EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
@@ -122,7 +124,8 @@
assertEquals("^(.*)", patternRoute.pattern.toString());
assertEquals(Collections.singletonList(new QualifiedName("a")),
patternRoute.parameterNames);
assertEquals(1, patternRoute.parameterPatterns.size());
- assertEquals("^.*$",
patternRoute.parameterPatterns.get(0).toString());
+ assertEquals("^.*$",
patternRoute.parameterPatterns.get(0).pattern.toString());
+ assertEquals(EncodingMode.DEFAULT_FORM,
patternRoute.parameterPatterns.get(0).encodingMode);
assertEquals(2, patternRoute.chunks.size());
assertEquals("", patternRoute.chunks.get(0));
assertEquals("", patternRoute.chunks.get(1));
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestDescriptorBuilder.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestDescriptorBuilder.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestDescriptorBuilder.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -53,14 +53,22 @@
//
assertTrue(i.hasNext());
RouteDescriptor route1 = i.next();
- assertEquals("/public/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}",
route1.getPath());
+ assertEquals("/public/{gtn:sitetype}/{gtn:sitename}{gtn:path}",
route1.getPath());
assertEquals(Collections.singletonMap(WebAppController.HANDLER_PARAM,
"portal"), route1.getParams());
+ assertEquals(Collections.singleton(QualifiedName.parse("gtn:path")),
route1.getPathParams().keySet());
+ assertEquals(QualifiedName.parse("gtn:path"),
route1.getPathParams().get(QualifiedName.parse("gtn:path")).getName());
+ assertEquals(".*",
route1.getPathParams().get(QualifiedName.parse("gtn:path")).getPattern());
+ assertEquals(EncodingMode.DEFAULT_FORM,
route1.getPathParams().get(QualifiedName.parse("gtn:path")).getEncodingMode());
//
assertTrue(i.hasNext());
RouteDescriptor route2 = i.next();
- assertEquals("/private/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}",
route2.getPath());
+ assertEquals("/private/{gtn:sitetype}/{gtn:sitename}{gtn:path}",
route2.getPath());
assertEquals(Collections.singletonMap(WebAppController.HANDLER_PARAM,
"portal"), route2.getParams());
+ assertEquals(Collections.singleton(QualifiedName.parse("gtn:path")),
route2.getPathParams().keySet());
+ assertEquals(QualifiedName.parse("gtn:path"),
route2.getPathParams().get(QualifiedName.parse("gtn:path")).getName());
+ assertEquals(".*",
route2.getPathParams().get(QualifiedName.parse("gtn:path")).getPattern());
+ assertEquals(EncodingMode.PRESERVE_PATH,
route2.getPathParams().get(QualifiedName.parse("gtn:path")).getEncodingMode());
//
assertTrue(i.hasNext());
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestLegacyPortal.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestLegacyPortal.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestLegacyPortal.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -44,14 +44,14 @@
RouterDescriptor routerMD = new RouterDescriptor();
RouteDescriptor portal = new RouteDescriptor("/").
- addParam(QualifiedName.parse("{gtn}handler"), "portal").
- addRequestParam(QualifiedName.parse("{gtn}componentid"),
"portal:componentId", null, false).
- addRequestParam(QualifiedName.parse("{gtn}action"),
"portal:action", null, false).
- addRequestParam(QualifiedName.parse("{gtn}objectid"),
"portal:objectId", null, false).
- addRoute(new
RouteDescriptor("/public/{{gtn}sitename}{{gtn}path:.*}").
- addParam(QualifiedName.parse("{gtn}access"), "public")).
- addRoute(new
RouteDescriptor("/private/{{gtn}sitename}{{gtn}path:.*}").
- addParam(QualifiedName.parse("{gtn}access"),
"private"));
+ addParam(QualifiedName.parse("gtn:handler"), "portal").
+ addRequestParam(QualifiedName.parse("gtn:componentid"),
"portal:componentId", null, false).
+ addRequestParam(QualifiedName.parse("gtn:action"),
"portal:action", null, false).
+ addRequestParam(QualifiedName.parse("gtn:objectid"),
"portal:objectId", null, false).
+ addRoute(new RouteDescriptor("/public/{gtn:sitename}{gtn:path}").
+ addParam(QualifiedName.parse("gtn:access"),
"public")).addPathParam(QualifiedName.parse("gtn:path"),
".*", EncodingMode.PRESERVE_PATH).
+ addRoute(new
RouteDescriptor("/private/{gtn:sitename}{gtn:path}").addPathParam(QualifiedName.parse("gtn:path"),
".*", EncodingMode.PRESERVE_PATH).
+ addParam(QualifiedName.parse("gtn:access"), "private"));
//
routerMD.addRoute(portal);
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -42,14 +42,8 @@
//
assertNull(router.route(""));
-
- //
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/"));
-
- //
assertNull(router.route("/a"));
-
- //
assertNull(router.route("a"));
}
@@ -61,29 +55,13 @@
//
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a"));
-
- //
assertNull(router.route("a"));
-
- //
assertNull(router.route("a/"));
-
- //
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a/"));
-
- //
assertNull(router.route(""));
-
- //
assertNull(router.route("/"));
-
- //
assertNull(router.route("/b"));
-
- //
assertNull(router.route("b"));
-
- //
assertNull(router.route("/a/b"));
}
@@ -95,29 +73,13 @@
//
assertNull(router.route("a/b"));
-
- //
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a/b"));
-
- //
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a/b/"));
-
- //
assertNull(router.route("a/b/"));
-
- //
assertNull(router.route(""));
-
- //
assertNull(router.route("/"));
-
- //
assertNull(router.route("/b"));
-
- //
assertNull(router.route("b"));
-
- //
assertNull(router.route("/a/b/c"));
}
@@ -126,7 +88,9 @@
RouterDescriptor routerMD = new RouterDescriptor();
routerMD.addRoute(new RouteDescriptor("/{p}"));
Router router = new Router(routerMD);
- assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route(("/a")));
+
+ //
+ assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route("/a"));
}
public void testParameterPropagationToDescendants() throws Exception
@@ -135,44 +99,44 @@
routerMD.addRoute(new RouteDescriptor("/").addParam("p",
"a"));
routerMD.addRoute(new RouteDescriptor("/a"));
Router router = new Router(routerMD);
- assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route(("/a")));
+
+ //
+ assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route("/a"));
}
public void testWildcardPattern() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{p:.*}"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
".*", EncodingMode.PRESERVE_PATH));
Router router = new Router(routerMD);
//
assertEquals(Collections.singletonMap(new QualifiedName("p"),
""), router.route("/"));
-
- //
assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route("/a"));
+ assertNull(router.route("a"));
+ assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a/b"), router.route("/a/b"));
+ }
- //
- assertNull(router.route(("a")));
+ public void testDefaultForm() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
"[^/]+", EncodingMode.DEFAULT_FORM));
+ Router router = new Router(routerMD);
//
- assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a/b"), router.route("/a/b"));
+ assertEquals(Collections.singletonMap(new QualifiedName("p"),
"/"), router.route("/~"));
}
public void testSimplePattern() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{p:a}"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
"a", EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route("/a"));
-
- //
assertNull(router.route("a"));
-
- //
assertNull(router.route("/ab"));
-
- //
assertNull(router.route("ab"));
}
@@ -180,19 +144,13 @@
{
RouterDescriptor routerMD = new RouterDescriptor();
routerMD.addRoute(new RouteDescriptor("/a"));
- routerMD.addRoute(new RouteDescriptor("/{p:a}/b"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}/b").addPathParam(QualifiedName.parse("p"),
"a", EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
- assertNull(router.route(("a")));
-
- //
+ assertNull(router.route("a"));
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a"));
-
- //
assertEquals(Collections.<QualifiedName, String>emptyMap(),
router.route("/a/"));
-
- //
assertEquals(Collections.singletonMap(new QualifiedName("p"),
"a"), router.route("/a/b"));
}
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortalConfiguration.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortalConfiguration.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortalConfiguration.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -43,24 +43,28 @@
RouterDescriptor routerMD = new RouterDescriptor();
//
- RouteDescriptor portalRouteMD = new
RouteDescriptor("/private/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}");
+ RouteDescriptor portalRouteMD = new
RouteDescriptor("/private/{gtn:sitetype}/{gtn:sitename}{gtn:path}");
portalRouteMD.addParam(new QualifiedName("gtn", "controller"),
"site");
portalRouteMD.addRequestParam(new QualifiedName("gtn",
"componentid"), "portal:componentId", null, false);
+ portalRouteMD.addPathParam(new QualifiedName("gtn", "path"),
".*", EncodingMode.PRESERVE_PATH);
routerMD.addRoute(portalRouteMD);
//
- RouteDescriptor portalRouteMD2 = new
RouteDescriptor("/private/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}");
+ RouteDescriptor portalRouteMD2 = new
RouteDescriptor("/private/{gtn:sitetype}/{gtn:sitename}{gtn:path}");
portalRouteMD2.addParam(new QualifiedName("gtn", "controller"),
"site");
+ portalRouteMD2.addPathParam(new QualifiedName("gtn", "path"),
".*", EncodingMode.PRESERVE_PATH);
routerMD.addRoute(portalRouteMD2);
//
- RouteDescriptor groupRouteMD = new
RouteDescriptor("/groups/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}");
- portalRouteMD.addParam(new QualifiedName("gtn", "controller"),
"site");
+ RouteDescriptor groupRouteMD = new
RouteDescriptor("/groups/{gtn:sitetype}/{gtn:sitename}{gtn:path}");
+ groupRouteMD.addParam(new QualifiedName("gtn", "controller"),
"site");
+ groupRouteMD.addPathParam(new QualifiedName("gtn", "path"),
".*", EncodingMode.PRESERVE_PATH);
routerMD.addRoute(groupRouteMD);
//
- RouteDescriptor userRouteMD = new
RouteDescriptor("/users/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}");
- portalRouteMD.addParam(new QualifiedName("gtn", "controller"),
"site");
+ RouteDescriptor userRouteMD = new
RouteDescriptor("/users/{gtn:sitetype}/{gtn:sitename}{gtn:path}");
+ userRouteMD.addParam(new QualifiedName("gtn", "controller"),
"site");
+ userRouteMD.addPathParam(new QualifiedName("gtn", "path"),
".*", EncodingMode.PRESERVE_PATH);
routerMD.addRoute(userRouteMD);
//
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -62,7 +62,7 @@
assertEquals("/a/b", router.render(Collections.<QualifiedName,
String>emptyMap()));
}
- public void testParameter() throws Exception
+ public void testPathParam() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
routerMD.addRoute(new RouteDescriptor("/{p}"));
@@ -73,40 +73,74 @@
assertNull(router.render(Collections.<QualifiedName, String>emptyMap()));
}
- public void testWildcardPattern() throws Exception
+ public void testSimplePatternPathParam() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{p:.*}"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
"a", EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
- assertEquals("/", router.render(Collections.singletonMap(new
QualifiedName("p"), "")));
+ assertEquals("/a", router.render(Collections.singletonMap(new
QualifiedName("p"), "a")));
+ assertNull(router.render(Collections.singletonMap(new QualifiedName("p"),
"ab")));
+ }
+ public void testWildcardPathParam() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
".*", EncodingMode.PRESERVE_PATH));
+ Router router = new Router(routerMD);
+
//
+ assertEquals("/", router.render(Collections.singletonMap(new
QualifiedName("p"), "")));
assertEquals("/a", router.render(Collections.singletonMap(new
QualifiedName("p"), "a")));
+ assertEquals("/a/b", router.render(Collections.singletonMap(new
QualifiedName("p"), "a/b")));
+ }
+ public void testFoo() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
"[^/]*", EncodingMode.PRESERVE_PATH));
+ Router router = new Router(routerMD);
+
//
- assertEquals("/a/b", router.render(Collections.singletonMap(new
QualifiedName("p"), "a/b")));
+ assertEquals(null, router.render(Collections.singletonMap(new
QualifiedName("p"), "/")));
}
- public void testSimplePattern() throws Exception
+ public void testBar() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{p:a}"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
"[^/]*", EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
- assertEquals("/a", router.render(Collections.singletonMap(new
QualifiedName("p"), "a")));
+ assertEquals("/~", router.render(Collections.singletonMap(new
QualifiedName("p"), "/")));
+ }
+ public void testWildcardParamPathPreservePathEncoding() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
".*", EncodingMode.PRESERVE_PATH));
+ Router router = new Router(routerMD);
+
//
- assertNull(router.render(Collections.singletonMap(new QualifiedName("p"),
"ab")));
+ assertEquals("//", router.render(Collections.singletonMap(new
QualifiedName("p"), "/")));
}
+ public void testWildcardParamPathDefaultFormEncoded() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new
RouteDescriptor("/{p}").addPathParam(QualifiedName.parse("p"),
".*", EncodingMode.DEFAULT_FORM));
+ Router router = new Router(routerMD);
+
+ //
+ assertEquals("/~", router.render(Collections.singletonMap(new
QualifiedName("p"), "/")));
+ }
+
public void testPrecedence() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
routerMD.addRoute(new RouteDescriptor("/a"));
- routerMD.addRoute(new RouteDescriptor("/{p:a}/b"));
+ routerMD.addRoute(new
RouteDescriptor("/{p}/b").addPathParam(QualifiedName.parse("p"),
"a", EncodingMode.DEFAULT_FORM));
Router router = new Router(routerMD);
//
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/router.xml
===================================================================
---
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/router.xml 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/router.xml 2010-11-04
11:22:09 UTC (rev 4941)
@@ -3,20 +3,22 @@
xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_router_1_0
http://www.gatein.org/xml/ns/gatein_router_1_0"
xmlns="http://www.gatein.org/xml/ns/gatein_router_1_0">
- <route path="/public/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}">
- <param name="{gtn}handler" value="portal"/>
+ <route path="/public/{gtn:sitetype}/{gtn:sitename}{gtn:path}">
+ <param name="gtn:handler" value="portal"/>
+ <path-param name="gtn:path" pattern=".*"/>
</route>
- <route path="/private/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}">
- <param name="{gtn}handler" value="portal"/>
+ <route path="/private/{gtn:sitetype}/{gtn:sitename}{gtn:path}">
+ <param name="gtn:handler" value="portal"/>
+ <path-param name="gtn:path" pattern=".*"
encoding="preserve-path"/>
</route>
<route path="/upload">
- <param name="{gtn}handler" value="upload"/>
+ <param name="gtn:handler" value="upload"/>
</route>
<route path="/download">
- <param name="{gtn}handler" value="download"/>
+ <param name="gtn:handler" value="download"/>
</route>
<route path="/a">
Modified:
portal/branches/navcontroller/portlet/exoadmin/src/main/webapp/groovy/admintoolbar/webui/component/UIUserToolBarGroupPortlet.gtmpl
===================================================================
---
portal/branches/navcontroller/portlet/exoadmin/src/main/webapp/groovy/admintoolbar/webui/component/UIUserToolBarGroupPortlet.gtmpl 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/portlet/exoadmin/src/main/webapp/groovy/admintoolbar/webui/component/UIUserToolBarGroupPortlet.gtmpl 2010-11-04
11:22:09 UTC (rev 4941)
@@ -48,7 +48,7 @@
boolean hasChild = (node.getChildren() != null && node.getChildren().size()
> 0);
String clazz = "";
if(hasChild) clazz = "ArrowIcon";
- String actionLink = nodeURL.setResource(new
NavigationResource(navigation.getOwnerType(),
navigation.getOwnerId().replaceAll("/", "_"), node)).toString();
+ String actionLink = nodeURL.setResource(new
NavigationResource(navigation.getOwnerType(), navigation.getOwnerId(), node)).toString();
String icon = node.getIcon();
if(icon == null) icon = "DefaultPageIcon";
boolean toolong = (node.resolvedLabel.length() > 60);
Modified:
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/default-router.xml
===================================================================
---
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/default-router.xml 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/default-router.xml 2010-11-04
11:22:09 UTC (rev 4941)
@@ -6,40 +6,42 @@
<route path="/">
<!-- Use the portal handler -->
- <param name="{gtn}handler" value="portal"/>
+ <param name="gtn:handler" value="portal"/>
<!-- Webui parameters -->
- <request-param name="{gtn}componentid"
matchName="portal:componentId" required="false"/>
- <request-param name="{gtn}action" matchName="portal:action"
required="false"/>
- <request-param name="{gtn}objectid" matchName="objectId"
required="false"/>
+ <request-param name="gtn:componentid"
matchName="portal:componentId" required="false"/>
+ <request-param name="gtn:action" matchName="portal:action"
required="false"/>
+ <request-param name="gtn:objectid" matchName="objectId"
required="false"/>
<!-- Map the sitemap navigation on the /foo path -->
<!--
<route path="/foo">
- <param name="{gtn}access" value="public"/>
- <param name="{gtn}sitename" value="classic"/>
- <param name="{gtn}path" value="/sitemap"/>
+ <param name="gtn:access" value="public"/>
+ <param name="gtn:sitename" value="classic"/>
+ <param name="gtn:path" value="/sitemap"/>
</route>
-->
<!-- The public access -->
- <route path="/public/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}">
- <param name="{gtn}access" value="public"/>
+ <route path="/public/{gtn:sitetype}/{gtn:sitename}{gtn:path}">
+ <param name="gtn:access" value="public"/>
+ <path-param name="gtn:path" pattern=".*"
encoding="preserve-path"/>
</route>
<!-- The private access -->
- <route
path="/private/{{gtn}sitetype}/{{gtn}sitename}{{gtn}path:.*}">
- <param name="{gtn}access" value="private"/>
+ <route path="/private/{gtn:sitetype}/{gtn:sitename}{gtn:path}">
+ <param name="gtn:access" value="private"/>
+ <path-param name="gtn:path" pattern=".*"
encoding="preserve-path"/>
</route>
</route>
<route path="/upload">
- <param name="{gtn}handler" value="upload"/>
+ <param name="gtn:handler" value="upload"/>
</route>
<route path="/download">
- <param name="{gtn}handler" value="download"/>
+ <param name="gtn:handler" value="download"/>
</route>
</router>
\ No newline at end of file
Modified:
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/proto-router-1.xml
===================================================================
---
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/proto-router-1.xml 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/web/portal/src/main/webapp/WEB-INF/conf/proto-router-1.xml 2010-11-04
11:22:09 UTC (rev 4941)
@@ -8,31 +8,33 @@
<route path="/">
<!-- Use the portal handler -->
- <param name="{gtn}handler" value="portal"/>
+ <param name="gtn:handler" value="portal"/>
<!-- Webui parameters -->
- <request-param name="{gtn}componentid"
matchName="portal:componentId" required="false"/>
- <request-param name="{gtn}action" matchName="portal:action"
required="false"/>
- <request-param name="{gtn}objectid" matchName="objectId"
required="false"/>
+ <request-param name="gtn:componentid"
matchName="portal:componentId" required="false"/>
+ <request-param name="gtn:action" matchName="portal:action"
required="false"/>
+ <request-param name="gtn:objectid" matchName="objectId"
required="false"/>
<!-- The public access -->
- <route path="/public/{{gtn}sitename}{{gtn}path:.*}.html">
- <param name="{gtn}access" value="public"/>
+ <route path="/public/{gtn:sitename}{gtn:path}.html">
+ <param name="gtn:access" value="public"/>
+ <path-param name="gtn:path" pattern=".*"
encoding="preserve-path"/>
</route>
<!-- The private access -->
- <route path="/private/{{gtn}sitename}{{gtn}path:.*}.html">
- <param name="{gtn}access" value="private"/>
+ <route path="/private/{gtn:sitename}{gtn:path}.html">
+ <param name="gtn:access" value="private"/>
+ <path-param name="gtn:path" pattern=".*"
encoding="preserve-path"/>
</route>
</route>
<route path="/upload">
- <param name="{gtn}handler" value="upload"/>
+ <param name="gtn:handler" value="upload"/>
</route>
<route path="/download">
- <param name="{gtn}handler" value="download"/>
+ <param name="gtn:handler" value="download"/>
</route>
</router>
\ No newline at end of file
Modified:
portal/branches/navcontroller/web/portal/src/main/webapp/groovy/webui/core/UISitemapTree.gtmpl
===================================================================
---
portal/branches/navcontroller/web/portal/src/main/webapp/groovy/webui/core/UISitemapTree.gtmpl 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/web/portal/src/main/webapp/groovy/webui/core/UISitemapTree.gtmpl 2010-11-04
11:22:09 UTC (rev 4941)
@@ -37,7 +37,7 @@
actionExpand = uicomponent.event("ExpandNode", nav.getId() + "::"
+ node.getUri());
def actionCollapse = "ajaxAsyncGetRequest('" +
uicomponent.url("CollapseNode",nav.getId() + "::" + node.getUri()) +
"', true)";
- String actionLink = nodeURL.setResource(new NavigationResource(nav.getOwnerType(),
nav.getOwnerId().replaceAll("/", "_"), node)).toString();
+ String actionLink = nodeURL.setResource(new NavigationResource(nav.getOwnerType(),
nav.getOwnerId(), node)).toString();
lastNode = '';
Modified:
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
===================================================================
---
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -239,7 +239,7 @@
*/
//
this.siteType = requestSiteType;
- this.siteName = requestSiteName.replaceAll("_", "/");
+ this.siteName = requestSiteName;
this.nodePath_ = requestPath;
this.access = access;
@@ -273,7 +273,7 @@
@Override
public <R, L extends ResourceLocator<R>> ControllerURL<R, L>
newURL(ResourceType<R, L> resourceType, L locator)
{
- return new PortalURL<R, L>(controllerContext, locator, false, siteType,
siteName.replaceAll("/", "_"), access);
+ return new PortalURL<R, L>(controllerContext, locator, false, siteType,
siteName, access);
}
public ControllerContext getControllerContext()
Modified:
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURL.java
===================================================================
---
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURL.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURL.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -19,17 +19,13 @@
package org.exoplatform.portal.url;
-import org.exoplatform.Constants;
import org.exoplatform.portal.application.PortalRequestHandler;
import org.exoplatform.web.ControllerContext;
import org.exoplatform.web.WebAppController;
import org.exoplatform.web.controller.QualifiedName;
-import org.exoplatform.web.controller.router.SimpleRenderContext;
import org.exoplatform.web.url.ControllerURL;
-import org.exoplatform.web.url.MimeType;
import org.exoplatform.web.url.ResourceLocator;
-import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
@@ -41,15 +37,6 @@
{
/** . */
- private static final Map<MimeType, String> AMP_MAP = new EnumMap<MimeType,
String>(MimeType.class);
-
- static
- {
- AMP_MAP.put(MimeType.XHTML, "&");
- AMP_MAP.put(MimeType.PLAIN, "&");
- }
-
- /** . */
private final ControllerContext controllerContext;
/** . */
@@ -62,11 +49,8 @@
private final String siteName;
/** . */
- private StringBuilder buffer;
+ private PortalURLRenderContext renderContext;
- /** . */
- private SimpleRenderContext renderContext;
-
public PortalURL(ControllerContext requestContext, L locator, Boolean ajax, String
siteType, String siteName, String access)
{
super(locator, ajax);
@@ -86,11 +70,9 @@
public String toString()
{
- //
if (renderContext == null)
{
- buffer = new StringBuilder();
- renderContext = new SimpleRenderContext(buffer);
+ renderContext = new PortalURLRenderContext(new StringBuilder());
}
else
{
@@ -103,15 +85,20 @@
throw new IllegalStateException("No resource set on portal URL");
}
+ // Configure mime type
+ renderContext.setMimeType(mimeType);
+
//
if (ajax)
{
- buffer.append("javascript:");
+ renderContext.append("javascript:", false);
if (confirm != null && confirm.length() > 0)
{
-
buffer.append("if(confirm('").append(confirm.replaceAll("'",
"\\\\'")).append("'))");
+ renderContext.append("if(confirm('", false);
+ renderContext.append(confirm.replaceAll("'",
"\\\\'"), false);
+ renderContext.append("'))", false);
}
- buffer.append("ajaxGet('");
+ renderContext.append("ajaxGet('", false);
}
else
{
@@ -142,54 +129,32 @@
}
}
- //
+ // Render url via controller
controllerContext.renderURL(parameters, renderContext);
- //
- MimeType mt = mimeType;
- if (mt == null)
- {
- mt = MimeType.XHTML;
- }
- String amp = AMP_MAP.get(mt);
-
- //
- boolean questionMarkDone = false;
- Map<String, String> queryParams = renderContext.getQueryParams();
- if (queryParams.size() > 0)
- {
- for (Map.Entry<String, String> entry : queryParams.entrySet())
- {
- buffer.append(questionMarkDone ? amp : "?");
- buffer.append(entry.getKey());
- buffer.append('=');
- buffer.append(entry.getValue());
- questionMarkDone = true;
- }
- }
-
// Now append generic query parameters
for (Map.Entry<String, String[]> entry : getQueryParameters().entrySet())
{
for (String value : entry.getValue())
{
- buffer.append(questionMarkDone ? amp : "?");
- buffer.append(entry.getKey());
- buffer.append("=");
- buffer.append(value);
- questionMarkDone = true;
+ renderContext.appendQueryParameter(entry.getKey(), value);
}
}
//
if (ajax)
{
- buffer.append(questionMarkDone ? amp : "?");
- buffer.append("ajaxRequest=true");
- buffer.append("')");
+ renderContext.appendQueryParameter("ajaxRequest", "true");
+ renderContext.flush();
+ renderContext.append("')", false);
}
+ else
+ {
+ renderContext.flush();
+ }
//
- return buffer.toString();
+ String s = renderContext.toString();
+ return s;
}
}
Added:
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURLRenderContext.java
===================================================================
---
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURLRenderContext.java
(rev 0)
+++
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/url/PortalURLRenderContext.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.portal.url;
+
+import org.exoplatform.commons.utils.CharEncoder;
+import org.exoplatform.commons.utils.CharsetCharEncoder;
+import org.exoplatform.web.controller.router.RenderContext;
+import org.exoplatform.web.url.MimeType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+class PortalURLRenderContext implements RenderContext
+{
+
+ /** . */
+ private static final Map<MimeType, String> AMP_MAP = new EnumMap<MimeType,
String>(MimeType.class);
+
+ static
+ {
+ AMP_MAP.put(MimeType.XHTML, "&");
+ AMP_MAP.put(MimeType.PLAIN, "&");
+ }
+
+ /** . */
+ private static final char[] ALPHABET = "0123456789ABCDEF".toCharArray();
+
+ /** . */
+ private static final List<String[]> EMPTY = Collections.emptyList();
+
+ /** . */
+ private static final CharEncoder encoder = CharsetCharEncoder.getUTF8();
+
+ /** . */
+ private StringBuilder buffer;
+
+ /** . */
+ private List<String[]> queryParams;
+
+ /** . */
+ private MimeType mimeType;
+
+
+ PortalURLRenderContext(StringBuilder buffer)
+ {
+ this.buffer = buffer;
+ this.queryParams = EMPTY;
+ }
+
+ public MimeType getMimeType()
+ {
+ return mimeType;
+ }
+
+ public void setMimeType(MimeType mimeType)
+ {
+ this.mimeType = mimeType;
+ }
+
+ public void appendSlash()
+ {
+ append('/', false);
+ }
+
+ public void appendPath(char c)
+ {
+ append(c, true);
+ }
+
+ public void appendPath(String s)
+ {
+ append(s, true);
+ }
+
+ public void appendQueryParameter(String parameterName, String paramaterValue)
+ {
+ if (parameterName == null)
+ {
+ throw new NullPointerException("No null parameter name accepted");
+ }
+ if (paramaterValue == null)
+ {
+ throw new NullPointerException("No null parameter value accepted");
+ }
+
+ //
+ if (queryParams == EMPTY)
+ {
+ queryParams = new ArrayList<String[]>();
+ }
+
+ //
+ queryParams.add(new String[]{parameterName,paramaterValue});
+ }
+
+ void reset()
+ {
+ buffer.setLength(0);
+ queryParams.clear();
+ }
+
+ /**
+ * Finish to write to the buffer.
+ */
+ void flush()
+ {
+ MimeType mt = mimeType;
+ if (mt == null)
+ {
+ mt = MimeType.XHTML;
+ }
+ String amp = AMP_MAP.get(mt);
+
+ //
+ boolean questionMarkDone = false;
+ if (queryParams.size() > 0)
+ {
+ for (String[] pair : queryParams)
+ {
+ append(questionMarkDone ? amp : "?", false);
+ append(pair[0], true);
+ append('=', false);
+ append(pair[1], true);
+ questionMarkDone = true;
+ }
+ }
+ }
+
+ public void appendPath(char c, boolean escape)
+ {
+ append(c, escape);
+ }
+
+ public void appendPath(String s, boolean escape)
+ {
+ append(s, escape);
+ }
+
+ /**
+ * Append a string to the underlying buffer.
+ *
+ * @param s the string to append
+ * @param encode true if the char should be pplication/x-www-form-urlencoded encoded
+ */
+ void append(String s, boolean encode)
+ {
+ for (int i = 0;i < s.length();i++)
+ {
+ append(s.charAt(i), encode);
+ }
+ }
+
+ /**
+ * Append a char to the underlying buffer.
+ *
+ * @param c the char to append
+ * @param encode true if the char should be pplication/x-www-form-urlencoded encoded
+ */
+ void append(char c, boolean encode)
+ {
+ if (!encode || c >= 'A' && c <= 'Z' || c >=
'a' && c <= 'z' || c >= '0' && c <=
'9' || c == '.' || c == '-' || c == '*' || c ==
'_')
+ {
+ buffer.append(c);
+ }
+ else if (c == ' ')
+ {
+ buffer.append('+');
+ }
+ else
+ {
+ byte[] bytes = encoder.encode(c);
+ buffer.append('%');
+ for (byte b : bytes)
+ {
+ buffer.append(ALPHABET[(b & 0xF0) >> 4]);
+ buffer.append(ALPHABET[b & 0xF]);
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return buffer.toString();
+ }
+}
Modified:
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplication.java
===================================================================
---
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplication.java 2010-11-04
09:19:18 UTC (rev 4940)
+++
portal/branches/navcontroller/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplication.java 2010-11-04
11:22:09 UTC (rev 4941)
@@ -544,7 +544,7 @@
ControllerURL<NavigationResource, NavigationLocator> nodeURL =
pcontext.createURL(org.exoplatform.portal.url.navigation.NavigationLocator.TYPE);
nodeURL.setResource(new
NavigationResource(getCurrentSite().getOwnerType(), getCurrentSite()
- .getOwner().replaceAll("/", "_"),
getCurrentSite().getSelectedNode()));
+ .getOwner(), getCurrentSite().getSelectedNode()));
pcontext.sendRedirect(nodeURL.toString());
return;
}