You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2015/10/29 13:57:45 UTC

svn commit: r1711242 - /sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java

Author: cziegeler
Date: Thu Oct 29 12:57:45 2015
New Revision: 1711242

URL: http://svn.apache.org/viewvc?rev=1711242&view=rev
Log:
SLING-5201 : Improve resource provider resolving

Modified:
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java?rev=1711242&r1=1711241&r2=1711242&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java Thu Oct 29 12:57:45 2015
@@ -18,8 +18,6 @@
  */
 package org.apache.sling.resourceresolver.impl.providers.stateful;
 
-import static org.apache.commons.collections.IteratorUtils.chainedIterator;
-import static org.apache.commons.collections.IteratorUtils.transformedIterator;
 import static org.apache.sling.api.resource.ResourceUtil.getName;
 import static org.apache.sling.spi.resource.provider.ResourceProvider.RESOURCE_TYPE_SYNTHETIC;
 
@@ -27,8 +25,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -41,6 +39,7 @@ import javax.annotation.Nonnull;
 import org.apache.commons.collections.IteratorUtils;
 import org.apache.commons.collections.ListUtils;
 import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.iterators.IteratorChain;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.resource.LoginException;
@@ -199,6 +198,12 @@ public class CombinedResourceProvider {
     @SuppressWarnings("unchecked")
     public Iterator<Resource> listChildren(final Resource parent) {
         final String parentPath = parent.getPath();
+
+        // 3 sources are combined: children of the provider which owns 'parent',
+        // providers which are directly mounted at a child path,
+        // synthetic resources for providers mounted at a lower level
+
+        // children of the 'parent' provider
         Iterator<Resource> realChildren = null;
         try {
             final StatefulResourceProvider provider = this.getBestMatchingProvider(parentPath);
@@ -206,53 +211,51 @@ public class CombinedResourceProvider {
         } catch ( final LoginException le ) {
             // ignore, realChildren will be null
         }
-        Iterator<Resource> syntheticChildren = getSyntheticChildren(parent);
-        Iterator<Resource> allChildren;
-        if (realChildren == null) {
-            allChildren = syntheticChildren;
-        } else if ( syntheticChildren == null ) {
-            allChildren = realChildren;
-        } else {
-            allChildren = new UniqueIterator(chainedIterator(realChildren, syntheticChildren));
-        }
-        if ( allChildren == null ) {
-            return Collections.EMPTY_LIST.iterator();
+
+        final Set<String> visitedNames = new HashSet<String>();
+
+        IteratorChain chain = new IteratorChain();
+        if ( realChildren != null ) {
+            chain.addIterator(realChildren);
         }
-        return transformedIterator(allChildren, new Transformer() {
-            @Override
-            public Object transform(Object input) {
-                Resource resource = (Resource) input;
-                resource.getResourceMetadata().setResolutionPath(resource.getPath());
-                return resource;
-            }
-        });
-    }
 
-    private Iterator<Resource> getSyntheticChildren(final Resource parent) {
+        // synthetic and providers are done in one loop
         final Node<ResourceProviderHandler> node = storage.getTree().getNode(parent.getPath());
-        if (node == null) {
-            return null;
-        }
-        final List<Resource> children = new ArrayList<Resource>();
-        for (Entry<String, Node<ResourceProviderHandler>> entry : node.getChildren().entrySet()) {
-            final String name = entry.getKey();
-            final ResourceProviderHandler handler = entry.getValue().getValue();
-            final String childPath = new StringBuilder(parent.getPath()).append('/').append(name).toString();
-            Resource child = null;
-            if (handler == null) {
-                child = new SyntheticResource(resolver, childPath, RESOURCE_TYPE_SYNTHETIC);
-            } else {
-                try {
-                    child = authenticator.getStateful(handler, this).getResource(childPath, parent, null, false);
-                } catch ( final LoginException ignore) {
-                    // ignore this
+        if (node != null) {
+            final List<Resource> syntheticList = new ArrayList<Resource>();
+            final List<Resource> providerList = new ArrayList<Resource>();
+
+            for (final Entry<String, Node<ResourceProviderHandler>> entry : node.getChildren().entrySet()) {
+                final String name = entry.getKey();
+                final ResourceProviderHandler handler = entry.getValue().getValue();
+                final String childPath = new StringBuilder(parent.getPath()).append('/').append(name).toString();
+                if (handler == null) {
+                    syntheticList.add(new SyntheticResource(resolver, childPath, RESOURCE_TYPE_SYNTHETIC));
+                } else {
+                    try {
+                        providerList.add(authenticator.getStateful(handler, this).getResource(childPath, parent, null, false));
+                    } catch ( final LoginException ignore) {
+                        // if there is a child provider underneath, we need to create a synthetic resource
+                        // otherwise we need to make sure that no one else is providing this child
+                        if ( entry.getValue().getChildren().isEmpty() ) {
+                            syntheticList.add(new SyntheticResource(resolver, childPath, RESOURCE_TYPE_SYNTHETIC));
+                        } else {
+                            visitedNames.add(name);
+                        }
+                    }
                 }
             }
-            if (child != null) {
-                children.add(child);
+            if ( !providerList.isEmpty() ) {
+                chain.addIterator(providerList.iterator());
             }
+            if ( !syntheticList.isEmpty() ) {
+                chain.addIterator(syntheticList.iterator());
+            }
+        }
+        if ( chain.size() == 0 ) {
+            return Collections.EMPTY_LIST.iterator();
         }
-        return children.isEmpty() ? null : children.iterator();
+        return new UniqueIterator(visitedNames, chain);
     }
 
     /**
@@ -599,41 +602,28 @@ public class CombinedResourceProvider {
 
         private final Iterator<Resource> input;
 
-        private final List<String> visited;
-
-        private final Map<String, Resource> delayed;
-
-        private Iterator<Resource> delayedIterator;
+        private final Set<String> visited;
 
-        public UniqueIterator(Iterator<Resource> input) {
+        public UniqueIterator(Set<String> visited, final Iterator<Resource> input) {
             this.input = input;
-            this.visited = new ArrayList<String>();
-            this.delayed = new LinkedHashMap<String, Resource>();
+            this.visited = visited;
         }
 
         @Override
         protected Resource seek() {
             while (input.hasNext()) {
-                Resource next = input.next();
-                String path = next.getPath();
+                final Resource next = input.next();
+                final String name = next.getPath();
 
-                if (visited.contains(path)) {
+                if (visited.contains(name)) {
                     continue;
-                } else if (next instanceof SyntheticResource) {
-                    delayed.put(path, next);
                 } else {
-                    visited.add(path);
-                    delayed.remove(path);
+                    visited.add(name);
+                    next.getResourceMetadata().setResolutionPath(next.getPath());
                     return next;
                 }
             }
 
-            if (delayedIterator == null) {
-                delayedIterator = delayed.values().iterator();
-            }
-            if (delayedIterator.hasNext()) {
-                return delayedIterator.next();
-            }
             return null;
         }
     }