You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2010/01/26 12:23:56 UTC
svn commit: r903175 - in /sling/trunk/bundles/servlets/get/src:
main/java/org/apache/sling/servlets/get/impl/
test/java/org/apache/sling/servlets/get/impl/
Author: fmeschbe
Date: Tue Jan 26 11:23:55 2010
New Revision: 903175
URL: http://svn.apache.org/viewvc?rev=903175&view=rev
Log:
SLING-1324 Add support to define the redirect status in the RedirectResource's
value map and some unit tests to validate helper methods.
Modified:
sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/RedirectServlet.java
sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockRequestPathInfo.java
sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockSlingHttpServletRequest.java
sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/RedirectServletTest.java
Modified: sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/RedirectServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/RedirectServlet.java?rev=903175&r1=903174&r2=903175&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/RedirectServlet.java (original)
+++ sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/RedirectServlet.java Tue Jan 26 11:23:55 2010
@@ -69,6 +69,9 @@
/** The name of the target property */
public static final String TARGET_PROP = "sling:target";
+ /** The name of the redirect status property */
+ public static final String STATUS_PROP = "sling:status";
+
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -76,20 +79,20 @@
/** @scr.property valueRef="DEFAULT_JSON_RENDERER_MAXIMUM_RESULTS" type="Integer" */
public static final String JSON_RENDERER_MAXIMUM_RESULTS_PROPERTY = "json.maximumresults";
-
+
/** Default value for the maximum amount of results that should be returned by the jsonResourceWriter */
public static final int DEFAULT_JSON_RENDERER_MAXIMUM_RESULTS = 200;
-
+
private int jsonMaximumResults;
-
+
protected void activate(ComponentContext ctx) {
Dictionary<?, ?> props = ctx.getProperties();
- this.jsonMaximumResults = OsgiUtil.toInteger(props.get(JSON_RENDERER_MAXIMUM_RESULTS_PROPERTY),
+ this.jsonMaximumResults = OsgiUtil.toInteger(props.get(JSON_RENDERER_MAXIMUM_RESULTS_PROPERTY),
DEFAULT_JSON_RENDERER_MAXIMUM_RESULTS);
// When the maximumResults get updated, we force a reset for the jsonRendererServlet.
jsonRendererServlet = getJsonRendererServlet();
}
-
+
@Override
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
@@ -136,18 +139,25 @@
// if the target resource is a path (string), redirect there
targetPath = targetResource.adaptTo(String.class);
-
}
// if we got a target path, make it external and redirect to it
if (targetPath != null) {
if (!isUrl(targetPath)) {
// make path relative and append selectors, extension etc.
+ // this is an absolute URI suitable for the Location header
targetPath = toRedirectPath(targetPath, request);
}
- // and redirect there ...
- response.sendRedirect(targetPath);
+ final int status = getStatus(valueMap);
+
+ // redirect the client, use our own setup since we might have a
+ // custom response status and we already have converted the target
+ // into an absolute URI.
+ response.reset();
+ response.setStatus(status);
+ response.setHeader("Location", targetPath);
+ response.flushBuffer();
return;
}
@@ -158,11 +168,38 @@
}
/**
- * Create a relative redirect URL for the targetPath relative to the given
- * request. The URL is relative to the request's resource and will include
- * the selectors, extension, suffix and query string of the request.
+ * Returns the response status from the {@link #STATUS_PROP} property in the
+ * value map. If <code>valueMap</code> is <code>null</code>, the property is
+ * not contained in the map or if the value is outside of the value HTTP
+ * response status range of [ 100 .. 999 ], the default status 302/FOUND is
+ * returned.
+ *
+ * @param valueMap The <code>valueMap</code> providing the optional status
+ * property.
+ * @return The status value as defined above.
+ */
+ static int getStatus(final ValueMap valueMap) {
+ if (valueMap != null) {
+ final Integer statusInt = valueMap.get(STATUS_PROP, Integer.class);
+ if (statusInt != null) {
+ int status = statusInt.intValue();
+ if (status >= 100 && status <= 999) {
+ return status;
+ }
+ }
+ }
+
+ // fall back to default value
+ return HttpServletResponse.SC_FOUND;
+
+ }
+
+ /**
+ * Create an absolute URI suitable for the "Location" response header
+ * including any selectors, extension, suffix and query from the current
+ * request.
*/
- protected static String toRedirectPath(String targetPath,
+ static String toRedirectPath(String targetPath,
SlingHttpServletRequest request) {
// if the target path is an URL, do nothing and return it unmodified
@@ -205,8 +242,47 @@
target.append('?').append(request.getQueryString());
}
- // return the mapped full path
- return request.getResourceResolver().map(request, target.toString());
+ // return the mapped full path and return if already an absolute URI
+ final String finalTarget = request.getResourceResolver().map(request, target.toString());
+ if (isUrl(finalTarget)) {
+ return finalTarget;
+ }
+
+ // otherwise prepend the current request's information
+ return toAbsoluteUri(request.getScheme(), request.getServerName(),
+ request.getServerPort(), finalTarget);
+ }
+
+ /**
+ * Returns an absolute URI built from the given parameters.
+ *
+ * @param scheme The scheme for the URI to be built.
+ * @param host The name of the host.
+ * @param port The port or -1 to not add a port number to the URI. For
+ * <code>http</code> and <code>https</code> schemes the port is
+ * not added if it is the default port.
+ * @param targetPath The path of the resulting URI. This path is expected to
+ * not be an absolute URI.
+ * @return The absolute URI built from the components.
+ */
+ static String toAbsoluteUri(final String scheme, final String host,
+ final int port, final String targetPath) {
+
+ // 1. scheme and host
+ final StringBuilder absUriBuilder = new StringBuilder();
+ absUriBuilder.append(scheme).append("://").append(host);
+
+ // 2. append the port depending on the scheme and whether the port is
+ // the default or not
+ if (port > 0) {
+ if (!(("http".equals(scheme) && port == 80) || ("https".equals(scheme) && port == 443))) {
+ absUriBuilder.append(':').append(port);
+ }
+ }
+
+ // 3. the actual target path
+ absUriBuilder.append(targetPath);
+ return absUriBuilder.toString();
}
private Servlet getJsonRendererServlet() {
@@ -224,15 +300,31 @@
/**
* Returns <code>true</code> if the path is potentially an URL. This
- * simplistic check looks for a ":/" string in the path assuming that this
- * is a separator to separate the scheme from the scheme-specific part. If
- * the separator occurs after a query separator ("?"), though, it is not
- * assumed to be a scheme-separator.
+ * checks whether the path starts with a scheme followed by a colon
+ * according to <a href="http://www.faqs.org/rfcs/rfc2396.html">RFC-2396</a>:
+ * <pre>
+ * scheme = alpha *( alpha | digit | "+" | "-" | "." )
+ * alpha = [ "A" .. "Z", "a" .. "z" ]
+ * digit = [ "0" .. "9" ]
+ * </pre>
*/
private static boolean isUrl(final String path) {
- final int protocolIndex = path.indexOf(":/");
- final int queryIndex = path.indexOf('?');
- return protocolIndex > -1
- && (queryIndex == -1 || queryIndex > protocolIndex);
+ for (int i = 0; i < path.length(); i++) {
+ char c = path.charAt(i);
+ if (c == ':') {
+ return true;
+ }
+ if (!((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (i > 0
+ && ((c >= '0' && c <= '9')
+ || c == '.'
+ || c == '+'
+ || c == '-')))) {
+ break;
+ }
+ }
+ return false;
}
+
}
Modified: sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockRequestPathInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockRequestPathInfo.java?rev=903175&r1=903174&r2=903175&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockRequestPathInfo.java (original)
+++ sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockRequestPathInfo.java Tue Jan 26 11:23:55 2010
@@ -30,10 +30,6 @@
private final String path;
- public MockRequestPathInfo(String selectors, String extension, String suffix) {
- this(selectors, extension ,suffix, null);
- }
-
public MockRequestPathInfo(String selectors, String extension, String suffix, String path) {
this.selectors = selectors;
this.extension = extension;
Modified: sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockSlingHttpServletRequest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockSlingHttpServletRequest.java?rev=903175&r1=903174&r2=903175&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockSlingHttpServletRequest.java (original)
+++ sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/MockSlingHttpServletRequest.java Tue Jan 26 11:23:55 2010
@@ -323,15 +323,15 @@
}
public String getScheme() {
- return null;
+ return RedirectServletTest.TEST_SCHEME;
}
public String getServerName() {
- return null;
+ return RedirectServletTest.TEST_HOST;
}
public int getServerPort() {
- return 0;
+ return RedirectServletTest.TEST_PORT;
}
public boolean isSecure() {
Modified: sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/RedirectServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/RedirectServletTest.java?rev=903175&r1=903174&r2=903175&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/RedirectServletTest.java (original)
+++ sling/trunk/bundles/servlets/get/src/test/java/org/apache/sling/servlets/get/impl/RedirectServletTest.java Tue Jan 26 11:23:55 2010
@@ -18,142 +18,211 @@
*/
package org.apache.sling.servlets.get.impl;
+import java.util.Collections;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletResponse;
+
import junit.framework.TestCase;
import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
public class RedirectServletTest extends TestCase {
+ static final String TEST_SCHEME = "http";
+
+ static final String TEST_HOST = "the.host.any";
+
+ static final int TEST_PORT = 80;
+
+ static final String TEST_PREFIX = TEST_SCHEME + "://" + TEST_HOST;
+
+ public void testToAbsoluteURI() {
+ final String http = "http";
+ final String https = "https";
+ final String scheme = "test";
+ final String host = TEST_HOST;
+ final int port80 = 80;
+ final int port443 = 443;
+ final int portAny = 9999;
+ final int portNone = -1;
+ final String target = "/target";
+
+ // regular building without default ports
+ assertEquals(http + "://" + host + ":" + portAny + target,
+ RedirectServlet.toAbsoluteUri(http, host, portAny, target));
+ assertEquals(https + "://" + host + ":" + portAny + target,
+ RedirectServlet.toAbsoluteUri(https, host, portAny, target));
+ assertEquals(scheme + "://" + host + ":" + portAny + target,
+ RedirectServlet.toAbsoluteUri(scheme, host, portAny, target));
+
+ // building with default ports
+ assertEquals(http + "://" + host + target,
+ RedirectServlet.toAbsoluteUri(http, host, port80, target));
+ assertEquals(https + "://" + host + target,
+ RedirectServlet.toAbsoluteUri(https, host, port443, target));
+ assertEquals(scheme + "://" + host + ":" + port80 + target,
+ RedirectServlet.toAbsoluteUri(scheme, host, port80, target));
+
+ // building without ports
+ assertEquals(http + "://" + host + target,
+ RedirectServlet.toAbsoluteUri(http, host, portNone, target));
+ assertEquals(https + "://" + host + target,
+ RedirectServlet.toAbsoluteUri(https, host, portNone, target));
+ assertEquals(scheme + "://" + host + target,
+ RedirectServlet.toAbsoluteUri(scheme, host, portNone, target));
+ }
+
+ public void testGetStatus() {
+ final int found = HttpServletResponse.SC_FOUND;
+ final int valid = 768;
+ final int invalidLow = 77;
+ final int invalidHigh = 1234;
+ final int min = 100;
+ final int max = 999;
+
+ assertStatus(found, -2);
+ assertStatus(found, -1);
+ assertStatus(found, invalidLow);
+ assertStatus(found, invalidHigh);
+
+ assertStatus(valid, valid);
+ assertStatus(min, min);
+ assertStatus(max, max);
+ }
+
public void testSameParent() {
String base = "/a";
String target = "/b";
- assertEquals("/b", toRedirect(base, target));
+ assertEqualsUri("/b", toRedirect(base, target));
base = "/";
target = "/a";
- assertEquals("/a", toRedirect(base, target));
+ assertEqualsUri("/a", toRedirect(base, target));
base = "/a/b/c";
target = "/a/b/d";
- assertEquals("/a/b/d", toRedirect(base, target));
+ assertEqualsUri("/a/b/d", toRedirect(base, target));
}
public void testTrailingSlash() {
String base = "/a/b/c/";
String target = "/a/b/c.html";
- assertEquals("/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/a/b/c.html", toRedirect(base, target));
}
public void testCommonAncestor() {
String base = "/a/b/c/d";
String target = "/a/b/x/y";
- assertEquals("/a/b/x/y", toRedirect(base, target));
+ assertEqualsUri("/a/b/x/y", toRedirect(base, target));
}
public void testChild() {
String base = "/a.html";
String target = "/a/b.html";
- assertEquals("/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/a/b.html", toRedirect(base, target));
base = "/a";
target = "/a/b.html";
- assertEquals("/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/a/b.html", toRedirect(base, target));
base = "/a";
target = "/a/b";
- assertEquals("/a/b", toRedirect(base, target));
+ assertEqualsUri("/a/b", toRedirect(base, target));
base = "/a.html";
target = "/a/b/c.html";
- assertEquals("/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/a/b/c.html", toRedirect(base, target));
base = "/a";
target = "/a/b/c.html";
- assertEquals("/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/a/b/c.html", toRedirect(base, target));
base = "/a";
target = "/a/b/c";
- assertEquals("/a/b/c", toRedirect(base, target));
+ assertEqualsUri("/a/b/c", toRedirect(base, target));
}
public void testChildNonRoot() {
String base = "/x/a.html";
String target = "/x/a/b.html";
- assertEquals("/x/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b.html", toRedirect(base, target));
base = "/x/a";
target = "/x/a/b.html";
- assertEquals("/x/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b.html", toRedirect(base, target));
base = "/x/a";
target = "/x/a/b";
- assertEquals("/x/a/b", toRedirect(base, target));
+ assertEqualsUri("/x/a/b", toRedirect(base, target));
base = "/x/a.html";
target = "/x/a/b/c.html";
- assertEquals("/x/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b/c.html", toRedirect(base, target));
base = "/x/a";
target = "/x/a/b/c.html";
- assertEquals("/x/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b/c.html", toRedirect(base, target));
base = "/x/a";
target = "/x/a/b/c";
- assertEquals("/x/a/b/c", toRedirect(base, target));
+ assertEqualsUri("/x/a/b/c", toRedirect(base, target));
}
public void testChildRelative() {
String base = "/a";
String target = "b.html";
- assertEquals("/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/a/b.html", toRedirect(base, target));
base = "/a";
target = "b";
- assertEquals("/a/b", toRedirect(base, target));
+ assertEqualsUri("/a/b", toRedirect(base, target));
base = "/a";
target = "b/c.html";
- assertEquals("/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/a/b/c.html", toRedirect(base, target));
base = "/a";
target = "b/c";
- assertEquals("/a/b/c", toRedirect(base, target));
+ assertEqualsUri("/a/b/c", toRedirect(base, target));
}
public void testChildNonRootRelative() {
String base = "/x/a";
String target = "b.html";
- assertEquals("/x/a/b.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b.html", toRedirect(base, target));
base = "/x/a";
target = "b";
- assertEquals("/x/a/b", toRedirect(base, target));
+ assertEqualsUri("/x/a/b", toRedirect(base, target));
base = "/x/a";
target = "b/c.html";
- assertEquals("/x/a/b/c.html", toRedirect(base, target));
+ assertEqualsUri("/x/a/b/c.html", toRedirect(base, target));
base = "/x/a";
target = "b/c";
- assertEquals("/x/a/b/c", toRedirect(base, target));
+ assertEqualsUri("/x/a/b/c", toRedirect(base, target));
}
public void testUnCommon() {
String base = "/a/b/c/d";
String target = "/w/x/y/z";
- assertEquals("/w/x/y/z", toRedirect(base, target));
+ assertEqualsUri("/w/x/y/z", toRedirect(base, target));
}
public void testSibbling() {
String base = "/a/b";
String target0 = "../y/z";
- assertEquals("/a/y/z", toRedirect(base, target0));
+ assertEqualsUri("/a/y/z", toRedirect(base, target0));
String target1 = "../../y/z";
- assertEquals("/y/z", toRedirect(base, target1));
+ assertEqualsUri("/y/z", toRedirect(base, target1));
String target2 = "../../../y/z";
- assertEquals(base + "/" + target2, toRedirect(base, target2));
+ assertEqualsUri(base + "/" + target2, toRedirect(base, target2));
}
public void testSelectorsEtc() {
@@ -218,7 +287,20 @@
target);
}
- private void assertEquals(String expected, String basePath,
+ public void testEmptyPath() {
+ SlingHttpServletRequest request = new MockSlingHttpServletRequest("/",
+ null, null, null, null, "", "/webapp");
+ String path = RedirectServlet.toRedirectPath("/index.html", request);
+ assertEqualsUri("/webapp/index.html", path);
+ request = new MockSlingHttpServletRequest("/", null, null, null, null,
+ "/", "/webapp");
+ path = RedirectServlet.toRedirectPath("/index.html", request);
+ assertEqualsUri("/webapp/index.html", path);
+ }
+
+ //---------- Helper
+
+ private static void assertEquals(String expected, String basePath,
String selectors, String extension, String suffix,
String queryString, String targetPath) {
@@ -238,14 +320,35 @@
String actual = toRedirect(basePath, selectors, extension, suffix,
queryString, targetPath);
- assertEquals(expected, actual);
+ assertEqualsUri(expected, actual);
+ }
+
+ private static void assertEqualsUri(String expected, String actual) {
+ assertEquals(TEST_PREFIX + expected, actual);
+ }
+
+ private static void assertStatus(final int expectedStatus,
+ final int testStatus) {
+ final ValueMap valueMap;
+ if (testStatus == -2) {
+ valueMap = null;
+ } else if (testStatus == -1) {
+ valueMap = new ValueMapDecorator(new HashMap<String, Object>());
+ } else {
+ valueMap = new ValueMapDecorator(Collections.singletonMap(
+ RedirectServlet.STATUS_PROP, (Object) testStatus));
+ }
+
+ final int actualStatus = RedirectServlet.getStatus(valueMap);
+
+ assertEquals(expectedStatus, actualStatus);
}
- private String toRedirect(String basePath, String targetPath) {
+ private static String toRedirect(String basePath, String targetPath) {
return toRedirect(basePath, null, null, null, null, targetPath);
}
- private String toRedirect(String basePath, String selectors,
+ private static String toRedirect(String basePath, String selectors,
String extension, String suffix, String queryString,
String targetPath) {
SlingHttpServletRequest request = new MockSlingHttpServletRequest(
@@ -253,14 +356,4 @@
return RedirectServlet.toRedirectPath(targetPath, request);
}
- public void testEmptyPath() {
- SlingHttpServletRequest request = new MockSlingHttpServletRequest("/",
- null, null, null, null, "", "/webapp");
- String path = RedirectServlet.toRedirectPath("/index.html", request);
- assertEquals("/webapp/index.html", path);
- request = new MockSlingHttpServletRequest("/", null, null, null, null,
- "/", "/webapp");
- path = RedirectServlet.toRedirectPath("/index.html", request);
- assertEquals("/webapp/index.html", path);
- }
}