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

svn commit: r1709747 [1/4] - in /sling/trunk/bundles/resourceresolver: ./ src/main/java/org/apache/sling/resourceresolver/impl/ src/main/java/org/apache/sling/resourceresolver/impl/helper/ src/main/java/org/apache/sling/resourceresolver/impl/legacy/ sr...

Author: tomekr
Date: Wed Oct 21 08:23:09 2015
New Revision: 1709747

URL: http://svn.apache.org/viewvc?rev=1709747&view=rev
Log:
SLING-5158 Refactor ResourceResolver to use the new ResourceProvider API

Added:
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/params/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/params/ParametersParser.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/params/ParsedParameters.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/params/PathParser.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AbstractIterator.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/EmptyResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/StatefulResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/StatefulResourceProviderWrapper.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Node.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathSegmentIterator.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTree.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Pathable.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ProviderHandlerTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceProviderEntryTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/params/
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/params/PathParametersParserTest.java
Removed:
    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/helper/SortedProviderList.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/tree/
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/SortedProviderListTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/tree/
Modified:
    sling/trunk/bundles/resourceresolver/pom.xml
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderInfo.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorReturnsNullTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorTestBase.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverMangleNamespacesTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/RedirectResourceTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntryTest.java

Modified: sling/trunk/bundles/resourceresolver/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/pom.xml?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/pom.xml (original)
+++ sling/trunk/bundles/resourceresolver/pom.xml Wed Oct 21 08:23:09 2015
@@ -135,11 +135,23 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+           <groupId>commons-lang</groupId>
+           <artifactId>commons-lang</artifactId>
+           <version>2.4</version>
+           <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>adapter-annotations</artifactId>
             <version>1.0.0</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.0</version>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- For the Console Plugin of the ResourceResolverFactoryImpl -->
         <dependency>

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java?rev=1709747&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java Wed Oct 21 08:23:09 2015
@@ -0,0 +1,80 @@
+/*
+ * 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.resourceresolver.impl;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
+
+public class BasicResolveContext<T> implements ResolveContext<T> {
+
+    private final ResourceResolver resourceResolver;
+
+    private final Map<String, String> resolveParameters;
+
+    private final T providerState;
+
+    private final ResolveContext<Object> parentResolveContext;
+
+    private final ResourceProvider<Object> parentResourceProvider;
+
+    public BasicResolveContext(ResourceResolver resourceResolver, Map<String, String> resolveParameters,
+            T providerState, ResourceProvider<Object> parentResourceProvider, ResolveContext<Object> parentResolveContext) {
+        this.resourceResolver = resourceResolver;
+        this.resolveParameters = resolveParameters == null ? Collections.<String, String> emptyMap()
+                : resolveParameters;
+        this.providerState = providerState;
+        this.parentResolveContext = parentResolveContext;
+        this.parentResourceProvider = parentResourceProvider;
+    }
+
+    public BasicResolveContext(ResourceResolver resourceResolver, Map<String, String> resolveParameters,
+            T providerState) {
+        this(resourceResolver, resolveParameters, providerState, null, null);
+    }
+
+    @Override
+    public ResourceResolver getResourceResolver() {
+        return resourceResolver;
+    }
+
+    @Override
+    public Map<String, String> getResolveParameters() {
+        return resolveParameters;
+    }
+
+    @Override
+    public T getProviderState() {
+        return providerState;
+    }
+
+    @Override
+    public ResolveContext<?> getParentResolveContext() {
+        return parentResolveContext;
+    }
+
+    @Override
+    public ResourceProvider<?> getParentResourceProvider() {
+        return parentResourceProvider;
+    }
+
+}

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java Wed Oct 21 08:23:09 2015
@@ -32,7 +32,6 @@ import java.util.concurrent.atomic.Atomi
 
 import org.apache.commons.collections.BidiMap;
 import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceProviderFactory;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.resourceresolver.impl.console.ResourceResolverWebConsolePlugin;
@@ -41,7 +40,8 @@ import org.apache.sling.resourceresolver
 import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider;
 import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
 import org.apache.sling.resourceresolver.impl.mapping.Mapping;
-import org.apache.sling.resourceresolver.impl.tree.RootResourceProviderEntry;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -129,10 +129,11 @@ public class CommonResourceResolverFacto
 
         // create a copy of the passed authentication info as we modify the map
         final Map<String, Object> authenticationInfo = new HashMap<String, Object>();
+        authenticationInfo.put(ResourceProvider.AUTH_ADMIN, Boolean.TRUE);
         if ( passedAuthenticationInfo != null ) {
             authenticationInfo.putAll(passedAuthenticationInfo);
             // make sure there is no leaking of service bundle and info props
-            authenticationInfo.remove(ResourceProviderFactory.SERVICE_BUNDLE);
+            authenticationInfo.remove(ResourceProvider.AUTH_SERVICE_BUNDLE);
             authenticationInfo.remove(SUBSERVICE);
         }
 
@@ -154,7 +155,7 @@ public class CommonResourceResolverFacto
         if ( passedAuthenticationInfo != null ) {
             authenticationInfo.putAll(passedAuthenticationInfo);
             // make sure there is no leaking of service bundle and info props
-            authenticationInfo.remove(ResourceProviderFactory.SERVICE_BUNDLE);
+            authenticationInfo.remove(ResourceProvider.AUTH_SERVICE_BUNDLE);
             authenticationInfo.remove(SUBSERVICE);
         }
 
@@ -253,13 +254,7 @@ public class CommonResourceResolverFacto
             throw new LoginException("ResourceResolverFactory is deactivated.");
         }
 
-        // create context
-        final ResourceResolverContext ctx = new ResourceResolverContext(isAdmin, authenticationInfo, this.activator.getResourceAccessSecurityTracker());
-
-        // login
-        this.activator.getRootProviderEntry().loginToRequiredFactories(ctx);
-
-        return new ResourceResolverImpl(this, ctx);
+        return new ResourceResolverImpl(this, isAdmin, authenticationInfo);
     }
 
     public MapEntries getMapEntries() {
@@ -329,10 +324,6 @@ public class CommonResourceResolverFacto
         return this.activator.getVirtualURLMap();
     }
 
-    public RootResourceProviderEntry getRootProviderEntry() {
-        return this.activator.getRootProviderEntry();
-    }
-
     @Override
     public int getDefaultVanityPathRedirectStatus() {
         return this.activator.getDefaultVanityPathRedirectStatus();
@@ -433,4 +424,8 @@ public class CommonResourceResolverFacto
             this.context.close();
         }
     }
+
+    public ResourceProviderTracker getResourceProviderTracker() {
+        return activator.getResourceProviderTracker();
+    }
 }
\ No newline at end of file

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java Wed Oct 21 08:23:09 2015
@@ -19,15 +19,16 @@
 package org.apache.sling.resourceresolver.impl;
 
 import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
 
+import org.apache.sling.resourceresolver.impl.legacy.LegacyResourceProviderWhiteboard;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,16 +37,15 @@ public class FactoryPreconditions {
     private static final class RequiredProvider {
         public String pid;
         public Filter filter;
-        public final List<Map<String, Object>> matchingServices = new ArrayList<Map<String,Object>>();
     };
 
-    private final List<Map<String, Object>> earlyPropertiesList = new ArrayList<Map<String, Object>>();
+    private ResourceProviderTracker tracker;
 
     private volatile List<RequiredProvider> requiredProviders;
 
-    private Boolean cachedResult = Boolean.FALSE;
+    public void activate(final BundleContext bc, final String[] configuration, ResourceProviderTracker tracker) {
+        this.tracker = tracker;
 
-    public void activate(final BundleContext bc, final String[] configuration) {
         final List<RequiredProvider> rps = new ArrayList<RequiredProvider>();
         if ( configuration != null ) {
             final Logger logger = LoggerFactory.getLogger(getClass());
@@ -69,14 +69,7 @@ public class FactoryPreconditions {
                 }
             }
         }
-        synchronized ( this ) {
-            this.requiredProviders = rps;
-            this.cachedResult = null;
-            for(final Map<String,Object> props : this.earlyPropertiesList) {
-                this.bindProvider(props);
-            }
-            this.earlyPropertiesList.clear();
-        }
+        this.requiredProviders = rps;
     }
 
     public void deactivate() {
@@ -85,75 +78,26 @@ public class FactoryPreconditions {
 
     public boolean checkPreconditions() {
         synchronized ( this ) {
-            if ( cachedResult != null ) {
-                return cachedResult;
-            }
             boolean canRegister = false;
-            if ( this.requiredProviders != null) {
-                canRegister = true;
-                for(final RequiredProvider rp : this.requiredProviders) {
-                    if ( rp.matchingServices.size() == 0 ) {
-                        canRegister = false;
-                        break;
+            if (this.requiredProviders != null) {
+                canRegister = false;
+                for (ResourceProviderHandler h : this.tracker.getResourceProviderStorage().getAllHandlers()) {
+                    for (final RequiredProvider rp : this.requiredProviders) {
+                        ServiceReference ref = h.getInfo().getServiceReference();
+                        if (rp.filter != null && rp.filter.match(ref)) {
+                            canRegister = true;
+                            break;
+                        } else if (rp.pid != null && rp.pid.equals(ref.getProperty(Constants.SERVICE_PID))){
+                            canRegister = true;
+                            break;
+                        } else if (rp.pid != null && rp.pid.equals(ref.getProperty(LegacyResourceProviderWhiteboard.ORIGINAL_SERVICE_PID))) {
+                            canRegister = true;
+                            break;
+                        }
                     }
                 }
             }
-            this.cachedResult = canRegister;
             return canRegister;
         }
     }
-
-    public void bindProvider(final Map<String, Object> props) {
-        synchronized ( this ) {
-            if ( this.requiredProviders == null ) {
-                this.earlyPropertiesList.add(props);
-                return;
-            }
-            Dictionary<String, Object> dict = null;
-            for(final RequiredProvider rp : this.requiredProviders) {
-                if ( rp.pid != null ) {
-                    if ( rp.pid.equals(props.get(Constants.SERVICE_PID)) ) {
-                        rp.matchingServices.add(props);
-                        this.cachedResult = null;
-                    }
-                } else {
-                    if ( dict == null ) {
-                        dict = new Hashtable<String, Object>(props);
-                    }
-                    if ( rp.filter.match(dict) ) {
-                        rp.matchingServices.add(props);
-                        this.cachedResult = null;
-                    }
-                }
-            }
-        }
-    }
-
-    private boolean removeFromList(final List<Map<String, Object>> list, final Map<String, Object> props) {
-        final Long id = (Long) props.get(Constants.SERVICE_ID);
-        int index = 0;
-        while ( index < list.size() ) {
-            final Long currentId = (Long ) list.get(index).get(Constants.SERVICE_ID);
-            if ( currentId == id ) {
-                list.remove(index);
-                return true;
-            }
-            index++;
-        }
-        return false;
-    }
-
-    public void unbindProvider(final Map<String, Object> props) {
-        synchronized ( this ) {
-            if ( this.requiredProviders == null ) {
-                this.removeFromList(this.earlyPropertiesList, props);
-                return;
-            }
-            for(final RequiredProvider rp : this.requiredProviders) {
-                if ( this.removeFromList(rp.matchingServices, props) ) {
-                    this.cachedResult = null;
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
+}

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java Wed Oct 21 08:23:09 2015
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import org.apache.commons.collections.BidiMap;
 import org.apache.commons.collections.bidimap.TreeBidiMap;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -36,15 +37,15 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.felix.scr.annotations.References;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.resource.ResourceDecorator;
-import org.apache.sling.api.resource.ResourceProvider;
-import org.apache.sling.api.resource.ResourceProviderFactory;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
 import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
 import org.apache.sling.resourceresolver.impl.mapping.Mapping;
-import org.apache.sling.resourceresolver.impl.tree.RootResourceProviderEntry;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
 import org.apache.sling.serviceusermapping.ServiceUserMapper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -52,7 +53,10 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
 
 /**
  * The <code>ResourceResolverFactoryActivator/code> keeps track of required services for the
@@ -67,17 +71,18 @@ import org.osgi.service.event.EventAdmin
      label = "Apache Sling Resource Resolver Factory",
      description = "Configures the Resource Resolver for request URL and resource path rewriting.",
      specVersion = "1.1",
-     metatype = true)
+     metatype = true,
+     immediate = true)
 @Properties({
     @Property(name = Constants.SERVICE_DESCRIPTION, value = "Apache Sling Resource Resolver Factory"),
-    @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation")
+    @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation"),
+    @Property(name = EventConstants.EVENT_TOPIC, value = SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED, propertyPrivate = true)
 })
 @References({
-    @Reference(name = "ResourceProvider", referenceInterface = ResourceProvider.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC),
-    @Reference(name = "ResourceProviderFactory", referenceInterface = ResourceProviderFactory.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC),
     @Reference(name = "ResourceDecorator", referenceInterface = ResourceDecorator.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
 })
-public class ResourceResolverFactoryActivator implements Runnable {
+@Service(EventHandler.class)
+public class ResourceResolverFactoryActivator implements Runnable, EventHandler {
 
     private static final class FactoryRegistration {
         /** Registration .*/
@@ -272,9 +277,6 @@ public class ResourceResolverFactoryActi
     /** whether to mangle paths with namespaces or not */
     private boolean mangleNamespacePrefixes;
 
-    /** The root provider entry. */
-    private final RootResourceProviderEntry rootProviderEntry = new RootResourceProviderEntry();
-
     /** Event admin. */
     @Reference
     EventAdmin eventAdmin;
@@ -286,6 +288,9 @@ public class ResourceResolverFactoryActi
     @Reference
     ResourceAccessSecurityTracker resourceAccessSecurityTracker;
 
+    @Reference
+    ResourceProviderTracker resourceProviderTracker;
+
     /** ComponentContext */
     private volatile ComponentContext componentContext;
 
@@ -312,7 +317,6 @@ public class ResourceResolverFactoryActi
     /** log the place where a resource resolver is closed */
     private boolean logResourceResolverClosing = DEFAULT_LOG_RESOURCE_RESOLVER_CLOSING;
 
-
     /** Vanity path whitelist */
     private String[] vanityPathWhiteList;
 
@@ -327,9 +331,6 @@ public class ResourceResolverFactoryActi
     /** Background thread coordination. */
     private final Object coordinator = new Object();
 
-    /** Paranoid provider handling? */
-    private volatile boolean paranoidProviderHandling;
-
     /** Background thread operation */
     private enum BG_OP {
         CHECK,                // check preconditions
@@ -339,6 +340,8 @@ public class ResourceResolverFactoryActi
 
     private final List<BG_OP> operations = new ArrayList<BG_OP>();
 
+    private String[] requiredResourceProviders;
+
     /**
      * Get the resource decorator tracker.
      */
@@ -355,13 +358,6 @@ public class ResourceResolverFactoryActi
     }
 
     /**
-     * Getter for rootProviderEntry.
-     */
-    public RootResourceProviderEntry getRootProviderEntry() {
-        return rootProviderEntry;
-    }
-
-    /**
      * This method is called from {@link MapEntries}
      */
     public BidiMap getVirtualURLMap() {
@@ -436,7 +432,6 @@ public class ResourceResolverFactoryActi
     @Activate
     protected void activate(final ComponentContext componentContext) {
         this.componentContext = componentContext;
-        this.rootProviderEntry.setEventAdmin(this.eventAdmin);
         final Dictionary<?, ?> properties = componentContext.getProperties();
 
         final BidiMap virtuals = new TreeBidiMap();
@@ -542,11 +537,8 @@ public class ResourceResolverFactoryActi
         final BundleContext bc = componentContext.getBundleContext();
 
         // check for required property
-        final String[] required = PropertiesUtil.toStringArray(properties.get(PROP_REQUIRED_PROVIDERS));
-        this.preconds.activate(bc, required);
-
-        this.paranoidProviderHandling = PropertiesUtil.toBoolean(properties.get(PROP_PARANOID_PROVIDER_HANDLING),
-                DEFAULT_PARANOID_PROVIDER_HANDLING);
+        requiredResourceProviders = PropertiesUtil.toStringArray(properties.get(PROP_REQUIRED_PROVIDERS));
+        this.preconds.activate(bc, requiredResourceProviders, resourceProviderTracker);
 
         this.checkFactoryPreconditions();
 
@@ -562,7 +554,6 @@ public class ResourceResolverFactoryActi
     protected void deactivate() {
         this.componentContext = null;
         this.preconds.deactivate();
-        this.rootProviderEntry.setEventAdmin(null);
         this.resourceDecoratorTracker.close();
 
         this.unregisterFactory();
@@ -648,42 +639,6 @@ public class ResourceResolverFactoryActi
     }
 
     /**
-     * Bind a resource provider.
-     */
-    protected void bindResourceProvider(final ResourceProvider provider, final Map<String, Object> props) {
-        this.rootProviderEntry.bindResourceProvider(provider, props);
-        this.preconds.bindProvider(props);
-        this.addOperation(BG_OP.CHECK);
-    }
-
-    /**
-     * Unbind a resource provider.
-     */
-    protected void unbindResourceProvider(final ResourceProvider provider, final Map<String, Object> props) {
-        this.rootProviderEntry.unbindResourceProvider(provider, props);
-        this.preconds.unbindProvider(props);
-        this.addOperation(this.paranoidProviderHandling ? BG_OP.UNREGISTER_AND_CHECK : BG_OP.CHECK);
-    }
-
-    /**
-     * Bind a resource provider factory.
-     */
-    protected void bindResourceProviderFactory(final ResourceProviderFactory provider, final Map<String, Object> props) {
-        this.rootProviderEntry.bindResourceProviderFactory(provider, props);
-        this.preconds.bindProvider(props);
-        this.addOperation(BG_OP.CHECK);
-    }
-
-    /**
-     * Unbind a resource provider factory.
-     */
-    protected void unbindResourceProviderFactory(final ResourceProviderFactory provider, final Map<String, Object> props) {
-        this.rootProviderEntry.unbindResourceProviderFactory(provider, props);
-        this.preconds.unbindProvider(props);
-        this.addOperation(BG_OP.UNREGISTER_AND_CHECK);
-    }
-
-    /**
      * Bind a resource decorator.
      */
     protected void bindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
@@ -747,4 +702,15 @@ public class ResourceResolverFactoryActi
             this.coordinator.notify();
         }
     }
-}
\ No newline at end of file
+
+    public ResourceProviderTracker getResourceProviderTracker() {
+        return resourceProviderTracker;
+    }
+
+    @Override
+    public void handleEvent(Event event) {
+        if (ArrayUtils.contains(requiredResourceProviders, event.getProperty(Constants.SERVICE_PID))) {
+            this.checkFactoryPreconditions();
+        }
+    }
+}

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java Wed Oct 21 08:23:09 2015
@@ -22,10 +22,10 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceProviderFactory;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.serviceusermapping.ServiceUserMapper;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
 import org.osgi.framework.Bundle;
 
 /**
@@ -86,7 +86,7 @@ public class ResourceResolverFactoryImpl
 
         // ensure proper user name and service bundle
         authenticationInfo.put(ResourceResolverFactory.USER, userName);
-        authenticationInfo.put(ResourceProviderFactory.SERVICE_BUNDLE, this.usingBundle);
+        authenticationInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, this.usingBundle);
 
         return commonFactory.getResourceResolverInternal(authenticationInfo, false);
     }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java Wed Oct 21 08:23:09 2015
@@ -18,11 +18,14 @@
  */
 package org.apache.sling.resourceresolver.impl;
 
+import static org.apache.commons.lang.StringUtils.defaultString;
+
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -38,7 +41,6 @@ import org.apache.sling.adapter.annotati
 import org.apache.sling.adapter.annotations.Adapter;
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.adapter.SlingAdaptable;
-import org.apache.sling.api.resource.DynamicResourceProvider;
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.NonExistingResource;
 import org.apache.sling.api.resource.PersistenceException;
@@ -49,7 +51,6 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ResourceWrapper;
 import org.apache.sling.resourceresolver.impl.helper.RedirectResource;
-import org.apache.sling.resourceresolver.impl.helper.ResourceIterator;
 import org.apache.sling.resourceresolver.impl.helper.ResourceIteratorDecorator;
 import org.apache.sling.resourceresolver.impl.helper.ResourcePathIterator;
 import org.apache.sling.resourceresolver.impl.helper.ResourceResolverContext;
@@ -57,7 +58,11 @@ import org.apache.sling.resourceresolver
 import org.apache.sling.resourceresolver.impl.helper.URI;
 import org.apache.sling.resourceresolver.impl.helper.URIException;
 import org.apache.sling.resourceresolver.impl.mapping.MapEntry;
-import org.apache.sling.resourceresolver.impl.tree.params.ParsedParameters;
+import org.apache.sling.resourceresolver.impl.params.ParsedParameters;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
+import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
+import org.apache.sling.resourceresolver.impl.providers.stateful.CombinedResourceProvider;
+import org.apache.sling.resourceresolver.impl.providers.stateful.ResourceProviderAuthenticator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,7 +70,7 @@ import org.slf4j.LoggerFactory;
 public class ResourceResolverImpl extends SlingAdaptable implements ResourceResolver {
 
     /** Default logger */
-    private final Logger logger = LoggerFactory.getLogger(ResourceResolverImpl.class);
+    private static final Logger logger = LoggerFactory.getLogger(ResourceResolverImpl.class);
 
     private static final Map<String, String> EMPTY_PARAMETERS = Collections.emptyMap();
 
@@ -100,16 +105,46 @@ public class ResourceResolverImpl extend
     /** Resource resolver context. */
     private final ResourceResolverContext context;
 
+    private final CombinedResourceProvider provider;
+
+    private final Map<String, Object> authenticationInfo;
+
     private volatile Exception closedResolverException;
 
-    /**
-     * The resource resolver context.
-     */
-    public ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory,
-            final ResourceResolverContext ctx) {
+    public ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo) throws LoginException {
+        this(factory, isAdmin, authenticationInfo, factory.getResourceProviderTracker().getResourceProviderStorage());
+    }
+
+    ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo, final List<ResourceProviderHandler> handlers) throws LoginException {
+        this(factory, isAdmin, authenticationInfo, new ResourceProviderStorage(handlers));
+    }
+
+    ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo, final ResourceProviderStorage storage) throws LoginException {
         this.factory = factory;
-        this.context = ctx;
-        this.factory.register(this, ctx);
+        this.authenticationInfo = authenticationInfo;
+        this.provider = createProvider(storage);
+        this.context = new ResourceResolverContext(isAdmin);
+        this.factory.register(this, context);
+    }
+
+    private ResourceResolverImpl(final ResourceResolverImpl resolver, final Map<String, Object> authenticationInfo) throws LoginException {
+        this.factory = resolver.factory;
+        this.authenticationInfo = new HashMap<String, Object>();
+        if (resolver.authenticationInfo != null) {
+            this.authenticationInfo.putAll(resolver.authenticationInfo);
+        }
+        if (authenticationInfo != null) {
+            this.authenticationInfo.putAll(authenticationInfo);
+        }
+        this.provider = createProvider(factory.getResourceProviderTracker().getResourceProviderStorage());
+        this.context = new ResourceResolverContext(resolver.context.isAdmin());
+        this.factory.register(this, context);
+    }
+
+    private CombinedResourceProvider createProvider(ResourceProviderStorage storage) throws LoginException {
+        final ResourceProviderAuthenticator authenticator = new ResourceProviderAuthenticator(this, authenticationInfo, this.factory.getResourceAccessSecurityTracker());
+        authenticator.authenticateAll(storage.getAuthRequiredHandlers());
+        return new CombinedResourceProvider(storage, this, authenticator);
     }
 
     /**
@@ -121,22 +156,8 @@ public class ResourceResolverImpl extend
         // ensure resolver is still live
         checkClosed();
 
-        // create the merged map
-        final Map<String, Object> newAuthenticationInfo = new HashMap<String, Object>();
-        if (this.context.getAuthenticationInfo() != null) {
-            newAuthenticationInfo.putAll(this.context.getAuthenticationInfo());
-        }
-        if (authenticationInfo != null) {
-            newAuthenticationInfo.putAll(authenticationInfo);
-        }
-
-        // create new context
-        final ResourceResolverContext newContext = new ResourceResolverContext(this.context.isAdmin(),
-                newAuthenticationInfo, factory.getResourceAccessSecurityTracker());
-        this.factory.getRootProviderEntry().loginToRequiredFactories(newContext);
-
         // create a regular resource resolver
-        return new ResourceResolverImpl(this.factory, newContext);
+        return new ResourceResolverImpl(this, authenticationInfo);
     }
 
     /**
@@ -144,7 +165,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public boolean isLive() {
-        return !this.isClosed.get() && this.context.isLive() && this.factory.isLive();
+        return !this.isClosed.get() && this.provider.isLive() && this.factory.isLive();
     }
 
     /**
@@ -157,6 +178,8 @@ public class ResourceResolverImpl extend
         }
         if ( this.isClosed.compareAndSet(false, true)) {
             this.factory.unregister(this, this.context);
+            provider.logout();
+            context.close();
         }
     }
 
@@ -186,7 +209,7 @@ public class ResourceResolverImpl extend
     @Override
     public Iterator<String> getAttributeNames() {
         checkClosed();
-        return this.factory.getRootProviderEntry().getAttributeNames(this.context, this);
+        return this.provider.getAttributeNames().iterator();
     }
 
     /**
@@ -199,7 +222,7 @@ public class ResourceResolverImpl extend
             throw new NullPointerException("name");
         }
 
-        return this.factory.getRootProviderEntry().getAttribute(this.context, this, name);
+        return this.provider.getAttribute(name);
     }
 
     // ---------- resolving resources
@@ -611,7 +634,7 @@ public class ResourceResolverImpl extend
     @Override
     public Resource getResource(String path) {
         checkClosed();
-        final Resource result = this.getResourceInternal(path);
+        final Resource result = this.getResourceInternal(null, path);
         return result;
     }
 
@@ -628,7 +651,7 @@ public class ResourceResolverImpl extend
             absolutePath = appendToPath(base.getPath(), absolutePath);
         }
 
-        final Resource result = getResourceInternal(absolutePath);
+        final Resource result = getResourceInternal(base, absolutePath);
         return result;
     }
 
@@ -643,13 +666,13 @@ public class ResourceResolverImpl extend
     private static String appendToPath(final String pathWithParameters, final String segmentToAppend) {
         final ParsedParameters parsed = new ParsedParameters(pathWithParameters);
         if (parsed.getParametersString() == null) {
-            return String.format("%s/%s", parsed.getRawPath(), segmentToAppend);
+            return new StringBuilder(parsed.getRawPath()).append('/').append(segmentToAppend).toString();
         } else {
-            return String.format("%s/%s%s", parsed.getRawPath(), segmentToAppend, parsed.getParametersString());
+            return new StringBuilder(parsed.getRawPath()).append('/').append(segmentToAppend).append(parsed.getParametersString()).toString();
         }
     }
 
-    private Resource getResourceInternal(String path) {
+    private Resource getResourceInternal(Resource parent, String path) {
 
         Resource result = null;
         if ( path != null ) {
@@ -657,7 +680,7 @@ public class ResourceResolverImpl extend
             if (path.startsWith("/")) {
                 ParsedParameters parsedPath = new ParsedParameters(path);
                 path = ResourceUtil.normalize(parsedPath.getRawPath());
-                result = (path != null) ? getAbsoluteResourceInternal(path, parsedPath.getParameters(), false) : null;
+                result = (path != null) ? getAbsoluteResourceInternal(parent, path, parsedPath.getParameters(), false) : null;
                 if (result != null) {
                     result = this.factory.getResourceDecoratorTracker().decorate(result);
                 }
@@ -690,8 +713,7 @@ public class ResourceResolverImpl extend
         if (parent instanceof ResourceWrapper) {
             return listChildren(((ResourceWrapper) parent).getResource());
         }
-        return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
-                new ResourceIterator(this.context, parent, this.factory.getRootProviderEntry()));
+        return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(), this.provider.listChildren(parent));
     }
 
     /**
@@ -721,8 +743,7 @@ public class ResourceResolverImpl extend
         checkClosed();
 
         return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
-                this.factory.getRootProviderEntry().findResources(this.context, this, query,
-                        language == null ? DEFAULT_QUERY_LANGUAGE : language));
+                provider.findResources(query, defaultString(language, DEFAULT_QUERY_LANGUAGE)));
     }
 
     /**
@@ -734,8 +755,7 @@ public class ResourceResolverImpl extend
             throws SlingException {
         checkClosed();
 
-        return this.factory.getRootProviderEntry().queryResources(this.context, this, query,
-                language == null ? DEFAULT_QUERY_LANGUAGE : language);
+        return provider.queryResources(query, defaultString(language, DEFAULT_QUERY_LANGUAGE));
     }
 
     /**
@@ -746,12 +766,12 @@ public class ResourceResolverImpl extend
         checkClosed();
 
         // Try auth info first
-        if ( this.context.getAuthenticationInfo() != null ) {
-            final Object impUser = this.context.getAuthenticationInfo().get(ResourceResolverFactory.USER_IMPERSONATION);
+        if ( this.authenticationInfo != null ) {
+            final Object impUser = this.authenticationInfo.get(ResourceResolverFactory.USER_IMPERSONATION);
             if ( impUser != null ) {
                 return impUser.toString();
             }
-            final Object user = this.context.getAuthenticationInfo().get(ResourceResolverFactory.USER);
+            final Object user = this.authenticationInfo.get(ResourceResolverFactory.USER);
             if ( user != null ) {
                 return user.toString();
             }
@@ -785,7 +805,7 @@ public class ResourceResolverImpl extend
     private Session getSession() {
         if ( !this.searchedSession ) {
             this.searchedSession = true;
-            this.cachedSession = this.factory.getRootProviderEntry().adaptTo(this.context, Session.class);
+            this.cachedSession = this.provider.adaptTo(Session.class);
         }
         return this.cachedSession;
     }
@@ -803,7 +823,7 @@ public class ResourceResolverImpl extend
         if (type == Session.class) {
             return (AdapterType) getSession();
         }
-        final AdapterType result = this.factory.getRootProviderEntry().adaptTo(this.context, type);
+        final AdapterType result = this.provider.adaptTo(type);
         if ( result != null ) {
             return result;
         }
@@ -871,7 +891,7 @@ public class ResourceResolverImpl extend
             final ResourcePathIterator it = new ResourcePathIterator(absPath);
             while (it.hasNext() && resource == null) {
                 curPath = it.next();
-                resource = getAbsoluteResourceInternal(curPath, parameters, true);
+                resource = getAbsoluteResourceInternal(null, curPath, parameters, true);
             }
         } catch (final Exception ex) {
             throw new SlingException("Problem trying " + curPath + " for request path " + absPath, ex);
@@ -893,7 +913,7 @@ public class ResourceResolverImpl extend
 
             // no direct resource found, so we have to drill down into the
             // resource tree to find a match
-            resource = getAbsoluteResourceInternal("/", parameters, true);
+            resource = getAbsoluteResourceInternal(null, "/", parameters, true);
             final StringBuilder resolutionPath = new StringBuilder();
             final StringTokenizer tokener = new StringTokenizer(absPath, "/");
             while (resource != null && tokener.hasMoreTokens()) {
@@ -953,7 +973,7 @@ public class ResourceResolverImpl extend
         } else {
             path = parent.getPath() + '/' + childName;
         }
-        Resource child = getAbsoluteResourceInternal( ResourceUtil.normalize(path), EMPTY_PARAMETERS, true );
+        Resource child = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(path), EMPTY_PARAMETERS, true );
         if (child != null) {
             final String alias = ResourceResolverContext.getProperty(child, PROP_REDIRECT_INTERNAL);
             if (alias != null) {
@@ -981,7 +1001,7 @@ public class ResourceResolverImpl extend
                     } else {
                         aliasPath = parent.getPath() + '/' + aliasName;
                     }
-                    final Resource aliasedChild = getAbsoluteResourceInternal( ResourceUtil.normalize(aliasPath), EMPTY_PARAMETERS, true );
+                    final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), EMPTY_PARAMETERS, true );
                     logger.debug("getChildInternal: Found Resource {} with alias {} to use", aliasedChild, childName);
                     return aliasedChild;
                 }
@@ -997,7 +1017,7 @@ public class ResourceResolverImpl extend
                         for (final String alias : aliases) {
                             if (childName.equals(alias)) {
                                 logger.debug("getChildInternal: Found Resource {} with alias {} to use", child, childName);
-                                final Resource aliasedChild = getAbsoluteResourceInternal( ResourceUtil.normalize(child.getPath()) , EMPTY_PARAMETERS, true);
+                                final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(child.getPath()) , EMPTY_PARAMETERS, true);
                                 return aliasedChild;
                             }
                         }
@@ -1014,9 +1034,15 @@ public class ResourceResolverImpl extend
     /**
      * Creates a resource with the given path if existing
      */
-    private Resource getAbsoluteResourceInternal(final String path, final Map<String, String> parameters, final boolean isResolve) {
+    private Resource getAbsoluteResourceInternal(final Resource parent, final String path, final Map<String, String> parameters, final boolean isResolve) {
+        final Resource parentToUse;
+        if (parent != null && path.startsWith(parent.getPath())) {
+            parentToUse = parent;
+        } else {
+            parentToUse = null;
+        }
 
-        final Resource resource = this.factory.getRootProviderEntry().getResource(this.context, this, path, parameters, isResolve);
+        final Resource resource = this.provider.getResource(path, parentToUse, parameters, isResolve);
         if (resource != null) {
             resource.getResourceMetadata().setResolutionPath(path);
             resource.getResourceMetadata().setParameterMap(parameters);
@@ -1135,7 +1161,7 @@ public class ResourceResolverImpl extend
             return;
         }
         // if resource is null, we get an NPE as stated in the API
-        this.factory.getRootProviderEntry().delete(this.context, this, resource);
+        this.provider.delete(resource);
     }
 
     /**
@@ -1160,9 +1186,14 @@ public class ResourceResolverImpl extend
         }
         // experimental code for handling synthetic resources
         if ( ResourceUtil.isSyntheticResource(parent) ) {
-            this.create(parent.getParent(), parent.getName(), null);
+            Resource grandParent = parent.getParent();
+            if (grandParent != null) {
+                this.create(grandParent, parent.getName(), null);
+            } else {
+                throw new IllegalArgumentException("Can't create child on a synthetic root");
+            }
         }
-        final Resource rsrc = this.factory.getRootProviderEntry().create(this.context, this, path, properties);
+        final Resource rsrc = this.provider.create(path, properties);
         return this.factory.getResourceDecoratorTracker().decorate(rsrc);
     }
 
@@ -1171,7 +1202,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void revert() {
-        this.context.revert(this);
+        this.provider.revert();
     }
 
     /**
@@ -1179,7 +1210,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void commit() throws PersistenceException {
-        this.context.commit(this);
+        this.provider.commit();
     }
 
     /**
@@ -1187,7 +1218,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public boolean hasChanges() {
-        return this.context.hasChanges(this);
+        return this.provider.hasChanges();
     }
 
     /**
@@ -1253,22 +1284,25 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void refresh() {
-        this.context.refresh();
+        this.provider.refresh();
     }
 
     @Override
     public Resource getParent(final Resource child) {
-        // TODO Auto-generated method stub
-        return this.getResource(ResourceUtil.getParent(child.getPath()));
+        return this.provider.getParent(child);
     }
 
     @Override
     public void copy(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
-        throw new UnsupportedOperationException();
+        if (!this.provider.copy(srcAbsPath, destAbsPath)) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     @Override
     public void move(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
-        throw new UnsupportedOperationException();
+        if (!this.provider.move(srcAbsPath, destAbsPath)) {
+            throw new UnsupportedOperationException();
+        }
     }
 }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java?rev=1709747&r1=1709746&r2=1709747&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java Wed Oct 21 08:23:09 2015
@@ -17,55 +17,23 @@
  */
 package org.apache.sling.resourceresolver.impl.helper;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.sling.api.resource.DynamicResourceProvider;
 import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ModifyingResourceProvider;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.RefreshableResourceProvider;
 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.ResourceResolverFactory;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
 
 /**
- * This class keeps track of the used resource providers for a
- * resource resolver.
  * Like a resource resolver itself, this class is not thread safe.
  */
 public class ResourceResolverContext {
 
-    /** A map of all used providers created by a factory. */
-    private final Map<Long, ResourceProvider> providers = new HashMap<Long, ResourceProvider>();
-
-    /** A set of all dynamic providers (for closing them later on) */
-    private final Set<DynamicResourceProvider> dynamicProviders = new HashSet<DynamicResourceProvider>();
-
-    /** A set of all refreshable providers */
-    private final Set<RefreshableResourceProvider> refreshableProviders = new HashSet<RefreshableResourceProvider>();
-
-    /** A set of all modifying providers */
-    private final Set<ModifyingResourceProvider> modifyingProviders = new HashSet<ModifyingResourceProvider>();
-
     /** Is this a resource resolver for an admin? */
     private final boolean isAdmin;
 
-    /**
-     * The original authentication information - this is used for cloning and lazy logins.
-     */
-    private final Map<String, Object> originalAuthInfo;
-
-    /** service tracker for ResourceAccessSecurity service */
-    private final ResourceAccessSecurityTracker resourceAccessSecurityTracker;
-
     /** Resource type resource resolver (admin resolver) */
     private ResourceResolver resourceTypeResourceResolver;
 
@@ -75,83 +43,19 @@ public class ResourceResolverContext {
     /**
      * Create a new resource resolver context.
      */
-    public ResourceResolverContext(final boolean isAdmin, final Map<String, Object> originalAuthInfo, final ResourceAccessSecurityTracker resourceAccessSecurityTracker) {
+    public ResourceResolverContext(final boolean isAdmin) {
         this.isAdmin = isAdmin;
-        this.originalAuthInfo = originalAuthInfo;
-        this.resourceAccessSecurityTracker = resourceAccessSecurityTracker;
     }
 
-    /**
-     * Is this an admin resource resolver.
-     */
     public boolean isAdmin() {
-        return this.isAdmin;
-    }
-
-    /**
-     * Return the authentication info.
-     */
-    public Map<String, Object> getAuthenticationInfo() {
-        return this.originalAuthInfo;
-    }
-
-    /**
-     * Add a new resource provider
-     * @param key      The unique key of the provider
-     * @param provider The provider.
-     */
-    public void addFactoryResourceProvider(final Long key, final ResourceProvider provider) {
-        this.providers.put(key, provider);
-        if (provider instanceof DynamicResourceProvider) {
-            this.dynamicProviders.add((DynamicResourceProvider) provider);
-        }
-        if (provider instanceof ModifyingResourceProvider) {
-            this.modifyingProviders.add((ModifyingResourceProvider) provider);
-        }
-        if (provider instanceof RefreshableResourceProvider) {
-            this.refreshableProviders.add((RefreshableResourceProvider)provider);
-        }
-    }
-
-    /**
-     * Return a resource provider for a given key
-     * @param key The unique key of a provider
-     * @return The resource provider or <code>null</code>
-     */
-    public ResourceProvider getFactoryResourceProvider(final Long key) {
-        return this.providers.get(key);
-    }
-
-    /**
-     * Check all active dynamic resource providers.
-     */
-    public boolean isLive() {
-        boolean result = true;
-        for (final DynamicResourceProvider provider : this.dynamicProviders) {
-            if (!provider.isLive()) {
-                result = false;
-                break;
-            }
-        }
-        return result;
+        return isAdmin;
     }
 
     /**
      * Close all dynamic resource providers.
      */
     public void close() {
-        if ( this.isClosed.compareAndSet(false, true)) {
-            for (final DynamicResourceProvider provider : this.dynamicProviders) {
-                try {
-                    provider.close();
-                } catch ( final Throwable t) {
-                    // the provider might already be terminated (bundle stopped etc.)
-                    // so we ignore anything from here
-                }
-            }
-            this.dynamicProviders.clear();
-            this.providers.clear();
-            this.refreshableProviders.clear();
+        if (this.isClosed.compareAndSet(false, true)) {
             if ( this.resourceTypeResourceResolver != null ) {
                 try {
                     this.resourceTypeResourceResolver.close();
@@ -164,52 +68,7 @@ public class ResourceResolverContext {
         }
     }
 
-    /**
-     * Revert all transient changes.
-     */
-    public void revert(final ResourceResolver resolver) {
-        for(final ModifyingResourceProvider provider : this.modifyingProviders) {
-            provider.revert(resolver);
-        }
-    }
-
-    /**
-     * Commit all transient changes
-     */
-    public void commit(final ResourceResolver resolver) throws PersistenceException {
-        for(final ModifyingResourceProvider provider : this.modifyingProviders) {
-            provider.commit(resolver);
-        }
-    }
-
-    /**
-     * Do we have changes?
-     */
-    public boolean hasChanges(final ResourceResolver resolver) {
-        for(final ModifyingResourceProvider provider : this.modifyingProviders) {
-            if ( provider.hasChanges(resolver) ) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Refresh
-     */
-    public void refresh() {
-        for(final RefreshableResourceProvider provider : this.refreshableProviders) {
-            provider.refresh();
-        }
-    }
-
-    /**
-     * get's the ServiceTracker of the ResourceAccessSecurity service
-     */
-    public ResourceAccessSecurityTracker getResourceAccessSecurityTracker () {
-        return resourceAccessSecurityTracker;
-    }
-
+    @SuppressWarnings("deprecation")
     private ResourceResolver getResourceTypeResourceResolver(
             final ResourceResolverFactory factory,
             final ResourceResolver resolver) {

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java?rev=1709747&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java Wed Oct 21 08:23:09 2015
@@ -0,0 +1,231 @@
+/*
+ * 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.resourceresolver.impl.legacy;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.sling.api.resource.AttributableResourceProvider;
+import org.apache.sling.api.resource.DynamicResourceProvider;
+import org.apache.sling.api.resource.ModifyingResourceProvider;
+import org.apache.sling.api.resource.ParametrizableResourceProvider;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.QueriableResourceProvider;
+import org.apache.sling.api.resource.RefreshableResourceProvider;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.spi.resource.provider.JCRQueryProvider;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
+
+@SuppressWarnings("deprecation")
+public class LegacyResourceProviderAdapter extends ResourceProvider<Object> {
+
+    private final org.apache.sling.api.resource.ResourceProvider rp;
+
+    private final String[] languages;
+
+    private final boolean ownsRoot;
+
+    public LegacyResourceProviderAdapter(org.apache.sling.api.resource.ResourceProvider rp, String[] languages, boolean ownsRoot) {
+        this.rp = rp;
+        this.languages = languages;
+        this.ownsRoot = ownsRoot;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Resource getResource(ResolveContext<Object> ctx, String path, Resource parent) {
+        Resource resourceCandidate;
+        if (rp instanceof ParametrizableResourceProvider) {
+            resourceCandidate = ((ParametrizableResourceProvider) rp).getResource(ctx.getResourceResolver(), path,
+                    ctx.getResolveParameters());
+        } else {
+            resourceCandidate = rp.getResource(ctx.getResourceResolver(), path);
+        }
+
+        ResourceProvider<?> parentProvider = ctx.getParentResourceProvider();
+        ResolveContext parentCtx = ctx.getParentResolveContext();
+        // Ask the parent provider
+        if (resourceCandidate == null && !ownsRoot && parentProvider != null) {
+            return parentProvider.getResource(parentCtx, path, parent);
+        }
+
+        // Support the INTERNAL_CONTINUE_RESOLVING flag
+        Resource fallbackResource = resourceCandidate;
+        if (resourceCandidate != null && parentProvider != null && isContinueResolving(resourceCandidate)) {
+            resourceCandidate = ctx.getParentResourceProvider().getResource(parentCtx, path, parent);
+        }
+        if (resourceCandidate != null) {
+            return resourceCandidate;
+        } else {
+            return fallbackResource;
+        }
+    }
+
+    private boolean isContinueResolving(Resource resource) {
+        return resource.getResourceMetadata() != null
+                && resource.getResourceMetadata().containsKey(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
+        Iterator<Resource> children = rp.listChildren(parent);
+        if (children == null && !ownsRoot && ctx.getParentResourceProvider() != null) {
+            children = ctx.getParentResourceProvider().listChildren((ResolveContext) ctx.getParentResolveContext(),
+                    parent);
+        }
+        return children;
+    }
+
+    @Override
+    public void refresh(final @Nonnull ResolveContext<Object> ctx) {
+        if (rp instanceof RefreshableResourceProvider) {
+            ((RefreshableResourceProvider) rp).refresh();
+        }
+    }
+
+    @Override
+    public @CheckForNull JCRQueryProvider<Object> getJCRQueryProvider() {
+        if (rp instanceof QueriableResourceProvider) {
+            return new JCRQueryProviderAdapter((QueriableResourceProvider) rp, languages);
+        } else {
+            return super.getJCRQueryProvider();
+        }
+    }
+
+    @Override
+    public Collection<String> getAttributeNames(final @Nonnull ResolveContext<Object> ctx) {
+        if (rp instanceof AttributableResourceProvider) {
+            return ((AttributableResourceProvider) rp).getAttributeNames(ctx.getResourceResolver());
+        } else {
+            return super.getAttributeNames(ctx);
+        }
+    }
+
+    @Override
+    public Object getAttribute(final @Nonnull ResolveContext<Object> ctx, final @Nonnull String name) {
+        if (rp instanceof AttributableResourceProvider) {
+            return ((AttributableResourceProvider) rp).getAttribute(ctx.getResourceResolver(), name);
+        } else {
+            return super.getAttribute(ctx, name);
+        }
+    }
+
+    @Override
+    public boolean isLive(final @Nonnull ResolveContext<Object> ctx) {
+        if (rp instanceof DynamicResourceProvider) {
+            return ((DynamicResourceProvider) rp).isLive();
+        } else {
+            return super.isLive(ctx);
+        }
+    }
+
+    @Override
+    public void logout(final @Nonnull Object state) {
+        if (rp instanceof DynamicResourceProvider) {
+            ((DynamicResourceProvider) rp).close();
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Resource create(final @Nonnull ResolveContext<Object> ctx, final String path,
+            final Map<String, Object> properties) throws PersistenceException {
+        Resource createdResource = null;
+        if (rp instanceof ModifyingResourceProvider) {
+            createdResource = ((ModifyingResourceProvider) rp).create(ctx.getResourceResolver(), path, properties);
+        }
+        if (createdResource == null && !ownsRoot && ctx.getParentResourceProvider() != null) {
+            createdResource = ctx.getParentResourceProvider().create((ResolveContext) ctx.getParentResolveContext(),
+                    path, properties);
+        }
+        return createdResource;
+    }
+
+    @Override
+    public void delete(final @Nonnull ResolveContext<Object> ctx, final @Nonnull Resource resource)
+            throws PersistenceException {
+        if (rp instanceof ModifyingResourceProvider) {
+            ((ModifyingResourceProvider) rp).delete(ctx.getResourceResolver(), resource.getPath());
+        } else {
+            super.delete(ctx, resource);
+        }
+    }
+
+    @Override
+    public void revert(final @Nonnull ResolveContext<Object> ctx) {
+        if (rp instanceof ModifyingResourceProvider) {
+            ((ModifyingResourceProvider) rp).revert(ctx.getResourceResolver());
+        } else {
+            super.revert(ctx);
+        }
+    }
+
+    @Override
+    public void commit(final @Nonnull ResolveContext<Object> ctx) throws PersistenceException {
+        if (rp instanceof ModifyingResourceProvider) {
+            ((ModifyingResourceProvider) rp).commit(ctx.getResourceResolver());
+        } else {
+            super.commit(ctx);
+        }
+    }
+
+    @Override
+    public boolean hasChanges(final @Nonnull ResolveContext<Object> ctx) {
+        if (rp instanceof ModifyingResourceProvider) {
+            return ((ModifyingResourceProvider) rp).hasChanges(ctx.getResourceResolver());
+        } else {
+            return super.hasChanges(ctx);
+        }
+    }
+
+    private static class JCRQueryProviderAdapter implements JCRQueryProvider<Object> {
+
+        private final QueriableResourceProvider rp;
+        
+        private final String[] languages;
+        
+        public JCRQueryProviderAdapter(QueriableResourceProvider rp, String[] languages) {
+            this.rp = rp;
+            this.languages = languages;
+        }
+
+        @Override
+        public String[] getSupportedLanguages(ResolveContext<Object> ctx) {
+            return languages;
+        }
+
+        @Override
+        public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) {
+            return rp.findResources(ctx.getResourceResolver(), query, language);
+        }
+
+        @Override
+        public Iterator<ValueMap> queryResources(ResolveContext<Object> ctx, String query, String language) {
+            return rp.queryResources(ctx.getResourceResolver(), query, language);
+        }
+    }
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java?rev=1709747&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java Wed Oct 21 08:23:09 2015
@@ -0,0 +1,155 @@
+/*
+ * 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.resourceresolver.impl.legacy;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProviderFactory;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.spi.resource.provider.JCRQueryProvider;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
+
+@SuppressWarnings({ "deprecation", "rawtypes", "unchecked" })
+public class LegacyResourceProviderFactoryAdapter extends ResourceProvider<LegacyResourceProviderAdapter> {
+
+    private final ResourceProviderFactory rpFactory;
+
+    private final String[] languages;
+
+    private final boolean ownsRoot;
+
+    public LegacyResourceProviderFactoryAdapter(ResourceProviderFactory rpFactory, String[] languages, boolean ownsRoot) {
+        this.rpFactory = rpFactory;
+        this.languages = languages;
+        this.ownsRoot = ownsRoot;
+    }
+
+    @Nonnull
+    public LegacyResourceProviderAdapter authenticate(final @Nonnull Map<String, Object> authenticationInfo)
+            throws LoginException {
+        return new LegacyResourceProviderAdapter(rpFactory.getResourceProvider(authenticationInfo), languages, ownsRoot);
+    }
+
+    public void logout(final @Nonnull LegacyResourceProviderAdapter state) {
+        state.logout(null);
+    }
+
+    @Override
+    public Resource getResource(ResolveContext<LegacyResourceProviderAdapter> ctx, String path, Resource parent) {
+        return ctx.getProviderState().getResource((ResolveContext) ctx, path, parent);
+    }
+
+    @Override
+    public Iterator<Resource> listChildren(ResolveContext<LegacyResourceProviderAdapter> ctx, Resource parent) {
+        return ctx.getProviderState().listChildren((ResolveContext) ctx, parent);
+    }
+
+    @Override
+    public void refresh(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
+        ctx.getProviderState().refresh((ResolveContext) ctx);
+    }
+
+    @Override
+    public @CheckForNull JCRQueryProvider<LegacyResourceProviderAdapter> getJCRQueryProvider() {
+        if (ArrayUtils.isEmpty(languages)) {
+            return super.getJCRQueryProvider();
+        } else {
+            return new JCRQueryProviderAdapter(languages);
+        }
+    }
+
+    @Override
+    public Collection<String> getAttributeNames(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
+        return ctx.getProviderState().getAttributeNames((ResolveContext) ctx);
+    }
+
+    @Override
+    public Object getAttribute(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx,
+            final @Nonnull String name) {
+        return ctx.getProviderState().getAttribute((ResolveContext) ctx, name);
+    }
+
+    @Override
+    public boolean isLive(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
+        return ctx.getProviderState().isLive((ResolveContext) ctx);
+    }
+
+    @Override
+    public Resource create(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx, final String path,
+            final Map<String, Object> properties) throws PersistenceException {
+        return ctx.getProviderState().create((ResolveContext) ctx, path, properties);
+    }
+
+    @Override
+    public void delete(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx,
+            final @Nonnull Resource resource) throws PersistenceException {
+        ctx.getProviderState().delete((ResolveContext) ctx, resource);
+    }
+
+    @Override
+    public void revert(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
+        ctx.getProviderState().revert((ResolveContext) ctx);
+    }
+
+    @Override
+    public void commit(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) throws PersistenceException {
+        ctx.getProviderState().commit((ResolveContext) ctx);
+    }
+
+    @Override
+    public boolean hasChanges(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
+        return ctx.getProviderState().hasChanges((ResolveContext) ctx);
+    }
+
+    private static class JCRQueryProviderAdapter implements JCRQueryProvider<LegacyResourceProviderAdapter> {
+
+        private final String[] languages;
+
+        public JCRQueryProviderAdapter(String[] languages) {
+            this.languages = languages;
+        }
+
+        @Override
+        public String[] getSupportedLanguages(ResolveContext<LegacyResourceProviderAdapter> ctx) {
+            return languages;
+        }
+
+        @Override
+        public Iterator<Resource> findResources(ResolveContext<LegacyResourceProviderAdapter> ctx, String query,
+                String language) {
+            return ctx.getProviderState().getJCRQueryProvider().findResources((ResolveContext) ctx, query, language);
+        }
+
+        @Override
+        public Iterator<ValueMap> queryResources(ResolveContext<LegacyResourceProviderAdapter> ctx, String query,
+                String language) {
+            return ctx.getProviderState().getJCRQueryProvider().queryResources((ResolveContext) ctx, query, language);
+        }
+    }
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java?rev=1709747&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java Wed Oct 21 08:23:09 2015
@@ -0,0 +1,169 @@
+/*
+ * 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.resourceresolver.impl.legacy;
+
+import static org.apache.sling.api.resource.QueriableResourceProvider.LANGUAGES;
+import static org.apache.sling.api.resource.ResourceProvider.OWNS_ROOTS;
+import static org.apache.sling.api.resource.ResourceProvider.ROOTS;
+import static org.apache.sling.api.resource.ResourceProvider.USE_RESOURCE_ACCESS_SECURITY;
+import static org.apache.sling.api.resource.ResourceProviderFactory.PROPERTY_REQUIRED;
+import static org.apache.sling.commons.osgi.PropertiesUtil.toBoolean;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ADAPTABLE;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ATTRIBUTABLE;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_AUTHENTICATE;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_MODIFIABLE;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_NAME;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_REFRESHABLE;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ROOT;
+import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_USE_RESOURCE_ACCESS_SECURITY;
+import static org.osgi.framework.Constants.SERVICE_PID;
+import static org.osgi.framework.Constants.SERVICE_RANKING;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.References;
+import org.apache.sling.api.adapter.Adaptable;
+import org.apache.sling.api.resource.AttributableResourceProvider;
+import org.apache.sling.api.resource.ModifyingResourceProvider;
+import org.apache.sling.api.resource.RefreshableResourceProvider;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceProviderFactory;
+import org.apache.sling.api.resource.runtime.dto.AuthType;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+@SuppressWarnings("deprecation")
+@Component(immediate = true)
+@References({
+        @Reference(name = "ResourceProvider", referenceInterface = ResourceProvider.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC),
+        @Reference(name = "ResourceProviderFactory", referenceInterface = ResourceProviderFactory.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC) })
+public class LegacyResourceProviderWhiteboard {
+
+    public static final String ORIGINAL_SERVICE_PID = "original.service.pid";
+
+    private Map<Object, List<ServiceRegistration>> registrations = new HashMap<Object, List<ServiceRegistration>>();
+
+    protected void bindResourceProvider(ServiceReference ref) {
+        BundleContext bundleContext = ref.getBundle().getBundleContext();
+        ResourceProvider provider = (ResourceProvider) bundleContext.getService(ref);
+        String[] propertyNames = ref.getPropertyKeys();
+        boolean ownsRoot = toBoolean(ref.getProperty(OWNS_ROOTS), false);
+
+        List<ServiceRegistration> newServices = new ArrayList<ServiceRegistration>();
+        for (String path : PropertiesUtil.toStringArray(ref.getProperty(ROOTS), new String[0])) {
+            Dictionary<String, Object> newProps = new Hashtable<String, Object>();
+            newProps.put(PROPERTY_AUTHENTICATE, AuthType.no.toString());
+            newProps.put(PROPERTY_MODIFIABLE, provider instanceof ModifyingResourceProvider);
+            newProps.put(PROPERTY_ADAPTABLE, provider instanceof Adaptable);
+            newProps.put(PROPERTY_ATTRIBUTABLE, provider instanceof AttributableResourceProvider);
+            newProps.put(PROPERTY_REFRESHABLE, provider instanceof RefreshableResourceProvider);
+            newProps.put(PROPERTY_NAME, provider.getClass().getName());
+            newProps.put(PROPERTY_ROOT, normalizePath(path));
+            if (ArrayUtils.contains(propertyNames, SERVICE_PID)) {
+                newProps.put(ORIGINAL_SERVICE_PID, ref.getProperty(SERVICE_PID));
+            }
+            if (ArrayUtils.contains(propertyNames, USE_RESOURCE_ACCESS_SECURITY)) {
+                newProps.put(PROPERTY_USE_RESOURCE_ACCESS_SECURITY, ref.getProperty(USE_RESOURCE_ACCESS_SECURITY));
+            }
+            if (ArrayUtils.contains(propertyNames, SERVICE_RANKING)) {
+                newProps.put(SERVICE_RANKING, ref.getProperty(SERVICE_RANKING));
+            }
+
+            String[] languages = PropertiesUtil.toStringArray(ref.getProperty(LANGUAGES), new String[0]);
+            ServiceRegistration reg = bundleContext.registerService(
+                    org.apache.sling.spi.resource.provider.ResourceProvider.class.getName(),
+                    new LegacyResourceProviderAdapter(provider, languages, ownsRoot), newProps);
+            newServices.add(reg);
+        }
+        registrations.put(provider, newServices);
+    }
+
+    protected void unbindResourceProvider(final ResourceProvider provider, final Map<String, Object> props) {
+        for (ServiceRegistration r : registrations.remove(provider)) {
+            r.unregister();
+        }
+    }
+
+    protected void bindResourceProviderFactory(ServiceReference ref) {
+        BundleContext bundleContext = ref.getBundle().getBundleContext();
+        ResourceProviderFactory factory = (ResourceProviderFactory) bundleContext.getService(ref);
+        String[] propertyNames = ref.getPropertyKeys();
+        boolean ownsRoot = toBoolean(ref.getProperty(OWNS_ROOTS), false);
+
+        List<ServiceRegistration> newServices = new ArrayList<ServiceRegistration>();
+        for (String path : PropertiesUtil.toStringArray(ref.getProperty(ROOTS), new String[0])) {
+            Dictionary<String, Object> newProps = new Hashtable<String, Object>();
+            if (PropertiesUtil.toBoolean(ref.getProperty(PROPERTY_REQUIRED), false)) {
+                newProps.put(PROPERTY_AUTHENTICATE, AuthType.required.toString());
+            } else {
+                newProps.put(PROPERTY_AUTHENTICATE, AuthType.lazy.toString());
+            }
+            newProps.put(PROPERTY_MODIFIABLE, true);
+            newProps.put(PROPERTY_ADAPTABLE, true);
+            newProps.put(PROPERTY_ATTRIBUTABLE, true);
+            newProps.put(PROPERTY_REFRESHABLE, true);
+            newProps.put(PROPERTY_NAME, factory.getClass().getName());
+            newProps.put(PROPERTY_ROOT, normalizePath(path));
+            if (ArrayUtils.contains(propertyNames, SERVICE_PID)) {
+                newProps.put(ORIGINAL_SERVICE_PID, ref.getProperty(SERVICE_PID));
+            }
+            if (ArrayUtils.contains(propertyNames, USE_RESOURCE_ACCESS_SECURITY)) {
+                newProps.put(PROPERTY_USE_RESOURCE_ACCESS_SECURITY, ref.getProperty(USE_RESOURCE_ACCESS_SECURITY));
+            }
+            if (ArrayUtils.contains(propertyNames, SERVICE_RANKING)) {
+                newProps.put(SERVICE_RANKING, ref.getProperty(SERVICE_RANKING));
+            }
+            String[] languages = PropertiesUtil.toStringArray(ref.getProperty(LANGUAGES), new String[0]);
+            ServiceRegistration reg = bundleContext.registerService(
+                    org.apache.sling.spi.resource.provider.ResourceProvider.class.getName(),
+                    new LegacyResourceProviderFactoryAdapter(factory, languages, ownsRoot), newProps);
+            newServices.add(reg);
+        }
+        registrations.put(factory, newServices);
+    }
+
+    protected void unbindResourceProviderFactory(final ResourceProviderFactory factory,
+            final Map<String, Object> props) {
+        for (ServiceRegistration r : registrations.remove(factory)) {
+            r.unregister();
+        }
+    }
+
+    private static String normalizePath(String path) {
+        String result = path;
+        result = StringUtils.removeEnd(path, "/");
+        if (result != null && !result.startsWith("/")) {
+            result = "/" + result;
+        }
+        return result;
+    }
+}