Author: justin
Date: Sat Jun 11 03:03:15 2011
New Revision: 1134511
URL: http://svn.apache.org/viewvc?rev=1134511&view=rev
Log:
SLING-2101 - adding support for a sling:redirectStatus property which
determines the status code returned to the requestor of a vanity path where
sling:redirect is true
Added:
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VanityPathTest.java
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
sling/trunk/bundles/jcr/resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java?rev=1134511&r1=1134510&r2=1134511&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
Sat Jun 11 03:03:15 2011
@@ -299,7 +299,7 @@ public class MapEntries implements Event
List<MapEntry> entries) {
// sling:VanityPath (uppercase V) is the mixin name
// sling:vanityPath (lowercase) is the property name
- final String queryString = "SELECT sling:vanityPath, sling:redirect
FROM sling:VanityPath WHERE sling:vanityPath IS NOT NULL ORDER BY
sling:vanityOrder DESC";
+ final String queryString = "SELECT sling:vanityPath, sling:redirect,
sling:redirectStatus FROM sling:VanityPath WHERE sling:vanityPath IS NOT NULL
ORDER BY sling:vanityOrder DESC";
final Iterator<Resource> i = resolver.findResources(
queryString, Query.SQL);
while (i.hasNext()) {
@@ -325,7 +325,7 @@ public class MapEntries implements Event
// whether the target is attained by a 302/FOUND or by an
// internal redirect is defined by the sling:redirect
property
int status = row.get("sling:redirect", false)
- ? HttpServletResponse.SC_FOUND
+ ? row.get("sling:redirectStatus",
HttpServletResponse.SC_FOUND)
: -1;
// 1. entry with exact match
Modified:
sling/trunk/bundles/jcr/resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd?rev=1134511&r1=1134510&r2=1134511&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd
(original)
+++
sling/trunk/bundles/jcr/resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd
Sat Jun 11 03:03:15 2011
@@ -26,3 +26,4 @@
- sling:vanityPath (string) multiple
- sling:redirect (boolean)
- sling:vanityOrder (long)
+ - sling:redirectStatus (long)
Added:
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VanityPathTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VanityPathTest.java?rev=1134511&view=auto
==============================================================================
---
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VanityPathTest.java
(added)
+++
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VanityPathTest.java
Sat Jun 11 03:03:15 2011
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.sling.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Tests of the sling:VanityPath mixin support.
+ *
+ */
+public class VanityPathTest extends HttpTestBase {
+ private String postUrl;
+ private String vanityPath;
+ private String vanityUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // create the test node, under a path that's specific to this class to
+ // allow collisions
+ postUrl = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "_"
+ + System.currentTimeMillis()
+ + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ vanityPath = "/" + getClass().getSimpleName() + "_" +
System.currentTimeMillis() + "/vanity";
+ vanityUrl = HTTP_BASE_URL + vanityPath;
+
+
+ }
+
+ /** test vanity path with internal redirect */
+ public void testInternalRedirect() throws IOException {
+ // create a node with a vanity path
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("jcr:mixinTypes", "sling:VanityPath");
+ props.put("sling:vanityPath", vanityPath);
+ String createdNodeUrl = testClient.createNode(postUrl, props);
+ String createdPath = createdNodeUrl.substring(HTTP_BASE_URL.length());
+
+ waitForMapReload();
+
+ // get the created node without following redirects
+ GetMethod get = new GetMethod(vanityUrl);
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect a 200, not a redirect
+ assertEquals(200, status);
+
+ assertTrue(get.getResponseBodyAsString().contains(createdPath));
+ }
+
+ /** test vanity path with redirect */
+ public void test302Redirect() throws IOException {
+ // create a node with a vanity path
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("jcr:mixinTypes", "sling:VanityPath");
+ props.put("sling:vanityPath", vanityPath);
+ props.put("sling:redirect", "true");
+ String createdNodeUrl = testClient.createNode(postUrl, props);
+
+ waitForMapReload();
+
+ // get the created node's vanity path without following redirects
+ GetMethod get = new GetMethod(vanityUrl);
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect temporary redirect ...
+ assertEquals(302, status);
+
+ // ... to the created node
+ String location = get.getResponseHeader("Location").getValue();
+ assertNotNull(location);
+ assertEquals(createdNodeUrl + ".html", location);
+ }
+
+ /** test vanity path with 301 redirect */
+ public void test301Redirect() throws IOException {
+ // create a node with a vanity path
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("jcr:mixinTypes", "sling:VanityPath");
+ props.put("sling:vanityPath", vanityPath);
+ props.put("sling:redirect", "true");
+ props.put("sling:redirectStatus", "301");
+ String createdNodeUrl = testClient.createNode(postUrl, props);
+
+ waitForMapReload();
+
+ // get the created node without following redirects
+ GetMethod get = new GetMethod(vanityUrl);
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect permanent redirect ...
+ assertEquals(301, status);
+
+ // ... to the created node
+ String location = get.getResponseHeader("Location").getValue();
+ assertNotNull(location);
+ assertEquals(createdNodeUrl + ".html", location);
+ }
+
+ /** test vanity path with redirect using a non-html extension and a
selector */
+ public void testRedirectKeepingExtensionAndSelector() throws IOException {
+ // create a node with a vanity path
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("jcr:mixinTypes", "sling:VanityPath");
+ props.put("sling:vanityPath", vanityPath);
+ props.put("sling:redirect", "true");
+ String createdNodeUrl = testClient.createNode(postUrl, props);
+
+ waitForMapReload();
+
+ // get the created node's vanity path without following redirects
+ GetMethod get = new GetMethod(vanityUrl + ".test.json");
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect temporary redirect ...
+ assertEquals(302, status);
+
+ // ... to the created node
+ String location = get.getResponseHeader("Location").getValue();
+ assertNotNull(location);
+ assertEquals(createdNodeUrl + ".test.json", location);
+ }
+
+ /**
+ * Wait a little bit to give the observation events to fire, causing
+ * MapEntries to reinitialize.
+ */
+ private void waitForMapReload() {
+ try {
+ Thread.sleep(500L);
+ } catch (InterruptedException e) {
+ }
+ }
+}