You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/01/28 13:29:35 UTC

svn commit: r615860 - in /incubator/sling/trunk/jcr/resource/src: main/java/org/apache/sling/jcr/resource/internal/ main/java/org/apache/sling/jcr/resource/internal/helper/ test/java/org/apache/sling/jcr/resource/internal/ test/java/org/apache/sling/jc...

Author: bdelacretaz
Date: Mon Jan 28 04:29:30 2008
New Revision: 615860

URL: http://svn.apache.org/viewvc?rev=615860&view=rev
Log:
SLING-179 - ResourceResolver should not go up the path for GET requests

Modified:
    incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
    incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java
    incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java
    incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java

Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java?rev=615860&r1=615859&r2=615860&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java Mon Jan 28 04:29:30 2008
@@ -27,9 +27,6 @@
 import java.util.List;
 import java.util.Map;
 
-import javax.jcr.Item;
-import javax.jcr.Node;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
@@ -50,7 +47,6 @@
 import org.apache.sling.jcr.resource.internal.helper.ResourcePathIterator;
 import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry;
 import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResourceIterator;
-import org.apache.sling.jcr.resource.internal.helper.jcr.JcrPropertyResource;
 import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,7 +76,7 @@
 
     public Resource resolve(HttpServletRequest request) throws SlingException {
         String pathInfo = request.getPathInfo();
-        Resource result = resolve(pathInfo);
+        Resource result = resolve(pathInfo, request.getMethod());
 
         if (result == null) {
             result = new NonExistingResource(pathInfo);
@@ -221,6 +217,45 @@
      *             to this manager's session.
      */
     public Resource resolve(String uri) throws SlingException {
+        // TODO for now use null as a method to make sure this goes up the path
+        // (see SLING-179)
+        return resolve(uri, null);
+    }
+
+    public String pathToURL(Resource resource) {
+        String path = resource.getPath();
+
+        // get first map
+        String href = null;
+        Mapping[] mappings = factory.getMappings();
+        for (int i = 0; i < mappings.length && href == null; i++) {
+            href = mappings[i].mapHandle(path);
+        }
+
+        // if no mapping's to prefix matches the handle, use the handle itself
+        if (href == null) {
+            href = path;
+        }
+
+        // check virtual mappings
+        String virtual = factory.realToVirtualUri(href);
+        if (virtual != null) {
+            log.debug("pathToURL: Using virtual URI {} for path {}", virtual,
+                href);
+            href = virtual;
+        }
+
+        log.debug("MapHandle: {} -> {}", path, href);
+        return href;
+    }
+
+    // ---------- implementation helper ----------------------------------------
+
+    /**
+     * @throws AccessControlException If an item would exist but is not readable
+     *             to this manager's session.
+     */
+    public Resource resolve(String uri, String httpMethod) throws SlingException {
 
         // decode the request URI (required as the servlet container does not
         try {
@@ -242,7 +277,7 @@
         try {
 
             // translate url to a mapped url structure
-            Resource result = transformURL(uri);
+            Resource result = urlToResource(uri, httpMethod);
             return result;
 
         } catch (AccessControlException ace) {
@@ -259,40 +294,11 @@
         }
     }
 
-    public String pathToURL(Resource resource) {
-        String path = resource.getPath();
-
-        // get first map
-        String href = null;
-        Mapping[] mappings = factory.getMappings();
-        for (int i = 0; i < mappings.length && href == null; i++) {
-            href = mappings[i].mapHandle(path);
-        }
-
-        // if no mapping's to prefix matches the handle, use the handle itself
-        if (href == null) {
-            href = path;
-        }
-
-        // check virtual mappings
-        String virtual = factory.realToVirtualUri(href);
-        if (virtual != null) {
-            log.debug("pathToURL: Using virtual URI {} for path {}", virtual,
-                href);
-            href = virtual;
-        }
-
-        log.debug("MapHandle: {} -> {}", path, href);
-        return href;
-    }
-
-    // ---------- implementation helper ----------------------------------------
-
     public Session getSession() {
         return rootProvider.getSession();
     }
 
-    private Resource transformURL(String uri) throws SlingException {
+    private Resource urlToResource(String uri, String httpMethod) throws SlingException {
         Mapping[] mappings = factory.getMappings();
         for (int i = 0; i < mappings.length; i++) {
             // exchange the 'to'-portion with the 'from' portion and check
@@ -302,7 +308,7 @@
                 continue;
             }
 
-            Resource resource = scanPath(mappedUri);
+            Resource resource = scanPath(mappedUri, httpMethod);
             if (resource != null) {
 
                 ResourceMetadata rm = resource.getResourceMetadata();
@@ -324,11 +330,11 @@
 
     }
 
-    private Resource scanPath(String uriPath) throws SlingException {
+    private Resource scanPath(String uriPath, String httpMethod) throws SlingException {
         Resource resource = null;
         String curPath = uriPath;
         try {
-            final ResourcePathIterator it = new ResourcePathIterator(uriPath);
+            final ResourcePathIterator it = new ResourcePathIterator(uriPath, httpMethod);
             while (it.hasNext() && resource == null) {
                 curPath = it.next();
                 resource = getResourceInternal(curPath);

Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java?rev=615860&r1=615859&r2=615860&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java Mon Jan 28 04:29:30 2008
@@ -34,18 +34,31 @@
  * <p>
  * The root path (/) is never returned. Creating a resource path iterator with a
  * null or empty path or a root path will not return anything.
+ * 
+ * The above rules are not valid for GET or HEAD requests, where
+ * we do not go up the path: for those requests, the path is
+ * only split at dots that follow the last slash
  */
 public class ResourcePathIterator implements Iterator<String> {
 
     private String nextPath;
+    private final String httpMethod;
+    private final int smallestBreakPos;
 
-    public ResourcePathIterator(String path) {
+    public ResourcePathIterator(String path, String httpMethod) {
+        this.httpMethod = httpMethod;
+
+        // For GET or HEAD requests, path can only be split after
+        // the last slash (SLING-179)
+        final boolean getOrHead = "GET".equals(httpMethod) || "HEAD".equals(httpMethod);
+        smallestBreakPos = getOrHead ? path.lastIndexOf('/') : 0; 
+            
         if (path != null) {
             int i = path.length() - 1;
-            while (i >= 0 && path.charAt(i) == '/') {
+            while (i >= smallestBreakPos && path.charAt(i) == '/') {
                 i--;
             }
-            if (i < 0) {
+            if (i < 0 || i <= smallestBreakPos) {
                 nextPath = null;
             } else if (i < path.length() - 1) {
                 nextPath = path.substring(0, i + 1);
@@ -70,7 +83,7 @@
 
         // find next path
         int pos = result.length() - 1;
-        while (pos >= 0) {
+        while (pos >= smallestBreakPos) {
             final char c = result.charAt(pos);
             if (c == '.' || c == '/') {
                 break;
@@ -78,7 +91,7 @@
             pos--;
         }
 
-        nextPath = (pos <= 0) ? null : result.substring(0, pos);
+        nextPath = (pos <= smallestBreakPos) ? null : result.substring(0, pos);
 
         return result;
     }

Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java?rev=615860&r1=615859&r2=615860&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java Mon Jan 28 04:29:30 2008
@@ -27,50 +27,40 @@
 
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.Node;
-import javax.jcr.Session;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
-import junit.framework.TestCase;
-
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.resource.NonExistingResource;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.commons.testing.jcr.RepositoryUtil;
-import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
 import org.apache.sling.jcr.resource.JcrResourceConstants;
 import org.apache.sling.jcr.resource.internal.helper.Mapping;
 
-public class JcrResourceResolverTest extends TestCase {
-
-    private Session session;
-
-    private String root;
+public class JcrResourceResolverTest extends RepositoryTestBase {
 
+    private String rootPath;
     private Node rootNode;
-
     private ResourceResolver resResolver;
 
     protected void setUp() throws Exception {
-        RepositoryUtil.startRepository();
-        SlingRepository repository = RepositoryUtil.getRepository();
-
+        super.setUp();
+        getSession();
+        
         JcrResourceResolverFactoryImpl resFac = new JcrResourceResolverFactoryImpl();
 
         Field repoField = resFac.getClass().getDeclaredField("repository");
         repoField.setAccessible(true);
-        repoField.set(resFac, repository);
+        repoField.set(resFac, getRepository());
 
         Field mappingsField = resFac.getClass().getDeclaredField("mappings");
         mappingsField.setAccessible(true);
         mappingsField.set(resFac, new Mapping[] { Mapping.DIRECT });
 
-        session = RepositoryUtil.getRepository().loginAdministrative(null);
-
         try {
             NamespaceRegistry nsr = session.getWorkspace().getNamespaceRegistry();
             nsr.registerNamespace(SlingConstants.NAMESPACE_PREFIX,
@@ -81,8 +71,8 @@
 
         resResolver = resFac.getResourceResolver(session);
 
-        root = "/test" + System.currentTimeMillis();
-        rootNode = session.getRootNode().addNode(root.substring(1),
+        rootPath = "/test" + System.currentTimeMillis();
+        rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
             "nt:unstructured");
         session.save();
     }
@@ -93,19 +83,13 @@
             rootNode.remove();
             session.save();
         }
-
-        if (session != null) {
-            session.logout();
-        }
-
-        RepositoryUtil.stopRepository();
     }
 
     public void testGetResource() throws Exception {
         // existing resource
-        Resource res = resResolver.getResource(root);
+        Resource res = resResolver.getResource(rootPath);
         assertNotNull(res);
-        assertEquals(root, res.getPath());
+        assertEquals(rootPath, res.getPath());
         assertEquals(rootNode.getPrimaryNodeType().getName(),
             res.getResourceType());
 
@@ -113,16 +97,16 @@
         assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
 
         // missing resource
-        String path = root + "/missing";
+        String path = rootPath + "/missing";
         res = resResolver.getResource(path);
         assertNull(res);
     }
 
     public void testResolveResource() throws Exception {
         // existing resource
-        Resource res = resResolver.resolve(new ResourceResolverTestRequest(root));
+        Resource res = resResolver.resolve(new ResourceResolverTestRequest(rootPath));
         assertNotNull(res);
-        assertEquals(root, res.getPath());
+        assertEquals(rootPath, res.getPath());
         assertEquals(rootNode.getPrimaryNodeType().getName(),
             res.getResourceType());
 
@@ -130,10 +114,10 @@
         assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
 
         // missing resource below root should resolve root
-        String path = root + "/missing";
+        String path = rootPath + "/missing";
         res = resResolver.resolve(new ResourceResolverTestRequest(path));
         assertNotNull(res);
-        assertEquals(root, res.getPath());
+        assertEquals(rootPath, res.getPath());
         assertEquals(rootNode.getPrimaryNodeType().getName(),
             res.getResourceType());
 
@@ -141,10 +125,10 @@
         assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
 
         // root with selectors/ext should resolve root
-        path = root + ".print.a4.html";
+        path = rootPath + ".print.a4.html";
         res = resResolver.resolve(new ResourceResolverTestRequest(path));
         assertNotNull(res);
-        assertEquals(root, res.getPath());
+        assertEquals(rootPath, res.getPath());
         assertEquals(rootNode.getPrimaryNodeType().getName(),
             res.getResourceType());
 
@@ -152,20 +136,54 @@
         assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
 
         // missing resource should return NON_EXISTING Resource
-        path = root + System.currentTimeMillis();
+        path = rootPath + System.currentTimeMillis();
         res = resResolver.resolve(new ResourceResolverTestRequest(path));
         assertNotNull(res);
         assertTrue(res instanceof NonExistingResource);
         assertEquals(path, res.getPath());
         assertEquals(Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
     }
+    
+    public void testGetDoesNotGoUp() throws Exception {
+        
+        final String path = rootPath + "/nothing";
+        
+        { 
+            final Resource res = resResolver.resolve(new ResourceResolverTestRequest(path, "POST"));
+            assertNotNull(res);
+            assertEquals("POST request resolution goes up up the path to rootPath", rootPath, res.getPath());
+            assertEquals(rootNode.getPrimaryNodeType().getName(), res.getResourceType());
+        }
+        
+        { 
+            final Resource res = resResolver.resolve(new ResourceResolverTestRequest(path, "GET"));
+            assertNotNull(res);
+            assertEquals("GET request resolution does not go up the path", 
+                    Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
+        }
+    }
+    
+    public void testGetRemovesExtensionInResolution() throws Exception {
+        final String path = rootPath + ".whatever";
+        final Resource res = resResolver.resolve(new ResourceResolverTestRequest(path, "GET"));
+        assertNotNull(res);
+        assertEquals(rootPath, res.getPath());
+        assertEquals(rootNode.getPrimaryNodeType().getName(), res.getResourceType());
+    }
+
 
     private static class ResourceResolverTestRequest implements HttpServletRequest {
 
-        private String pathInfo;
+        private final String pathInfo;
+        private final String method;
 
         ResourceResolverTestRequest(String pathInfo) {
+            this(pathInfo, null);
+        }
+
+        ResourceResolverTestRequest(String pathInfo, String httpMethod) {
             this.pathInfo = pathInfo;
+            this.method = httpMethod;
         }
 
         public String getPathInfo() {
@@ -318,7 +336,7 @@
         }
 
         public String getMethod() {
-            return null;
+            return method;
         }
 
         public String getPathTranslated() {

Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java?rev=615860&r1=615859&r2=615860&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java Mon Jan 28 04:29:30 2008
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import java.util.Iterator;
 import java.util.NoSuchElementException;
 
 import junit.framework.TestCase;
@@ -25,7 +26,7 @@
 public class ResourcePathIteratorTest extends TestCase {
 
     public void testNull() {
-        ResourcePathIterator rpi = new ResourcePathIterator(null);
+        ResourcePathIterator rpi = new ResourcePathIterator(null,"POST");
         assertFalse(rpi.hasNext());
 
         try {
@@ -37,7 +38,7 @@
     }
 
     public void testEmpty() {
-        ResourcePathIterator rpi = new ResourcePathIterator("");
+        ResourcePathIterator rpi = new ResourcePathIterator("","POST");
         assertFalse(rpi.hasNext());
 
         try {
@@ -49,7 +50,7 @@
     }
 
     public void testRoot() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/");
+        ResourcePathIterator rpi = new ResourcePathIterator("/","POST");
         assertFalse(rpi.hasNext());
 
         try {
@@ -61,7 +62,7 @@
     }
 
     public void testSlashed() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/root/child");
+        ResourcePathIterator rpi = new ResourcePathIterator("/root/child","POST");
         assertEquals("/root/child", rpi.next());
         assertEquals("/root", rpi.next());
         assertFalse(rpi.hasNext());
@@ -74,8 +75,25 @@
         }
     }
     
+    public void testOtherMethods() {
+        final String [] methods = { "PUT", "WHATEVER.METHOD", null };
+        for(String method : methods) {
+            ResourcePathIterator rpi = new ResourcePathIterator("/root/child",method);
+            assertEquals("/root/child", rpi.next());
+            assertEquals("/root", rpi.next());
+            assertFalse(rpi.hasNext());
+            
+            try {
+                rpi.next();
+                fail("Expected NoSuchElementException after end of iterator");
+            } catch (NoSuchElementException nsee) {
+                // expected
+            }
+        }
+    }
+    
     public void testSlashedTrailingSlash1() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/root/child/");
+        ResourcePathIterator rpi = new ResourcePathIterator("/root/child/","POST");
         assertEquals("/root/child", rpi.next());
         assertEquals("/root", rpi.next());
         assertFalse(rpi.hasNext());
@@ -89,7 +107,7 @@
     }
     
     public void testSlashedTrailingSlash2() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/root/child//");
+        ResourcePathIterator rpi = new ResourcePathIterator("/root/child//","POST");
         assertEquals("/root/child", rpi.next());
         assertEquals("/root", rpi.next());
         assertFalse(rpi.hasNext());
@@ -103,7 +121,7 @@
     }
 
     public void testDotted() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/root.child");
+        ResourcePathIterator rpi = new ResourcePathIterator("/root.child","POST");
         assertEquals("/root.child", rpi.next());
         assertEquals("/root", rpi.next());
         assertFalse(rpi.hasNext());
@@ -117,7 +135,7 @@
     }
 
     public void testMixed() {
-        ResourcePathIterator rpi = new ResourcePathIterator("/root/child.print.a4.html/with/suffix");
+        ResourcePathIterator rpi = new ResourcePathIterator("/root/child.print.a4.html/with/suffix","POST");
         assertEquals("/root/child.print.a4.html/with/suffix", rpi.next());
         assertEquals("/root/child.print.a4.html/with", rpi.next());
         assertEquals("/root/child.print.a4.html", rpi.next());
@@ -134,5 +152,67 @@
             // expected
         }
     }
-
-}
+    
+    public void testNoSeparators() {
+        final Iterator<String> it = new ResourcePathIterator("MickeyMouseWasHere","POST");
+        assertTrue(it.hasNext());
+        assertEquals("MickeyMouseWasHere",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+
+    public void testGetA() {
+        final Iterator<String> it = new ResourcePathIterator("/some/stuff/more.a4.html","GET");
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more.a4.html",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more.a4",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+    
+    public void testGetB() {
+        final Iterator<String> it = new ResourcePathIterator("/some/stuff/more.html","GET");
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more.html",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+    
+    public void testHeadB() {
+        final Iterator<String> it = new ResourcePathIterator("/some/stuff/more.html","HEAD");
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more.html",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+    
+    public void testGetC() {
+        final Iterator<String> it = new ResourcePathIterator("/some/stuff/more","GET");
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff/more",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+    
+    public void testGetD() {
+        final Iterator<String> it = new ResourcePathIterator("/some/stuff.print/more.html","GET");
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff.print/more.html",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("/some/stuff.print/more",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+    
+    public void testRelativePath() {
+        final Iterator<String> it = new ResourcePathIterator("some/stuff.print","POST");
+        assertTrue(it.hasNext());
+        assertEquals("some/stuff.print",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("some/stuff",it.next());
+        assertTrue(it.hasNext());
+        assertEquals("some",it.next());
+        assertFalse("done iterating", it.hasNext());
+    }
+}
\ No newline at end of file