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 2008/02/05 19:29:36 UTC

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

Author: fmeschbe
Date: Tue Feb  5 10:29:33 2008
New Revision: 618734

URL: http://svn.apache.org/viewvc?rev=618734&view=rev
Log:
SLING-220 Refactoring the resource resolution process using the ResourceProviderEntry tree.
See issue for more information.

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/ResourceProviderEntry.java
    incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java
    incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.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=618734&r1=618733&r2=618734&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 Tue Feb  5 10:29:33 2008
@@ -45,7 +45,6 @@
 import org.apache.sling.jcr.resource.internal.helper.Descendable;
 import org.apache.sling.jcr.resource.internal.helper.Mapping;
 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.JcrResourceProviderEntry;
 import org.slf4j.Logger;
@@ -54,20 +53,23 @@
 /**
  * The <code>JcrResourceResolver</code> class implements the Sling
  * <code>ResourceResolver</code> and <code>ResourceResolver</code>
- * interfaces and in addition is a {@link PathMapper}. Instances of this
- * class are retrieved through the
+ * interfaces and in addition is a {@link PathMapper}. Instances of this class
+ * are retrieved through the
  * {@link org.apache.sling.jcr.resource.JcrResourceResolverFactory#getResourceResolver(Session)}
  * method.
  */
-public class JcrResourceResolver extends SlingAdaptable implements ResourceResolver {
+public class JcrResourceResolver extends SlingAdaptable implements
+        ResourceResolver {
 
     /** default log */
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     private final JcrResourceProviderEntry rootProvider;
+
     private final JcrResourceResolverFactoryImpl factory;
 
-    public JcrResourceResolver(JcrResourceProviderEntry rootProvider, JcrResourceResolverFactoryImpl factory) {
+    public JcrResourceResolver(JcrResourceProviderEntry rootProvider,
+            JcrResourceResolverFactoryImpl factory) {
         this.rootProvider = rootProvider;
         this.factory = factory;
     }
@@ -120,8 +122,7 @@
         // check virtual mappings
         String virtual = factory.realToVirtualUri(href);
         if (virtual != null) {
-            log.debug("map: Using virtual URI {} for path {}", virtual,
-                href);
+            log.debug("map: Using virtual URI {} for path {}", virtual, href);
             href = virtual;
         }
 
@@ -148,7 +149,7 @@
 
         // no resource found, if we get here
         return null;
-     }
+    }
 
     public Resource getResource(Resource base, String path) {
 
@@ -188,7 +189,8 @@
         try {
             QueryResult res = JcrResourceUtil.query(getSession(), query,
                 language);
-            return new JcrNodeResourceIterator(rootProvider.getResourceProvider(), res.getNodes());
+            return new JcrNodeResourceIterator(
+                rootProvider.getResourceProvider(), res.getNodes());
         } catch (javax.jcr.query.InvalidQueryException iqe) {
             throw new QuerySyntaxException(iqe.getMessage(), query, language,
                 iqe);
@@ -253,7 +255,8 @@
      * @throws AccessControlException If an item would exist but is not readable
      *             to this manager's session.
      */
-    private Resource resolve(String uri, String httpMethod) throws SlingException {
+    private Resource resolve(String uri, String httpMethod)
+            throws SlingException {
 
         // decode the request URI (required as the servlet container does not
         try {
@@ -296,7 +299,8 @@
         return rootProvider.getSession();
     }
 
-    private Resource urlToResource(String uri, String httpMethod) 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
@@ -328,11 +332,13 @@
 
     }
 
-    private Resource scanPath(String uriPath, String httpMethod) throws SlingException {
+    private Resource scanPath(String uriPath, String httpMethod)
+            throws SlingException {
         Resource resource = null;
         String curPath = uriPath;
         try {
-            final ResourcePathIterator it = new ResourcePathIterator(uriPath, httpMethod);
+            final ResourcePathIterator it = new ResourcePathIterator(uriPath,
+                httpMethod);
             while (it.hasNext() && resource == null) {
                 curPath = it.next();
                 resource = getResourceInternal(curPath);
@@ -347,23 +353,13 @@
 
     /**
      * Creates a JcrNodeResource with the given path if existing
-     *
+     * 
      * @throws AccessControlException If an item exists but this manager has no
      *             read access
      */
     protected Resource getResourceInternal(String path) {
 
-        Resource resource= null;
-
-        ResourceProviderEntry rp = rootProvider.getResourceProvider(path);
-        while (rp != null && resource == null) {
-            // resource provider can be null (TODO - why?)
-            if ( rp.getResourceProvider() != null ) {
-                resource = rp.getResourceProvider().getResource(path);
-            }
-            rp = rp.getParentEntry();
-        }
-
+        Resource resource = rootProvider.getResource(path);
         if (resource != null) {
             resource.getResourceMetadata().put(
                 ResourceMetadata.RESOLUTION_PATH, path);

Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java?rev=618734&r1=618733&r2=618734&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java Tue Feb  5 10:29:33 2008
@@ -22,27 +22,57 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceProvider;
 
+/**
+ * The <code>ResourceProviderEntry</code> class represents a node in the tree
+ * of resource providers spanned by the root paths of the provider resources.
+ * <p>
+ * This class is comparable to itself to help keep the child entries list sorted
+ * by their prefix.
+ */
 public class ResourceProviderEntry implements Comparable<ResourceProviderEntry> {
 
+    // the path to resources provided by the resource provider of this
+    // entry. this path is relative to the path of the parent resource
+    // provider entry and has no trailing slash.
     private final String path;
 
+    // the path to resources provided by the resource provider of this
+    // entry. this is the same path as the path field but with a trailing
+    // slash to be used as a prefix match resource paths to resolve
     private final String prefix;
 
+    // the resource provider kept in this entry supporting resources at and
+    // below the path of this entry.
     private final ResourceProvider provider;
 
-    private final ResourceProviderEntry parentEntry;
-
+    // child resource provider entries sharing the same path prefix of this
+    // entry but with more path elements.
     private ResourceProviderEntry[] entries;
 
+    /**
+     * Creates an instance of this class with the given path relative to the
+     * parent resource provider entry, encapsulating the given ResourceProvider.
+     * 
+     * @param path The relative path supported by the provider
+     * @param provider The resource provider to encapsulate by this entry.
+     */
+    public ResourceProviderEntry(String path, ResourceProvider provider) {
+        this(path, provider, null);
+    }
+
+    /**
+     * Creates an instance of this class with the given path relative to the
+     * parent resource provider entry, encapsulating the given ResourceProvider,
+     * and a number of inital child entries.
+     * 
+     * @param path The relative path supported by the provider
+     * @param provider The resource provider to encapsulate by this entry.
+     */
     public ResourceProviderEntry(String path, ResourceProvider provider,
-            ResourceProviderEntry parentEntry) {
-        this(path, provider, parentEntry, null);
-    }
-
-    public ResourceProviderEntry(String path, ResourceProvider provider,
-            ResourceProviderEntry parentEntry, ResourceProviderEntry[] entries) {
+            ResourceProviderEntry[] entries) {
         if (path.endsWith("/")) {
             this.path = path.substring(0, path.length() - 1);
             this.prefix = path;
@@ -51,33 +81,67 @@
             this.prefix = path + "/";
         }
         this.provider = provider;
-        this.parentEntry = parentEntry;
         this.entries = entries;
     }
 
-    public ResourceProviderEntry getParentEntry() {
-        return parentEntry;
-    }
-
+    /**
+     * Returns the resource provider contained in this entry
+     */
     public ResourceProvider getResourceProvider() {
         return provider;
     }
 
+    /**
+     * Returns the child resource provider entries of this entry
+     */
     public ResourceProviderEntry[] getEntries() {
         return entries;
     }
 
-    public ResourceProviderEntry getResourceProvider(String path) {
+    /**
+     * Returns the resource with the given path or <code>null</code> if
+     * neither the resource provider of this entry nor the resource provider of
+     * any of the child entries can provide the resource.
+     * 
+     * @param path The path to the resource to return.
+     * @return The resource for the path or <code>null</code> if no resource
+     *         can be found.
+     * @throws SlingException if an error occurrs trying to access an existing
+     *             resource.
+     */
+    public Resource getResource(String path) {
+        return getResource(path, path);
+    }
+
+    /**
+     * Returns the resource with the given path or <code>null</code> if
+     * neither the resource provider of this entry nor the resource provider of
+     * any of the child entries can provide the resource.
+     * <p>
+     * This method implements the {@link #getResource(String)} method
+     * recursively calling itself on any child provide entries matching the
+     * path.
+     * 
+     * @param path The path to the resource to return relative to the parent
+     *            resource provider entry, which called this method.
+     * @param fullPath The actual path to the resource as provided to the
+     *            {@link #getResource(String)} method.
+     * @return The resource for the path or <code>null</code> if no resource
+     *         can be found.
+     * @throws SlingException if an error occurrs trying to access an existing
+     *             resource.
+     */
+    private Resource getResource(String path, String fullPath) {
         if (path.equals(this.path)) {
-            return this;
-        } else if (match(path)) {
+            return getResourceProvider().getResource(fullPath);
+        } else if (path.startsWith(this.prefix)) {
             if (entries != null) {
 
                 // consider relative path for further checks
                 path = path.substring(this.prefix.length());
 
                 for (ResourceProviderEntry entry : entries) {
-                    ResourceProviderEntry test = entry.getResourceProvider(path);
+                    Resource test = entry.getResource(path, fullPath);
                     if (test != null) {
                         return test;
                     }
@@ -85,22 +149,18 @@
             }
 
             // no more specific provider, return mine
-            return this;
+            return getResourceProvider().getResource(fullPath);
         }
 
         // no match for my prefix, return null
         return null;
     }
 
-    public boolean match(String path) {
-        return path.startsWith(prefix);
-    }
-
     public boolean addResourceProvider(String prefix, ResourceProvider provider) {
         if (prefix.equals(this.path)) {
             throw new IllegalStateException(
                 "ResourceProviderEntry for prefix already exists");
-        } else if (match(prefix)) {
+        } else if (prefix.startsWith(this.prefix)) {
 
             // consider relative path for further checks
             prefix = prefix.substring(this.prefix.length());
@@ -114,7 +174,7 @@
                     } else if (entry.prefix.startsWith(prefix)
                         && entry.prefix.charAt(prefix.length()) == '/') {
                         ResourceProviderEntry newEntry = new ResourceProviderEntry(
-                            prefix, provider, this);
+                            prefix, provider);
                         newEntry.addResourceProvider(entry.path, entry.provider);
                         entries[i] = newEntry;
                         return true;
@@ -125,7 +185,7 @@
 
             // none found, so add it here
             ResourceProviderEntry entry = new ResourceProviderEntry(prefix,
-                provider, this);
+                provider);
             if (entries == null) {
                 entries = new ResourceProviderEntry[] { entry };
             } else {
@@ -145,7 +205,7 @@
     public boolean removeResourceProvider(String prefix) {
         if (prefix.equals(path)) {
             return true;
-        } else if (match(prefix)) {
+        } else if (prefix.startsWith(this.prefix)) {
             // consider relative path for further checks
             prefix = prefix.substring(this.prefix.length());
 

Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java?rev=618734&r1=618733&r2=618734&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java Tue Feb  5 10:29:33 2008
@@ -31,7 +31,7 @@
             JcrResourceResolverFactoryImpl resourceResolverFactory,
             Session session, ResourceProviderEntry[] entries) {
         super("/", new JcrResourceProvider(resourceResolverFactory, session),
-            null, entries);
+            entries);
 
         this.session = session;
     }

Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java?rev=618734&r1=618733&r2=618734&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java Tue Feb  5 10:29:33 2008
@@ -25,6 +25,7 @@
 import junit.framework.TestCase;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceProvider;
 
 public class ResourceProviderEntryTest extends TestCase {
@@ -47,14 +48,12 @@
     }
 
     public void testRootProvider() {
-        assertNull(root.getResourceProvider("relpath"));
-        assertEquals(root, root.getResourceProvider("/"));
-        assertEquals(root, root.getResourceProvider("/rootel"));
-        assertEquals(root, root.getResourceProvider("/rootel/child"));
-        assertEquals(root,
-            root.getResourceProvider("/apps/sling/sample/html.js"));
-        assertEquals(root,
-            root.getResourceProvider("/apps/sling/microsling/html.js"));
+        assertNull(root.getResource("relpath"));
+        assertEquals(root, root.getResource("/"));
+        assertEquals(root, root.getResource("/rootel"));
+        assertEquals(root, root.getResource("/rootel/child"));
+        assertEquals(root, root.getResource("/apps/sling/sample/html.js"));
+        assertEquals(root, root.getResource("/apps/sling/microsling/html.js"));
     }
 
     public void testAdd1Provider() {
@@ -62,15 +61,15 @@
         ResourceProvider first = new TestResourceProvider(firstPath);
         root.addResourceProvider(firstPath, first);
 
-        assertEquals(root, root.getResourceProvider("/"));
-        assertEquals(first, root.getResourceProvider("/rootel").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/child").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
+        assertEquals(root, root.getResource("/"));
+        assertEquals(first, root.getResource("/rootel"));
+        assertEquals(first, root.getResource("/rootel/html.js"));
+        assertEquals(first, root.getResource("/rootel/child"));
+        assertEquals(first, root.getResource("/rootel/child/html.js"));
         assertEquals(rootProvider,
-            root.getResourceProvider("/apps/sling/sample/html.js").getResourceProvider());
+            root.getResource("/apps/sling/sample/html.js"));
         assertEquals(rootProvider,
-            root.getResourceProvider("/apps/sling/microsling/html.js").getResourceProvider());
+            root.getResource("/apps/sling/microsling/html.js"));
     }
 
     public void testAdd3Providers() {
@@ -86,15 +85,14 @@
         root.addResourceProvider(secondPath, second);
         root.addResourceProvider(thirdPath, third);
 
-        assertEquals(rootProvider, root.getResourceProvider("/").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
-        assertEquals(third,
-            root.getResourceProvider("/apps/sling/sample/html.js").getResourceProvider());
+        assertEquals(rootProvider, root.getResource("/"));
+        assertEquals(first, root.getResource("/rootel"));
+        assertEquals(first, root.getResource("/rootel/html.js"));
+        assertEquals(second, root.getResource("/rootel/child"));
+        assertEquals(second, root.getResource("/rootel/child/html.js"));
+        assertEquals(third, root.getResource("/apps/sling/sample/html.js"));
         assertEquals(rootProvider,
-            root.getResourceProvider("/apps/sling/microsling/html.js").getResourceProvider());
+            root.getResource("/apps/sling/microsling/html.js"));
     }
 
     public void testAdd3ProvidersReverse() {
@@ -110,15 +108,14 @@
         root.addResourceProvider(secondPath, second);
         root.addResourceProvider(firstPath, first);
 
-        assertEquals(rootProvider, root.getResourceProvider("/").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
-        assertEquals(third,
-            root.getResourceProvider("/apps/sling/sample/html.js").getResourceProvider());
+        assertEquals(rootProvider, root.getResource("/"));
+        assertEquals(first, root.getResource("/rootel"));
+        assertEquals(first, root.getResource("/rootel/html.js"));
+        assertEquals(second, root.getResource("/rootel/child"));
+        assertEquals(second, root.getResource("/rootel/child/html.js"));
+        assertEquals(third, root.getResource("/apps/sling/sample/html.js"));
         assertEquals(rootProvider,
-            root.getResourceProvider("/apps/sling/microsling/html.js").getResourceProvider());
+            root.getResource("/apps/sling/microsling/html.js"));
     }
 
     public void testRemoveProviders() {
@@ -134,21 +131,29 @@
         root.addResourceProvider(secondPath, second);
         root.addResourceProvider(thirdPath, third);
 
-        assertEquals(rootProvider, root.getResourceProvider("/").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
+        assertEquals(rootProvider, root.getResource("/"));
+        assertEquals(first, root.getResource("/rootel/html.js"));
+        assertEquals(second, root.getResource("/rootel/child/html.js"));
 
         root.removeResourceProvider(firstPath);
 
-        assertEquals(rootProvider, root.getResourceProvider("/").getResourceProvider());
-        assertEquals(rootProvider, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
+        assertEquals(rootProvider, root.getResource("/"));
+        assertEquals(rootProvider, root.getResource("/rootel/html.js"));
+        assertEquals(second, root.getResource("/rootel/child/html.js"));
 
         root.addResourceProvider(firstPath, first);
 
-        assertEquals(rootProvider, root.getResourceProvider("/").getResourceProvider());
-        assertEquals(first, root.getResourceProvider("/rootel/html.js").getResourceProvider());
-        assertEquals(second, root.getResourceProvider("/rootel/child/html.js").getResourceProvider());
+        assertEquals(rootProvider, root.getResource("/"));
+        assertEquals(first, root.getResource("/rootel/html.js"));
+        assertEquals(second, root.getResource("/rootel/child/html.js"));
+    }
+
+    protected void assertEquals(ResourceProvider resProvider, Resource res) {
+        assertEquals(resProvider, res.getResourceProvider());
+    }
+    
+    protected void assertEquals(ResourceProviderEntry resProviderEntry, Resource res) {
+        assertEquals(resProviderEntry.getResourceProvider(), res.getResourceProvider());
     }
 
     private static class TestResourceProvider implements ResourceProvider {
@@ -164,7 +169,7 @@
         }
 
         public Resource getResource(String path) {
-            return null;
+            return new TestResource(path, this);
         }
 
         public String[] getRoots() {
@@ -174,5 +179,37 @@
         public Iterator<Resource> listChildren(Resource parent) {
             return null;
         }
+    }
+    
+    private static class TestResource implements Resource {
+
+        private final String path;
+        private final ResourceProvider resourceProvider;
+
+        public TestResource(String path, ResourceProvider resourceProvider) {
+            this.path = path;
+            this.resourceProvider = resourceProvider;
+        }
+        
+        public String getPath() {
+            return path;
+        }
+
+        public ResourceMetadata getResourceMetadata() {
+            return null;
+        }
+
+        public ResourceProvider getResourceProvider() {
+            return resourceProvider;
+        }
+
+        public String getResourceType() {
+            return null;
+        }
+
+        public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+            return null;
+        }
+        
     }
 }