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<Resource></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];