Return-Path: Delivered-To: apmail-sling-commits-archive@www.apache.org Received: (qmail 44597 invoked from network); 6 Nov 2009 02:20:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 6 Nov 2009 02:20:25 -0000 Received: (qmail 88752 invoked by uid 500); 6 Nov 2009 02:20:25 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 88696 invoked by uid 500); 6 Nov 2009 02:20:25 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 88687 invoked by uid 99); 6 Nov 2009 02:20:25 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 06 Nov 2009 02:20:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 06 Nov 2009 02:20:20 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 011A223888E8; Fri, 6 Nov 2009 02:19:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r833278 - in /sling/trunk: bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/ bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ bundles/jcr/resource/src/main/java/org/apache/sling/jcr/... Date: Fri, 06 Nov 2009 02:19:56 -0000 To: commits@sling.apache.org From: ieb@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091106021957.011A223888E8@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: ieb Date: Fri Nov 6 02:19:55 2009 New Revision: 833278 URL: http://svn.apache.org/viewvc?rev=833278&view=rev Log: SLING-1156 Merged New resource resolver into the trunk build, will remove the contrib project next. Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java (with props) sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java (with props) Removed: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryException.java Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java sling/trunk/contrib/jcr/resource2/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java?rev=833278&r1=833277&r2=833278&view=diff ============================================================================== --- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java (original) +++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java Fri Nov 6 02:19:55 2009 @@ -42,8 +42,7 @@ import org.apache.sling.jcr.resource.JcrResourceTypeProvider; import org.apache.sling.jcr.resource.internal.helper.MapEntries; import org.apache.sling.jcr.resource.internal.helper.Mapping; -import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry; -import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntryException; +import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2; import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; @@ -194,7 +193,7 @@ // the search path for ResourceResolver.getResource(String) private String[] searchPath; - private ResourceProviderEntry rootProviderEntry; + private ResourceProviderEntry2 rootProviderEntry; // whether to mangle paths with namespaces or not private boolean mangleNamespacePrefixes; @@ -211,7 +210,8 @@ private DynamicClassLoaderManager dynamicClassLoaderManager; public JcrResourceResolverFactoryImpl() { - this.rootProviderEntry = new ResourceProviderEntry("/", null, null); + this.rootProviderEntry = new ResourceProviderEntry2("/", null); + } // ---------- JcrResourceResolverFactory ----------------------------------- @@ -223,7 +223,7 @@ public ResourceResolver getResourceResolver(Session session) { JcrResourceProviderEntry sessionRoot = new JcrResourceProviderEntry( session, rootProviderEntry, getJcrResourceTypeProviders(), - this.getDynamicClassLoader()); + this.getDynamicClassLoader()); return new JcrResourceResolver2(sessionRoot, this, mapEntries); } @@ -288,7 +288,7 @@ * * @return Our rootProviderEntry */ - protected ResourceProviderEntry getRootProviderEntry() { + protected ResourceProviderEntry2 getRootProviderEntry() { return rootProviderEntry; } @@ -480,23 +480,16 @@ root = root.substring(0, root.length() - 1); } - try { - rootProviderEntry.addResourceProvider(root, - provider); - - log.debug("bindResourceProvider: {}={} ({})", - new Object[] { root, provider, serviceName }); - if ( localEA != null ) { - final Dictionary props = new Hashtable(); - props.put(SlingConstants.PROPERTY_PATH, root); - localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED, - props)); - } - } catch (ResourceProviderEntryException rpee) { - log.error( - "bindResourceProvider: Cannot register ResourceProvider {} for {}: ResourceProvider {} is already registered", - new Object[] { provider, root, - rpee.getExisting().getResourceProvider() }); + rootProviderEntry.addResourceProvider(root, + provider, reference); + + log.debug("bindResourceProvider: {}={} ({})", + new Object[] { root, provider, serviceName }); + if ( localEA != null ) { + final Dictionary props = new Hashtable(); + props.put(SlingConstants.PROPERTY_PATH, root); + localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED, + props)); } } } @@ -520,6 +513,10 @@ // synchronized insertion of new resource providers into // the tree to not inadvertently loose an entry synchronized (this) { + if ( componentContext != null ) { + ResourceProvider provider = (ResourceProvider) componentContext.locateService( + "ResourceProvider", reference); + for (String root : roots) { // cut off trailing slash @@ -530,7 +527,7 @@ // TODO: Do not remove this path, if another resource // owns it. This may be the case if adding the provider // yielded an ResourceProviderEntryException - rootProviderEntry.removeResourceProvider(root); + rootProviderEntry.removeResourceProvider(root, provider, reference); log.debug("unbindResourceProvider: root={} ({})", root, serviceName); @@ -541,6 +538,7 @@ props)); } } + } } } @@ -626,4 +624,12 @@ return null; } + + + public void run() { + String stat = rootProviderEntry.getResolutionStats(); + if ( stat != null ) { + log.info(stat); + } + } } Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java?rev=833278&view=auto ============================================================================== --- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java (added) +++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java Fri Nov 6 02:19:55 2009 @@ -0,0 +1,627 @@ +/* + * 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 org.apache.commons.collections.FastTreeMap; +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; + +import java.util.ArrayList; +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; + +/** + * The ResourceProviderEntry class represents a node in the tree of + * resource providers spanned by the root paths of the provider resources. + *

+ * This class is comparable to itself to help keep the child entries list sorted + * by their prefix. + */ +public class ResourceProviderEntry2 implements + Comparable { + + /** + * + */ + private static final long serialVersionUID = 7420631325909144862L; + + private static Logger LOGGER = LoggerFactory.getLogger(ResourceProviderEntry2.class); + + // 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 WrappedResourceProvider[] providers = new WrappedResourceProvider[0]; + + private long ttime = 0L; + + private long nmiss = 0L; + + private long nsynthetic = 0L; + + private long nreal = 0L; + + private FastTreeMap storageMap = new FastTreeMap(); + + /** + * 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 ResourceProviderEntry2(String path, ResourceProvider[] providerList) { + if (path.endsWith("/")) { + this.path = path.substring(0, path.length() - 1); + this.prefix = path; + } else { + this.path = path; + this.prefix = path + "/"; + } + if ( providerList != null ) { + providers = new WrappedResourceProvider[providerList.length]; + for ( int i = 0; i < providerList.length; i++ ) { + if ( providerList[i] instanceof WrappedResourceProvider ) { + providers[i] = (WrappedResourceProvider) providerList[i]; + } else { + providers[i] = new WrappedResourceProvider(providerList[i], null); + } + } + } + + // this will consume slightly more memory but ensures read is fast. + storageMap.setFast(true); + } + + /** + * Returns the resource provider contained in this entry + */ + public ResourceProvider[] getResourceProviders() { + return providers; + } + + /** + * Returns the resource with the given path or null 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 null if no resource can + * be found. + * @throws org.apache.sling.api.SlingException + * if an error occurrs trying to access an existing resource. + */ + public Resource getResource(ResourceResolver resourceResolver, String path) { + return getInternalResource(resourceResolver, path); + } + + public Iterator listChildren(final Resource resource) { + LOGGER.debug("Child Iterator for {}",resource.getPath()); + return new Iterator() { + private final Iterator providers; + + private Iterator resources; + + private Resource nextResource; + + private Map delayed; + + private Set visited; + + private Iterator 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 providersSet = new LinkedHashSet(); + getResourceProviders(path, providersSet); + + LOGGER.debug(" Provider Set for path {} {} ",path,Arrays.toString(providersSet.toArray(new ResourceProvider[0]))); + + providers = providersSet.iterator(); + delayed = new HashMap(); + visited = new HashSet(); + 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 {} ", 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(); + LOGGER.debug(" resource {} ", 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); + 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()); + } + return res; + } + }; + } + + /** + * Adds the given resource provider into the tree for the given prefix. + * + * @return true if the provider could be entered into the + * subtree below this entry. Otherwise false is + * returned. + */ + public boolean addResourceProvider(String prefix, ResourceProvider provider, Comparable comparable) { + synchronized (this) { + String[] elements = split(prefix, '/'); + List entryPath = new ArrayList(); + entryPath.add(this); // add this the start so if the list is empty we have a position to add to + populateProviderPath(entryPath, elements); + for (int i = entryPath.size() - 1; i < elements.length; i++) { + String stubPrefix = elements[i]; + ResourceProviderEntry2 rpe2 = new ResourceProviderEntry2( + stubPrefix, new ResourceProvider[0]); + entryPath.get(i).put(elements[i], rpe2); + entryPath.add(rpe2); + } + return entryPath.get(elements.length).addInternalProvider(new WrappedResourceProvider(provider, comparable)); + + } + } + + + //------------------ Map methods, here so that we can delegate 2 maps together + /** + * @param string + * @param rpe2 + */ + public void put(String key, ResourceProviderEntry2 value) { + storageMap.put(key,value); + } + + /** + * @param element + * @return + */ + public boolean containsKey(String key) { + return storageMap.containsKey(key); + } + + + /** + * @param element + * @return + */ + public ResourceProviderEntry2 get(String key) { + return (ResourceProviderEntry2) storageMap.get(key); + } + + /** + * @return + */ + @SuppressWarnings("unchecked") + public Collection values() { + return storageMap.values(); + } + + public boolean removeResourceProvider(String prefix, + ResourceProvider resourceProvider, Comparable comparable) { + synchronized (this) { + String[] elements = split(prefix, '/'); + List entryPath = new ArrayList(); + populateProviderPath(entryPath, elements); + if (entryPath.size() == elements.length) { + // the last element is a perfect match; + return entryPath.get(entryPath.size()-1).removeInternalProvider(new WrappedResourceProvider(resourceProvider, comparable)); + } + return false; + } + } + + // ---------- Comparable interface ------------------ + + public int compareTo(ResourceProviderEntry2 o) { + return prefix.compareTo(o.prefix); + } + + // ---------- internal ----------------------------------------------------- + + /** + * Adds a list of providers to this entry. + * + * @param provider + */ + private boolean addInternalProvider(WrappedResourceProvider provider) { + synchronized (providers) { + int before = providers.length; + Set set = new HashSet(); + if (providers != null) { + set.addAll(Arrays.asList(providers)); + } + set.add(provider); + providers = conditionalSort(set); + return providers.length > before; + } + + } + + /** + * @param provider + * @return + */ + private boolean removeInternalProvider(WrappedResourceProvider provider) { + synchronized (providers) { + int before = providers.length; + Set set = new HashSet(); + if (providers != null) { + set.addAll(Arrays.asList(providers)); + } + set.remove(provider); + providers = conditionalSort(set); + return providers.length < before; + } + } + + /** + * @param set + * @return + */ + private WrappedResourceProvider[] conditionalSort(Set set) { + + List providerList = new ArrayList( + set); + + Collections.sort(providerList, new Comparator() { + + @SuppressWarnings("unchecked") + public int compare(WrappedResourceProvider o1, WrappedResourceProvider o2) { + Comparable c1 = o1.getComparable(); + Comparable c2 = o2.getComparable(); + if ( c1 == null && c2 == null ) { + return 0; + } + if ( c1 == null ) { + return -1; + } + if ( c2 == null ) { + return 1; + } + return c1.compareTo(c2); + } + }); + + return set.toArray(new WrappedResourceProvider[set.size()]); + } + + /** + * Get a of ResourceProvidersEntries leading to the fullPath in reverse + * order. + * + * @param fullPath + * the full path + * @return a reverse order list of ProviderEntries to the path. + */ + private void populateProviderPath( + List providerEntryPath, String[] elements) { + ResourceProviderEntry2 base = this; + if (elements != null) { + for (String element : elements) { + if (element != null) { + if (base.containsKey(element)) { + base = base.get(element); + providerEntryPath.add(base); + } else { + break; + } + } + } + } + } + + + /** + * Resolve a resource from a path into a Resource + * + * @param resolver + * the ResourceResolver. + * @param fullPath + * the Full path + * @return null if no resource was found, a resource if one was found. + */ + private Resource getInternalResource(ResourceResolver resourceResolver, + String fullPath) { + long start = System.currentTimeMillis(); + try { + + if (fullPath == null || fullPath.length() == 0 + || fullPath.charAt(0) != '/') { + nmiss++; + LOGGER.debug("Not absolute {} :{}",fullPath,(System.currentTimeMillis() - start)); + return null; // fullpath must be absolute + } + String[] elements = split(fullPath, '/'); + + List list = new ArrayList(); + populateProviderPath(list, elements); + // the path is in reverse order end first + + for(int i = list.size()-1; i >= 0; i--) { + ResourceProvider[] rps = list.get(i).getResourceProviders(); + for (ResourceProvider rp : rps) { + + Resource resource = rp.getResource(resourceResolver, + fullPath); + if (resource != null) { + nreal++; + LOGGER.debug("Resolved Full {} using {} from {} ",new Object[]{ + fullPath, rp, Arrays.toString(rps)}); + return resource; + } + } + } + // query: /libs/sling/servlet/default + // resource Provider: libs/sling/servlet/default/GET.servlet + // list will match libs, sling, servlet, default + // and there will be no resource provider at the end + if (list.size() > 0 && list.size() == elements.length ) { + if ( list.get(list.size()-1).getResourceProviders().length == 0 ) { + nsynthetic++; + LOGGER.debug("Resolved Synthetic {}", fullPath); + return new SyntheticResource(resourceResolver, + fullPath, + ResourceProvider.RESOURCE_TYPE_SYNTHETIC); + } + } + + // 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; + } + } + + + LOGGER.debug("Resource null {} ", fullPath); + nmiss++; + return null; + } catch (Exception ex) { + LOGGER.debug("Failed! ",ex); + return null; + } finally { + ttime += System.currentTimeMillis() - start; + } + } + + + /** + * 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 providers) { + String[] elements = split(path, '/'); + ResourceProviderEntry2 base = this; + for (String element : elements ) { + if ( base.containsKey(element)) { + base = base.get(element); + } else { + base = null; + break; + } + } + // the path has been exausted and there is a subtree to be collected, so go and collect it. + if ( base != null ) { + getResourceProviders(base, providers); + } + // add in providers at this node in the tree, ie the root provider + for ( ResourceProvider rp : getResourceProviders() ) { + providers.add(rp); + } + + } + + /** + * @param base + * @param providers2 + */ + private void getResourceProviders(ResourceProviderEntry2 entry, + Set providers) { + // recurse down the tree + LOGGER.debug(" Gathering For {} ",entry.prefix); + for ( ResourceProviderEntry2 e : entry.values() ) { + getResourceProviders(e, providers); + } + // add in providers at this node in the tree. + for ( ResourceProvider rp : entry.getResourceProviders() ) { + providers.add(rp); + } + } + + /** + * @param st + * @param sep + * @return an array of the strings between the separator + */ + private String[] split(String st, char sep) { + + if (st == null) { + return new String[0]; + } + char[] pn = st.toCharArray(); + if (pn.length == 0) { + return new String[0]; + } + if (pn.length == 1 && pn[0] == sep) { + return new String[0]; + } + int n = 1; + int start = 0; + int end = pn.length; + while (start < end && sep == pn[start]) + start++; + while (start < end && sep == pn[end - 1]) + end--; + for (int i = start; i < end; i++) { + if (sep == pn[i]) { + n++; + } + } + String[] e = new String[n]; + int s = start; + int j = 0; + for (int i = start; i < end; i++) { + if (pn[i] == sep) { + e[j++] = new String(pn, s, i - s); + s = i + 1; + } + } + if (s < end) { + e[j++] = new String(pn, s, end - s); + } + return e; + } + + /** + * @return + */ + public String getResolutionStats() { + long tot = nreal + nsynthetic + nmiss; + if (tot == 0) { + return null; + } + float n = tot; + float t = ttime; + float persec = 1000 * n / t; + float avgtime = t / n; + + String stat = "Resolved: Real(" + nreal + ") Synthetic(" + nsynthetic + + ") Missing(" + nmiss + ") Total(" + tot + ") at " + persec + + " ops/sec avg " + avgtime + " ms"; + ttime = nmiss = nsynthetic = nreal = 0L; + return stat; + } + + /** + * {@inheritDoc} + * + * @see java.util.AbstractMap#toString() + */ + @Override + public String toString() { + return this.path; + //"{path:\"" + this.path + "\", providers:"+Arrays.toString(getResourceProviders())+", map:" + storageMap.toString() + "}"; + } + +} Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry2.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java?rev=833278&view=auto ============================================================================== --- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java (added) +++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java Fri Nov 6 02:19:55 2009 @@ -0,0 +1,97 @@ +/* + * Licensed to the Sakai Foundation (SF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The SF 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 org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceProvider; +import org.apache.sling.api.resource.ResourceResolver; + +import java.util.Iterator; + +import javax.servlet.http.HttpServletRequest; + +/** + * + */ +public class WrappedResourceProvider implements ResourceProvider { + + private ResourceProvider resourceProvider; + private Comparable serviceReference; + + /** + * + */ + public WrappedResourceProvider(ResourceProvider resourceProvider, Comparable serviceReference) { + this.resourceProvider = resourceProvider; + this.serviceReference = serviceReference; + } + /** + * {@inheritDoc} + * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, java.lang.String) + */ + public Resource getResource(ResourceResolver arg0, String arg1) { + return resourceProvider.getResource(arg0, arg1); + } + + /** + * {@inheritDoc} + * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, javax.servlet.http.HttpServletRequest, java.lang.String) + */ + public Resource getResource(ResourceResolver arg0, HttpServletRequest arg1, String arg2) { + return resourceProvider.getResource(arg0, arg1, arg2); + } + + /** + * {@inheritDoc} + * @see org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache.sling.api.resource.Resource) + */ + public Iterator listChildren(Resource arg0) { + return resourceProvider.listChildren(arg0); + } + /** + * @return + */ + public Comparable getComparable() { + return serviceReference; + } + + /** + * {@inheritDoc} + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return resourceProvider.hashCode(); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if ( obj instanceof WrappedResourceProvider ) { + return resourceProvider.equals(((WrappedResourceProvider) obj).resourceProvider); + } else if ( obj instanceof ResourceProvider) { + return resourceProvider.equals(obj); + } + return super.equals(obj); + } + + +} Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java?rev=833278&r1=833277&r2=833278&view=diff ============================================================================== --- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java (original) +++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java Fri Nov 6 02:19:55 2009 @@ -22,21 +22,31 @@ import org.apache.sling.api.resource.ResourceProvider; import org.apache.sling.jcr.resource.JcrResourceTypeProvider; -import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry; +import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2; -public class JcrResourceProviderEntry extends ResourceProviderEntry { +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; - private final ResourceProviderEntry delegatee; +public class JcrResourceProviderEntry extends ResourceProviderEntry2 { + + /** + * + */ + private static final long serialVersionUID = 5672648586247261128L; + + private final ResourceProviderEntry2 delegatee; private final Session session; private final JcrResourceTypeProvider[] resourceTypeProviders; public JcrResourceProviderEntry(Session session, - ResourceProviderEntry delegatee, - JcrResourceTypeProvider[] resourceTypeProviders, - final ClassLoader dynamicClassLoader) { - super("/", new JcrResourceProvider(session, resourceTypeProviders, dynamicClassLoader), null); + ResourceProviderEntry2 delegatee, + JcrResourceTypeProvider[] resourceTypeProviders, + final ClassLoader dynamicClassLoader) { + super("/", new ResourceProvider[] { new JcrResourceProvider(session, + resourceTypeProviders, dynamicClassLoader) }); this.delegatee = delegatee; this.session = session; @@ -52,17 +62,99 @@ } @Override - public ResourceProviderEntry[] getEntries() { - return delegatee.getEntries(); + public boolean addResourceProvider(String prefix, ResourceProvider provider, Comparable comparable) { + return delegatee.addResourceProvider(prefix, provider, comparable); + } + + @Override + public boolean removeResourceProvider(String prefix, + ResourceProvider provider, Comparable comparable) { + return delegatee.removeResourceProvider(prefix, provider, comparable); + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#put(java.lang.String, + * org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2) + */ + + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#get(java.lang.String) + */ + @Override + public ResourceProviderEntry2 get(String key) { + ResourceProviderEntry2 rpe = super.get(key); + if (rpe == null) { + rpe = delegatee.get(key); + } + return rpe; } + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#values() + */ @Override - public boolean addResourceProvider(String prefix, ResourceProvider provider) { - return delegatee.addResourceProvider(prefix, provider); + public Collection values() { + List list = new ArrayList( + super.values()); + list.addAll(delegatee.values()); + return list; } + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#containsKey(java.lang.String) + */ @Override - public boolean removeResourceProvider(String prefix) { - return delegatee.removeResourceProvider(prefix); + public boolean containsKey(String key) { + return (super.containsKey(key) || delegatee.containsKey(key)); } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#getResourceProviders() + */ + @Override + public ResourceProvider[] getResourceProviders() { + // merge the delegatee and this set of providers, + // its probably better to do this every time, as + + ResourceProvider[] delegateeProviders = delegatee + .getResourceProviders(); + ResourceProvider[] superProviders = super.getResourceProviders(); + if (delegateeProviders == null && superProviders == null) { + return null; + } + if (delegateeProviders == null) { + delegateeProviders = new ResourceProvider[0]; + } + if (superProviders == null) { + superProviders = new ResourceProvider[0]; + } + ResourceProvider[] resourceProviders = new ResourceProvider[delegateeProviders.length + + superProviders.length]; + System.arraycopy(delegateeProviders, 0, resourceProviders, 0, + delegateeProviders.length); + System.arraycopy(superProviders, 0, resourceProviders, + delegateeProviders.length, superProviders.length); + return resourceProviders; + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#toString() + */ + @Override + public String toString() { + return delegatee.toString(); + } + } Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java?rev=833278&r1=833277&r2=833278&view=diff ============================================================================== --- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java (original) +++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java Fri Nov 6 02:19:55 2009 @@ -144,6 +144,7 @@ super.tearDown(); } + @SuppressWarnings("deprecation") public void testBasicAPIAssumptions() throws Exception { // null resource is accessing /, which exists of course @@ -195,7 +196,7 @@ final HttpServletRequest req2 = new ResourceResolverTestRequest(null); final Resource res2 = resResolver.resolve(req2); assertNotNull("Expecting resource if resolution fails", res2); - assertTrue("Resource must not be NonExistingResource", + assertTrue("Resource must not be NonExistingResource was ", !(res2 instanceof NonExistingResource)); assertEquals("Path must be the the root path", "/", res2.getPath()); } Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java?rev=833278&r1=833277&r2=833278&view=diff ============================================================================== --- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java (original) +++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java Fri Nov 6 02:19:55 2009 @@ -18,6 +18,7 @@ */ package org.apache.sling.jcr.resource.internal.helper; +import java.util.Arrays; import java.util.Iterator; import java.util.Map; @@ -34,14 +35,14 @@ private ResourceProvider rootProvider; - private ResourceProviderEntry root; + private ResourceProviderEntry2 root; @Override protected void setUp() throws Exception { super.setUp(); rootProvider = new TestResourceProvider("/"); - root = new ResourceProviderEntry("/", rootProvider, null); + root = new ResourceProviderEntry2("/", new ResourceProvider[]{ rootProvider}); } @Override @@ -62,7 +63,8 @@ public void testAdd1Provider() { String firstPath = "/rootel"; ResourceProvider first = new TestResourceProvider(firstPath); - root.addResourceProvider(firstPath, first); + root.addResourceProvider(firstPath, first, null); + assertEquals(root, root.getResource(null, "/")); assertEquals(first, root.getResource(null, "/rootel")); @@ -84,9 +86,11 @@ ResourceProvider second = new TestResourceProvider(secondPath); ResourceProvider third = new TestResourceProvider(thirdPath); - root.addResourceProvider(firstPath, first); - root.addResourceProvider(secondPath, second); - root.addResourceProvider(thirdPath, third); + root.addResourceProvider(firstPath, first, null); + root.addResourceProvider(secondPath, second, null); + root.addResourceProvider(thirdPath, third, null); + + assertEquals(rootProvider, root.getResource(null, "/")); assertEquals(first, root.getResource(null, "/rootel")); @@ -95,8 +99,9 @@ assertEquals(second, root.getResource(null, "/rootel/child/html.js")); assertEquals(third, root.getResource(null, "/apps/sling/sample/html.js")); - assertEquals(rootProvider, root.getResource(null, - "/apps/sling/microsling/html.js")); + Resource resource = root.getResource(null, + "/apps/sling/microsling/html.js"); + assertEquals(rootProvider, resource); } public void testAdd3ProvidersReverse() { @@ -108,9 +113,9 @@ ResourceProvider second = new TestResourceProvider(secondPath); ResourceProvider third = new TestResourceProvider(thirdPath); - root.addResourceProvider(thirdPath, third); - root.addResourceProvider(secondPath, second); - root.addResourceProvider(firstPath, first); + root.addResourceProvider(thirdPath, third, null); + root.addResourceProvider(secondPath, second, null); + root.addResourceProvider(firstPath, first, null); assertEquals(rootProvider, root.getResource(null, "/")); assertEquals(first, root.getResource(null, "/rootel")); @@ -118,9 +123,10 @@ assertEquals(second, root.getResource(null, "/rootel/child")); assertEquals(second, root.getResource(null, "/rootel/child/html.js")); assertEquals(third, - root.getResource(null, "/apps/sling/sample/html.js")); - assertEquals(rootProvider, root.getResource(null, - "/apps/sling/microsling/html.js")); + root.getResource(null, "/apps/sling/sample/html.js")); + Resource resource = root.getResource(null, + "/apps/sling/microsling/html.js"); + assertEquals(rootProvider, resource); } public void testRemoveProviders() { @@ -132,21 +138,22 @@ ResourceProvider second = new TestResourceProvider(secondPath); ResourceProvider third = new TestResourceProvider(thirdPath); - root.addResourceProvider(firstPath, first); - root.addResourceProvider(secondPath, second); - root.addResourceProvider(thirdPath, third); + root.addResourceProvider(firstPath, first, null); + root.addResourceProvider(secondPath, second, null); + root.addResourceProvider(thirdPath, third, null); assertEquals(rootProvider, root.getResource(null, "/")); assertEquals(first, root.getResource(null, "/rootel/html.js")); assertEquals(second, root.getResource(null, "/rootel/child/html.js")); - root.removeResourceProvider(firstPath); + root.removeResourceProvider(firstPath, first, null); assertEquals(rootProvider, root.getResource(null, "/")); + assertEquals(rootProvider, root.getResource(null, "/rootel/sddsf/sdfsdf/html.js")); assertEquals(rootProvider, root.getResource(null, "/rootel/html.js")); assertEquals(second, root.getResource(null, "/rootel/child/html.js")); - root.addResourceProvider(firstPath, first); + root.addResourceProvider(firstPath, first, null); assertEquals(rootProvider, root.getResource(null, "/")); assertEquals(first, root.getResource(null, "/rootel/html.js")); @@ -157,10 +164,15 @@ assertEquals(resProvider, res.getResourceResolver()); } - protected void assertEquals(ResourceProviderEntry resProviderEntry, + protected void assertEquals(ResourceProviderEntry2 resProviderEntry, Resource res) { - assertEquals(resProviderEntry.getResourceProvider(), - res.getResourceResolver()); + ResourceProvider[] resourceProviders = resProviderEntry.getResourceProviders(); + for ( ResourceProvider rp : resourceProviders ) { + if ( rp.equals(res.getResourceResolver())) { + return; + } + } + fail(); } // The test provider implements the ResourceResolver interface and sets @@ -237,6 +249,16 @@ public AdapterType adaptTo(Class type) { return null; } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return Arrays.toString(roots); + } + } private static class TestResource implements Resource { Modified: sling/trunk/contrib/jcr/resource2/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/jcr/resource2/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java?rev=833278&r1=833277&r2=833278&view=diff ============================================================================== --- sling/trunk/contrib/jcr/resource2/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java (original) +++ sling/trunk/contrib/jcr/resource2/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java Fri Nov 6 02:19:55 2009 @@ -91,7 +91,7 @@ private final MapEntries resourceMapper; public JcrResourceResolver2(JcrResourceProviderEntry rootProvider, - JcrResourceResolverFactoryImpl factory, MapEntries resourceMapper) { + JcrResourceResolverFactoryImpl factory, MapEntries resourceMapper) { this.rootProvider = rootProvider; this.factory = factory; this.resourceMapper = resourceMapper;