Return-Path: X-Original-To: apmail-sling-commits-archive@www.apache.org Delivered-To: apmail-sling-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EEAFBD86D for ; Thu, 25 Oct 2012 09:18:29 +0000 (UTC) Received: (qmail 9800 invoked by uid 500); 25 Oct 2012 09:18:29 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 9690 invoked by uid 500); 25 Oct 2012 09:18:26 -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 9643 invoked by uid 99); 25 Oct 2012 09:18:25 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 25 Oct 2012 09:18:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.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; Thu, 25 Oct 2012 09:18:20 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 15D2D2388980; Thu, 25 Oct 2012 09:17:35 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1402037 - in /sling/trunk/bundles: api/src/main/java/org/apache/sling/api/resource/ extensions/bundleresource/ extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/ extensions/fsresource/ extensions/fsresource/src/m... Date: Thu, 25 Oct 2012 09:17:34 -0000 To: commits@sling.apache.org From: cziegeler@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121025091735.15D2D2388980@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: cziegeler Date: Thu Oct 25 09:17:34 2012 New Revision: 1402037 URL: http://svn.apache.org/viewvc?rev=1402037&view=rev Log: SLING-2541 : General mechanism to chain resource providers Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java sling/trunk/bundles/extensions/bundleresource/pom.xml sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java sling/trunk/bundles/extensions/fsresource/pom.xml sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResource.java sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIterator.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/ResourceProviderEntry.java Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java (original) +++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java Thu Oct 25 09:17:34 2012 @@ -106,6 +106,20 @@ public class ResourceMetadata extends Ha public static final String MODIFICATION_TIME = "sling.modificationTime"; /** + * Returns whether the resource resolver should continue to search for a + * resource. + * A resource provider can set this flag to indicate that the resource + * resolver should search for a provider with a lower priority. If it + * finds a resource using such a provider, that resource is returned + * instead. If none is found this resource is returned. + * This flag should never be manipulated by application code! + * The value of this property has no meaning, the resource resolver + * just checks whether this flag is set or not. + * @since 2.2 + */ + public static final String INTERNAL_CONTINUE_RESOLVING = ":org.apache.sling.resource.internal.continue.resolving"; + + /** * Sets the {@link #CHARACTER_ENCODING} property to encoding * if not null. */ Modified: sling/trunk/bundles/extensions/bundleresource/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/bundleresource/pom.xml?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/extensions/bundleresource/pom.xml (original) +++ sling/trunk/bundles/extensions/bundleresource/pom.xml Thu Oct 25 09:17:34 2012 @@ -118,10 +118,6 @@ provided - javax.jcr - jcr - - org.slf4j slf4j-api Modified: sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java (original) +++ sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java Thu Oct 25 09:17:34 2012 @@ -25,9 +25,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - import org.apache.sling.api.resource.AbstractResource; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceMetadata; @@ -68,16 +65,6 @@ public class BundleResource extends Abst // able to return an item-based resource URL entry = bundle.getEntry(entryPath.concat("/")); if (entry != null) { - Session session = resourceResolver.adaptTo(Session.class); - if (session != null) { - try { - if (session.itemExists(resourcePath)) { - return null; - } - } catch (RepositoryException re) { - // don't care - } - } // append the slash to path for next steps resourcePath = resourcePath.concat("/"); @@ -93,7 +80,7 @@ public class BundleResource extends Abst // or a bundle file if (entry != null) { return new BundleResource(resourceResolver, bundle, mappedPath, - resourcePath); + resourcePath); } // the bundle does not contain the path @@ -117,6 +104,7 @@ public class BundleResource extends Abst this.path = resourcePath.substring(0, resourcePath.length() - 1); this.resourceType = NT_FOLDER; + metadata.put(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING, Boolean.TRUE); } else { @@ -153,6 +141,7 @@ public class BundleResource extends Abst return resourceResolver; } + @Override @SuppressWarnings("unchecked") public Type adaptTo(Class type) { if (type == InputStream.class) { @@ -165,9 +154,10 @@ public class BundleResource extends Abst return super.adaptTo(type); } + @Override public String toString() { return getClass().getSimpleName() + ", type=" + getResourceType() - + ", path=" + getPath(); + + ", path=" + getPath(); } // ---------- internal ----------------------------------------------------- @@ -186,7 +176,7 @@ public class BundleResource extends Abst } } catch (IOException ioe) { log.error( - "getInputStream: Cannot get input stream for " + this, ioe); + "getInputStream: Cannot get input stream for " + this, ioe); } } @@ -198,8 +188,8 @@ public class BundleResource extends Abst if (url == null) { try { url = new URL(BundleResourceURLStreamHandler.PROTOCOL, null, - -1, path, new BundleResourceURLStreamHandler( - bundle.getBundle(), mappedPath.getEntryPath(path))); + -1, path, new BundleResourceURLStreamHandler( + bundle.getBundle(), mappedPath.getEntryPath(path))); } catch (MalformedURLException mue) { log.error("getURL: Cannot get URL for " + this, mue); } @@ -208,6 +198,7 @@ public class BundleResource extends Abst return url; } + @Override public Iterator listChildren() { return new BundleResourceIterator(this); } Modified: sling/trunk/bundles/extensions/fsresource/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/pom.xml?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/extensions/fsresource/pom.xml (original) +++ sling/trunk/bundles/extensions/fsresource/pom.xml Thu Oct 25 09:17:34 2012 @@ -89,10 +89,6 @@ servlet-api - javax.jcr - jcr - - org.apache.sling org.apache.sling.api 2.2.5-SNAPSHOT Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResource.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResource.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResource.java (original) +++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResource.java Thu Oct 25 09:17:34 2012 @@ -110,6 +110,9 @@ public class FsResource extends Abstract metaData.setContentLength(file.length()); metaData.setModificationTime(file.lastModified()); metaData.setResolutionPath(resourcePath); + if ( this.file.isDirectory() ) { + metaData.put(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING, Boolean.TRUE); + } } return metaData; } @@ -138,7 +141,7 @@ public class FsResource extends Abstract if (resourceType == null) { resourceType = file.isFile() ? RESOURCE_TYPE_FILE - : RESOURCE_TYPE_FOLDER; + : RESOURCE_TYPE_FOLDER; } return resourceType; @@ -149,6 +152,7 @@ public class FsResource extends Abstract * File, InputStream and URL * plus those supported by the adapter manager. */ + @Override @SuppressWarnings("unchecked") public AdapterType adaptTo(Class type) { if (type == File.class) { @@ -163,8 +167,8 @@ public class FsResource extends Abstract return (AdapterType) new FileInputStream(file); } catch (IOException ioe) { getLog().info( - "adaptTo: Cannot open a stream on the file " + file, - ioe); + "adaptTo: Cannot open a stream on the file " + file, + ioe); } } else { @@ -179,12 +183,12 @@ public class FsResource extends Abstract return (AdapterType) file.toURI().toURL(); } catch (MalformedURLException mue) { getLog().info( - "adaptTo: Cannot convert the file path " + file + "adaptTo: Cannot convert the file path " + file + " to an URL", mue); } } else if (type == ValueMap.class) { - + // this resource simulates nt:file/nt:folder behavior by returning it as resource type // we should simulate the corresponding JCR properties in a value map as well if (file.exists() && file.canRead()) { @@ -196,9 +200,9 @@ public class FsResource extends Abstract props.put("jcr:created", lastModifed); return (AdapterType) new ValueMapDecorator(props); } - + } - + return super.adaptTo(type); } Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java (original) +++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java Thu Oct 25 09:17:34 2012 @@ -24,8 +24,6 @@ import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; import javax.servlet.http.HttpServletRequest; import org.apache.felix.scr.annotations.Component; @@ -54,18 +52,18 @@ import org.osgi.service.event.EventAdmin * resource ({@link #PROP_PROVIDER_FILE}). */ @Component( - name="org.apache.sling.fsprovider.internal.FsResourceProvider", - label="%resource.resolver.name", - description="%resource.resolver.description", - configurationFactory=true, - policy=ConfigurationPolicy.REQUIRE, - metatype=true -) + name="org.apache.sling.fsprovider.internal.FsResourceProvider", + label="%resource.resolver.name", + description="%resource.resolver.description", + configurationFactory=true, + policy=ConfigurationPolicy.REQUIRE, + metatype=true + ) @Service(ResourceProvider.class) @Properties({ @Property(name="service.description", value="Sling Filesystem Resource Provider"), @Property(name="service.vendor", value="The Apache Software Foundation"), - @Property(name=ResourceProvider.ROOTS) + @Property(name=ResourceProvider.ROOTS) }) public class FsResourceProvider implements ResourceProvider { @@ -148,8 +146,8 @@ public class FsResourceProvider implemen String relPath = providerRoot.substring(parentPath.length()); if (relPath.indexOf('/') < 0) { Resource res = getResource( - parent.getResourceResolver(), providerRoot, - providerFile); + parent.getResourceResolver(), providerRoot, + providerFile); if (res != null) { return Collections.singletonList(res).iterator(); } @@ -220,7 +218,7 @@ public class FsResourceProvider implemen String providerFileName = (String) props.get(PROP_PROVIDER_FILE); if (providerFileName == null || providerFileName.length() == 0) { throw new IllegalArgumentException(PROP_PROVIDER_FILE - + " property must be set"); + + " property must be set"); } this.providerRoot = providerRoot; @@ -282,7 +280,7 @@ public class FsResourceProvider implemen // if the provider file does not exist, create an empty new folder if (!providerFile.exists() && !providerFile.mkdirs()) { throw new IllegalArgumentException( - "Cannot create provider file root " + providerFile); + "Cannot create provider file root " + providerFile); } return providerFile; @@ -314,21 +312,6 @@ public class FsResourceProvider implemen if (file != null) { - // if the file is a directory, and a repository item exists for - // the path, do not return the directory here - if (file.isDirectory()) { - Session session = resourceResolver.adaptTo(Session.class); - if (session != null) { - try { - if (session.itemExists(resourcePath)) { - return null; - } - } catch (RepositoryException re) { - // don't care - } - } - } - // if the file exists, but is not a directory or no repository entry // exists, return it as a resource if (file.exists()) { Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIterator.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIterator.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIterator.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIterator.java Thu Oct 25 09:17:34 2012 @@ -120,8 +120,8 @@ public class ResourceIterator implements private final ResourceResolverContext resourceResolverContext; public ResourceIterator(final ResourceResolverContext ctx, - final Resource parentResource, - final RootResourceProviderEntry rootProviderEntry) { + final Resource parentResource, + final RootResourceProviderEntry rootProviderEntry) { this.resourceResolverContext = ctx; this.parentResource = parentResource; this.rootProviderEntry = rootProviderEntry; @@ -141,7 +141,7 @@ public class ResourceIterator implements if (log.isDebugEnabled()) { log.debug(" Provider Set for path {} {} ", path, Arrays - .toString(providersSet.toArray(new ProviderHandler[providersSet.size()]))); + .toString(providersSet.toArray(new ProviderHandler[providersSet.size()]))); } this.iteratorPath = path; providers = providersSet.iterator(); @@ -173,7 +173,7 @@ public class ResourceIterator implements private Resource seek() { while (delayedIter == null) { while ((resources == null || !resources.hasNext()) - && providers.hasNext()) { + && providers.hasNext()) { final ProviderHandler provider = providers.next(); resources = provider.listChildren(this.resourceResolverContext, parentResource); log.debug(" Checking Provider {} ", provider); @@ -214,18 +214,17 @@ public class ResourceIterator implements final ResourceProviderEntry rpw = baseEntryValues.next(); final String resPath = iteratorPath + rpw.getPath(); if (!visited.contains(resPath)) { - final ResourceResolver rr = parentResource - .getResourceResolver(); + final ResourceResolver rr = parentResource.getResourceResolver(); final Resource res = rpw.getResourceFromProviders(this.resourceResolverContext, rr, - resPath); + resPath); if (res == null) { if (!delayed.containsKey(resPath)) { delayed.put( + resPath, + new SyntheticResource( + rr, resPath, - new SyntheticResource( - rr, - resPath, - ResourceProvider.RESOURCE_TYPE_SYNTHETIC)); + ResourceProvider.RESOURCE_TYPE_SYNTHETIC)); } } else { // return the real resource immediately, add @@ -234,7 +233,7 @@ public class ResourceIterator implements delayed.remove(resPath); visited.add(resPath); log.debug(" B resource {} {}", resPath, - res.getClass()); + res.getClass()); return res; } } @@ -273,7 +272,7 @@ public class ResourceIterator implements * null if there is no entry at the given location */ private ResourceProviderEntry getResourceProviders(final String path, - final Set providers) { + final Set providers) { // collect providers along the ancestor path segements final String[] elements = ResourceProviderEntry.split(path); @@ -283,7 +282,7 @@ public class ResourceIterator implements base = base.get(element); if (log.isDebugEnabled()) { log.debug("Loading from {} {} ", element, - base.getResourceProviders().length); + base.getResourceProviders().length); } for (final ProviderHandler rp : base.getResourceProviders()) { log.debug("Adding {} for {} ", rp, path); Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/ResourceProviderEntry.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/ResourceProviderEntry.java?rev=1402037&r1=1402036&r2=1402037&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/ResourceProviderEntry.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/ResourceProviderEntry.java Thu Oct 25 09:17:34 2012 @@ -29,6 +29,7 @@ import java.util.Set; import org.apache.commons.collections.FastTreeMap; import org.apache.sling.api.resource.ModifyingResourceProvider; import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceMetadata; import org.apache.sling.api.resource.ResourceProvider; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.SyntheticResource; @@ -118,8 +119,8 @@ public class ResourceProviderEntry imple * if an error occurrs trying to access an existing resource. */ public Resource getResource(final ResourceResolverContext ctx, - final ResourceResolver resourceResolver, - final String path) { + final ResourceResolver resourceResolver, + final String path) { return getInternalResource(ctx, resourceResolver, path); } @@ -265,8 +266,8 @@ public class ResourceProviderEntry imple * @return null if no resource was found, a resource if one was found. */ private Resource getInternalResource(final ResourceResolverContext ctx, - final ResourceResolver resourceResolver, - final String fullPath) { + final ResourceResolver resourceResolver, + final String fullPath) { try { if (fullPath == null || fullPath.length() == 0 || fullPath.charAt(0) != '/') { @@ -277,19 +278,29 @@ public class ResourceProviderEntry imple final List entries = new ArrayList(); this.populateProviderPath(entries, elements); + Resource fallbackResource = null; + // the path is in reverse order end first for (int i = entries.size() - 1; i >= 0; i--) { final ProviderHandler[] rps = entries.get(i).getResourceProviders(); for (final ProviderHandler rp : rps) { + boolean foundFallback = false; final Resource resource = rp.getResource(ctx, resourceResolver, fullPath); if (resource != null) { - LOGGER.debug("Resolved Full {} using {} from {} ", new Object[] { fullPath, rp, Arrays.toString(rps) }); - return resource; + if ( resource.getResourceMetadata() != null && resource.getResourceMetadata().get(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING) != null ) { + LOGGER.debug("Resolved Full {} using {} from {} - continue resolving flag is set!", new Object[] { fullPath, rp, Arrays.toString(rps) }); + fallbackResource = resource; + fallbackResource.getResourceMetadata().remove(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING); + foundFallback = true; + } else { + LOGGER.debug("Resolved Full {} using {} from {} ", new Object[] { fullPath, rp, Arrays.toString(rps) }); + return resource; + } } - if ( rp.ownsRoots() ) { + if ( rp.ownsRoots() && !foundFallback ) { LOGGER.debug("Resource null {} ", fullPath); - return null; + return fallbackResource; } } } @@ -300,6 +311,11 @@ public class ResourceProviderEntry imple return resource; } + if ( fallbackResource != null ) { + LOGGER.debug("Using first found resource {} for {}", fallbackResource, fullPath); + return fallbackResource; + } + // query: /libs/sling/servlet/default // resource Provider: libs/sling/servlet/default/GET.servlet // list will match libs, sling, servlet, default @@ -320,21 +336,36 @@ public class ResourceProviderEntry imple } public Resource getResourceFromProviders(final ResourceResolverContext ctx, - final ResourceResolver resourceResolver, final String fullPath) { + final ResourceResolver resourceResolver, + final String fullPath) { + Resource fallbackResource = null; final ProviderHandler[] rps = getResourceProviders(); for (final ProviderHandler rp : rps) { + boolean foundFallback = false; + final Resource resource = rp.getResource(ctx, resourceResolver, fullPath); if (resource != null) { - LOGGER.debug("Resolved Base {} using {} ", fullPath, rp); - return resource; + if ( resource.getResourceMetadata() != null && resource.getResourceMetadata().get(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING) != null ) { + LOGGER.debug("Resolved Base {} using {} - continue resolving flag is set!", fullPath, rp); + fallbackResource = resource; + fallbackResource.getResourceMetadata().remove(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING); + foundFallback = true; + } else { + LOGGER.debug("Resolved Base {} using {} ", fullPath, rp); + return resource; + } + } + if ( rp.ownsRoots() && !foundFallback ) { + LOGGER.debug("Resource null {} ", fullPath); + return fallbackResource; } } - return null; + return fallbackResource; } public ModifyingResourceProvider getModifyingProvider(final ResourceResolverContext ctx, - final ResourceResolver resourceResolver, - final String fullPath) { + final ResourceResolver resourceResolver, + final String fullPath) { final String[] elements = split(fullPath); final List entries = new ArrayList(); this.populateProviderPath(entries, elements);