Author: fmeschbe
Date: Sun Aug 29 19:02:16 2010
New Revision: 990628

URL: http://svn.apache.org/viewvc?rev=990628&view=rev
Log:
SLING-1672 Create a new ResourceIterator class from the internal class of the 
ResourceProviderEntry.listChildren method. This class is now directly created 
from the JcrResourceResolver.listChildren method. The 
ResourceProviderEntry.listChildren method is removed.

Added:
    
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
   (with props)
Modified:
    
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
    
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java

Modified: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java?rev=990628&r1=990627&r2=990628&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
 (original)
+++ 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
 Sun Aug 29 19:02:16 2010
@@ -55,6 +55,7 @@ import org.apache.sling.jcr.resource.Jcr
 import org.apache.sling.jcr.resource.JcrResourceUtil;
 import org.apache.sling.jcr.resource.internal.helper.MapEntry;
 import org.apache.sling.jcr.resource.internal.helper.RedirectResource;
+import org.apache.sling.jcr.resource.internal.helper.ResourceIterator;
 import org.apache.sling.jcr.resource.internal.helper.ResourcePathIterator;
 import org.apache.sling.jcr.resource.internal.helper.URI;
 import org.apache.sling.jcr.resource.internal.helper.URIException;
@@ -816,8 +817,9 @@ public class JcrResourceResolver
             workspacePrefix = getSession().getWorkspace().getName();
         }
 
-        return new 
ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(), 
workspacePrefix,
-                rootProvider.listChildren(parent));
+        return new ResourceIteratorDecorator(
+            this.factory.getResourceDecoratorTracker(), workspacePrefix,
+            new ResourceIterator(parent, rootProvider));
     }
 
     // ---------- Querying resources

Added: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java?rev=990628&view=auto
==============================================================================
--- 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
 (added)
+++ 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
 Sun Aug 29 19:02:16 2010
@@ -0,0 +1,294 @@
+/*
+ * 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.jcr.resource.internal.helper;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>ResourceIterator</code> implements the
+ * <code>Iterator&lt;Resource&gt;</code> returned from the
+ * <code>ResourceResolver.listChidlren(Resource)</code> method.
+ * <p>
+ * Note: This iterator is created by the
+ * <code>JcrResourceResolver.listChildren(Resource)</code> and is not intended
+ * for general use by any other code. This class uses internal API of the
+ * {...@link ResourceProviderEntry} class.
+ */
+public class ResourceIterator implements Iterator<Resource> {
+
+    /** default log */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * The resource whose children are listed
+     */
+    private final Resource parentResource;
+
+    /**
+     * The root {...@link ResourceProviderEntry} used to walk down the resource
+     * tree to collect entries which might provide children for the
+     * {...@link #parentResource}.
+     */
+    private final ResourceProviderEntry rootProviderEntry;
+
+    /**
+     * <code>ResourceProvider</code> objects registered as nodes above the
+     * {...@link #parentResource} up to the root of the resource tree
+     */
+    private final Iterator<ResourceProvider> providers;
+
+    /**
+     * The child {...@link ResourceProviderEntry} registered at the node of the
+     * {...@link #parentResource} in the resource tree. This may be
+     * <code>null</code> if there is no provider entry registered at that
+     * location and will be set to <code>null</code> once all entries have been
+     * processed.
+     */
+    private Iterator<ResourceProviderEntry> baseEntryValues;
+
+    /**
+     * An iterator of child resources provided by the current provider entry of
+     * the {...@link #providers} iterator.
+     */
+    private Iterator<Resource> resources;
+
+    /**
+     * The next resource to be returned from the {...@link #next()} method. If 
this
+     * is <code>null</code> the {...@link #hasNext()} returns 
<code>false</code>.
+     */
+    private Resource nextResource;
+
+    /**
+     * Map of synthetic resources returned from resource providers while
+     * scanning for children of the {...@link #parentResource}. These delayed
+     * entries are returned after all non-synthetic resources have been
+     * returned. Any delayed entry whose path matches the path of a
+     * non-synthetic resource will not returned.
+     */
+    private Map<String, Resource> delayed;
+
+    /**
+     * Set of paths of resources already returned. This is used to prevent
+     * duplicate return of resources.
+     */
+    private Set<String> visited;
+
+    /**
+     * The absolute path prefix of the {...@link #parentResource} resource 
with a
+     * trailing slash to build the absolute path of child resources.
+     */
+    private String iteratorPath;
+
+    /**
+     * Iterator on the map of {...@link #delayed} synthetic resources
+     */
+    private Iterator<Resource> delayedIter;
+
+    public ResourceIterator(final Resource parentResource,
+            final ResourceProviderEntry rootProviderEntry) {
+        this.parentResource = parentResource;
+        this.rootProviderEntry = rootProviderEntry;
+
+        log.debug("Child Iterator for {}", parentResource.getPath());
+
+        String path = parentResource.getPath();
+        if (!path.endsWith("/")) {
+            path += "/";
+        }
+
+        // gather the providers in linked set, such that we keep
+        // the order of addition and make sure we only get one entry
+        // for each resource provider
+        Set<ResourceProvider> providersSet = new 
LinkedHashSet<ResourceProvider>();
+        ResourceProviderEntry atPath = getResourceProviders(path, 
providersSet);
+
+        if (log.isDebugEnabled()) {
+            log.debug(" Provider Set for path {} {} ", path,
+                Arrays.toString(providersSet.toArray(new 
ResourceProvider[0])));
+        }
+        this.iteratorPath = path;
+        providers = providersSet.iterator();
+        baseEntryValues = (atPath != null) ? atPath.values().iterator() : null;
+        delayed = new HashMap<String, Resource>();
+        visited = new HashSet<String>();
+        nextResource = seek();
+    }
+
+    public boolean hasNext() {
+        return nextResource != null;
+    }
+
+    public Resource next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+
+        Resource result = nextResource;
+        nextResource = seek();
+        log.debug("  Child Resoruce [{}] [{}] ", iteratorPath, 
result.getPath());
+        return result;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("remove");
+    }
+
+    private Resource seek() {
+        while (delayedIter == null) {
+            while ((resources == null || !resources.hasNext())
+                && providers.hasNext()) {
+                ResourceProvider provider = providers.next();
+                resources = provider.listChildren(parentResource);
+                log.debug("     Checking Provider {} ", provider);
+            }
+
+            if (resources != null && resources.hasNext()) {
+                Resource res = resources.next();
+                String resPath = res.getPath();
+
+                if (visited.contains(resPath)) {
+
+                    // ignore a path, we have already visited and
+                    // ensure it will not be listed as a delayed
+                    // resource at the end
+                    delayed.remove(resPath);
+
+                } else if (res instanceof SyntheticResource) {
+
+                    // don't return synthetic resources right away,
+                    // since a concrete resource for the same path
+                    // may be provided later on
+                    delayed.put(resPath, res);
+
+                } else {
+
+                    // we use this concrete, unvisited resource but
+                    // mark it as visited and remove from delayed
+                    visited.add(resPath);
+                    delayed.remove(resPath);
+                    log.debug("      resource {} {}", resPath, res.getClass());
+                    return res;
+
+                }
+
+            } else if (baseEntryValues != null) {
+
+                while (baseEntryValues.hasNext()) {
+                    final ResourceProviderEntry rpw = baseEntryValues.next();
+                    final String resPath = iteratorPath + rpw.getPath();
+                    if (!visited.contains(resPath)) {
+                        final ResourceResolver rr = 
parentResource.getResourceResolver();
+                        final Resource res = rpw.getResourceFromProviders(rr,
+                            resPath);
+                        if (res == null) {
+                            if (!delayed.containsKey(resPath)) {
+                                delayed.put(resPath, new SyntheticResource(rr,
+                                    resPath,
+                                    ResourceProvider.RESOURCE_TYPE_SYNTHETIC));
+                            }
+                        } else {
+                            // return the real resource immediately, add
+                            // to the visited keys and ensure delayed
+                            // does not contain it
+                            delayed.remove(resPath);
+                            visited.add(resPath);
+                            log.debug("   B  resource {} {}", resPath,
+                                res.getClass());
+                            return res;
+                        }
+                    }
+                }
+
+                baseEntryValues = null;
+
+            } else {
+
+                // all resource providers and baseEntryValues have
+                // exhausted, so we should continue returning the
+                // delayed (synthetic resources)
+                delayedIter = delayed.values().iterator();
+            }
+        }
+
+        // we exhausted all resource providers with their concrete
+        // resources. now lets do the delayed (synthetic) resources
+        Resource res = delayedIter.hasNext() ? delayedIter.next() : null;
+        if (res != null) {
+            log.debug("   D  resource {} {}", res.getPath(), res.getClass());
+        }
+        return res;
+    }
+
+    /**
+     * Returns all resource providers which provider resources whose prefix is
+     * the given path.
+     *
+     * @param path The prefix path to match the resource provider roots against
+     * @param providers The set of already found resource providers to which 
any
+     *            additional resource providers are added.
+     * @return The ResourceProviderEntry at the node identified with the path 
or
+     *         <code>null</code> if there is no entry at the given location
+     */
+    private ResourceProviderEntry getResourceProviders(String path,
+            Set<ResourceProvider> providers) {
+
+        // collect providers along the ancestor path segements
+        String[] elements = ResourceProviderEntry.split(path, '/');
+        ResourceProviderEntry base = rootProviderEntry;
+        for (String element : elements) {
+            if (base.containsKey(element)) {
+                base = base.get(element);
+                if (log.isDebugEnabled()) {
+                    log.debug("Loading from {}  {} ", element,
+                        base.getResourceProviders().length);
+                }
+                for (ResourceProvider rp : base.getResourceProviders()) {
+                    log.debug("Adding {} for {} ", rp, path);
+                    providers.add(rp);
+                }
+            } else {
+                log.debug("No container for {} ", element);
+                base = null;
+                break;
+            }
+        }
+
+        // add in providers at this node in the tree, ie the root provider
+        for (ResourceProvider rp : rootProviderEntry.getResourceProviders()) {
+            log.debug("Loading All at {} ", path);
+            providers.add(rp);
+        }
+        return base;
+    }
+
+}

Propchange: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java?rev=990628&r1=990627&r2=990628&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java
 (original)
+++ 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java
 Sun Aug 29 19:02:16 2010
@@ -23,13 +23,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Set;
 
 import org.apache.commons.collections.FastTreeMap;
@@ -117,6 +112,10 @@ public class ResourceProviderEntry imple
 
     }
 
+    String getPath() {
+        return path;
+    }
+
     /**
      * Returns the resource provider contained in this entry
      */
@@ -140,123 +139,6 @@ public class ResourceProviderEntry imple
         return getInternalResource(resourceResolver, path);
     }
 
-    public Iterator<Resource> listChildren(final Resource resource) {
-        LOGGER.debug("Child Iterator for {}",resource.getPath());
-        return new Iterator<Resource>() {
-            private final Iterator<ResourceProvider> providers;
-
-            private Iterator<Resource> resources;
-
-            private Resource nextResource;
-
-            private Map<String, Resource> delayed;
-
-            private Set<String> visited;
-
-            private String iteratorPath;
-
-            private Iterator<Resource> delayedIter;
-
-            {
-                String path = resource.getPath();
-                if (!path.endsWith("/")) {
-                    path += "/";
-                }
-
-                // gather the providers in linked set, such that we keep
-                // the order of addition and make sure we only get one entry
-                // for each resource provider
-                Set<ResourceProvider> providersSet = new 
LinkedHashSet<ResourceProvider>();
-                getResourceProviders(path, providersSet);
-
-                if ( LOGGER.isDebugEnabled()) {
-                    LOGGER.debug(" Provider Set for path {} {} 
",path,Arrays.toString(providersSet.toArray(new ResourceProvider[0])));
-                }
-                this.iteratorPath = path;
-                providers = providersSet.iterator();
-                delayed = new HashMap<String, Resource>();
-                visited = new HashSet<String>();
-                nextResource = seek();
-            }
-
-            public boolean hasNext() {
-                return nextResource != null;
-            }
-
-            public Resource next() {
-                if (!hasNext()) {
-                    throw new NoSuchElementException();
-                }
-
-                Resource result = nextResource;
-                nextResource = seek();
-                LOGGER.debug("  Child Resoruce [{}] [{}] ", iteratorPath, 
result.getPath());
-                return result;
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException("remove");
-            }
-
-            private Resource seek() {
-                for (;;) {
-                    while ((resources == null || !resources.hasNext())
-                            && providers.hasNext()) {
-                        ResourceProvider provider = providers.next();
-                        resources = provider.listChildren(resource);
-                        LOGGER.debug("     Checking Provider {} ", provider);
-                    }
-
-                    if (resources != null && resources.hasNext()) {
-                        Resource res = resources.next();
-                        String resPath = res.getPath();
-
-                        if (visited.contains(resPath)) {
-
-                            // ignore a path, we have already visited and
-                            // ensure it will not be listed as a delayed
-                            // resource at the end
-                            delayed.remove(resPath);
-
-                        } else if (res instanceof SyntheticResource) {
-
-                            // don't return synthetic resources right away,
-                            // since a concrete resource for the same path
-                            // may be provided later on
-                            delayed.put(resPath, res);
-
-                        } else {
-
-                            // we use this concrete, unvisited resource but
-                            // mark it as visited
-                            visited.add(resPath);
-                            // also remove it from delayed if it was there.
-                            if ( delayed.containsKey(resPath) ) {
-                                delayed.remove(resPath);
-                            }
-                            LOGGER.debug("      resource {} {}", resPath, 
res.getClass());
-                            return res;
-
-                        }
-                    } else {
-                        break;
-                    }
-                }
-
-                // we exhausted all resource providers with their concrete
-                // resources. now lets do the delayed (synthetic) resources
-                if (delayedIter == null) {
-                    delayedIter = delayed.values().iterator();
-                }
-                Resource res = delayedIter.hasNext() ? delayedIter.next() : 
null;
-                if ( res != null ) {
-                    LOGGER.debug("   D  resource {} {}", res.getPath(), 
res.getClass());
-                }
-                return res;
-            }
-        };
-    }
-
     /**
      * Adds the given resource provider into the tree for the given prefix.
      *
@@ -460,14 +342,10 @@ public class ResourceProviderEntry imple
             }
 
             // resolve against this one
-            ResourceProvider[] rps = getResourceProviders();
-            for (ResourceProvider rp : rps) {
-                Resource resource = rp.getResource(resourceResolver, fullPath);
-                if (resource != null) {
-                    nreal++;
-                    LOGGER.debug("Resolved Base {} using {} ", fullPath, rp);
-                    return resource;
-                }
+            final Resource resource = getResourceFromProviders(
+                resourceResolver, fullPath);
+            if (resource != null) {
+                return resource;
             }
 
             // query: /libs/sling/servlet/default
@@ -497,65 +375,18 @@ public class ResourceProviderEntry imple
         }
     }
 
-
-    /**
-     * Returns all resource providers which provider resources whose prefix is
-     * the given path.
-     *
-     * @param path
-     *            The prefix path to match the resource provider roots against
-     * @param providers
-     *            The set of already found resource providers to which any
-     *            additional resource providers are added.
-     */
-    private void getResourceProviders(String path,
-            Set<ResourceProvider> providers) {
-        String[] elements = split(path, '/');
-        ResourceProviderEntry base = this;
-        for (String element : elements ) {
-            if ( base.containsKey(element)) {
-                base = base.get(element);
-                if ( LOGGER.isDebugEnabled() ) {
-                    LOGGER.debug("Loading from {}  {} ", element, 
base.getResourceProviders().length );
-                }
-                for ( ResourceProvider rp : base.getResourceProviders() ) {
-                    LOGGER.debug("Adding {} for {} ",rp,path);
-                    providers.add(rp);
-                }
-            } else {
-                LOGGER.debug("No container for {} ", element );
-                base = null;
-                break;
+    Resource getResourceFromProviders(final ResourceResolver resourceResolver,
+            final String fullPath) {
+        ResourceProvider[] rps = getResourceProviders();
+        for (ResourceProvider rp : rps) {
+            Resource resource = rp.getResource(resourceResolver, fullPath);
+            if (resource != null) {
+                nreal++;
+                LOGGER.debug("Resolved Base {} using {} ", fullPath, rp);
+                return resource;
             }
         }
-        // the path has been exausted and there is a subtree to be collected, 
so go and collect it.
-        if ( base != null ) {
-            LOGGER.debug("Loading All below {} ", base.path );
-            getResourceProviders(base, providers);
-        }
-        // add in providers at this node in the tree, ie the root provider
-        for ( ResourceProvider rp : getResourceProviders() ) {
-            LOGGER.debug("Loading All at {} ", path );
-            providers.add(rp);
-        }
-
-    }
-
-    /**
-     * @param base
-     * @param providers2
-     */
-    private void getResourceProviders(ResourceProviderEntry entry,
-            Set<ResourceProvider> providers) {
-        // recurse down the tree
-        LOGGER.debug(" Gathering For {} ",entry.prefix);
-        for ( ResourceProviderEntry e : entry.values() ) {
-            getResourceProviders(e, providers);
-        }
-        // add in providers at this node in the tree.
-        for ( ResourceProvider rp : entry.getResourceProviders() ) {
-            providers.add(rp);
-        }
+        return null;
     }
 
     /**
@@ -563,7 +394,7 @@ public class ResourceProviderEntry imple
      * @param sep
      * @return an array of the strings between the separator
      */
-    private String[] split(String st, char sep) {
+    static String[] split(String st, char sep) {
 
         if (st == null) {
             return new String[0];


Reply via email to