You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2016/02/05 11:19:25 UTC

svn commit: r1728626 - in /sling/trunk/bundles/resourceresolver/src: main/java/org/apache/sling/resourceresolver/impl/ main/java/org/apache/sling/resourceresolver/impl/helper/ main/java/org/apache/sling/resourceresolver/impl/providers/ main/java/org/ap...

Author: cziegeler
Date: Fri Feb  5 10:19:24 2016
New Revision: 1728626

URL: http://svn.apache.org/viewvc?rev=1728626&view=rev
Log:
SLING-5470 : Resource providers might not be closed

Removed:
    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/StatefulResourceProvider.java
Modified:
    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/helper/ResourceResolverControl.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/AuthenticatedResourceProvider.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResolveContextManager.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecorator.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java
    sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/stateful/SecureResourceProviderDecoratorTest.java

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=1728626&r1=1728625&r2=1728626&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 Fri Feb  5 10:19:24 2016
@@ -61,7 +61,6 @@ import org.apache.sling.resourceresolver
 import org.apache.sling.resourceresolver.impl.mapping.MapEntry;
 import org.apache.sling.resourceresolver.impl.params.ParsedParameters;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.stateful.ResourceProviderAuthenticator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -112,9 +111,9 @@ public class ResourceResolverImpl extend
 
     ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo, final ResourceProviderStorage storage) throws LoginException {
         this.factory = factory;
+        this.context = new ResourceResolverContext(this);
         this.control = createControl(storage, authenticationInfo, isAdmin);
         this.factory.register(this, control);
-        this.context = new ResourceResolverContext(this);
     }
 
     /**
@@ -132,17 +131,28 @@ public class ResourceResolverImpl extend
         if (authenticationInfo != null) {
             authInfo.putAll(authenticationInfo);
         }
+        this.context = new ResourceResolverContext(this);
         this.control = createControl(factory.getResourceProviderTracker().getResourceProviderStorage(), authInfo, resolver.control.isAdmin());
         this.factory.register(this, control);
-        this.context = new ResourceResolverContext(this);
     }
 
-    private ResourceResolverControl createControl(ResourceProviderStorage storage, Map<String, Object> authenticationInfo, final boolean isAdmin)
+    /**
+     * Create the resource resolver control
+     * @param storage The provider storage
+     * @param authenticationInfo Current auth info
+     * @param isAdmin Is this admin?
+     * @return A control
+     * @throws LoginException If auth to the required providers fails.
+     */
+    private ResourceResolverControl createControl(final ResourceProviderStorage storage,
+            final Map<String, Object> authenticationInfo,
+            final boolean isAdmin)
     throws LoginException {
-        final ResourceProviderAuthenticator authenticator = new ResourceProviderAuthenticator(this, authenticationInfo, this.factory.getResourceAccessSecurityTracker());
-        final ResourceResolverControl provider = new ResourceResolverControl(isAdmin, authenticationInfo, storage, authenticator);
-        authenticator.authenticateAll(storage.getAuthRequiredHandlers(), provider);
-        return provider;
+        final ResourceResolverControl control = new ResourceResolverControl(isAdmin, authenticationInfo, storage);
+
+        this.context.getResolveContextManager().authenticateAll(storage.getAuthRequiredHandlers(), control);
+
+        return control;
     }
 
     /**
@@ -163,7 +173,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public boolean isLive() {
-        return !this.control.isClosed() && this.control.isLive() && this.factory.isLive();
+        return !this.control.isClosed() && this.control.isLive(this.context) && this.factory.isLive();
     }
 
     /**
@@ -203,7 +213,7 @@ public class ResourceResolverImpl extend
     @Override
     public Iterator<String> getAttributeNames() {
         checkClosed();
-        return this.control.getAttributeNames().iterator();
+        return this.control.getAttributeNames(this.context).iterator();
     }
 
     /**
@@ -216,7 +226,7 @@ public class ResourceResolverImpl extend
             throw new NullPointerException("name");
         }
 
-        return this.control.getAttribute(name);
+        return this.control.getAttribute(this.context, name);
     }
 
     // ---------- resolving resources
@@ -737,7 +747,7 @@ public class ResourceResolverImpl extend
         checkClosed();
 
         return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
-                control.findResources(query, defaultString(language, DEFAULT_QUERY_LANGUAGE)));
+                control.findResources(this.context, query, defaultString(language, DEFAULT_QUERY_LANGUAGE)));
     }
 
     /**
@@ -749,7 +759,7 @@ public class ResourceResolverImpl extend
             throws SlingException {
         checkClosed();
 
-        return control.queryResources(query, defaultString(language, DEFAULT_QUERY_LANGUAGE));
+        return control.queryResources(this.context, query, defaultString(language, DEFAULT_QUERY_LANGUAGE));
     }
 
     /**
@@ -799,7 +809,7 @@ public class ResourceResolverImpl extend
     private Session getSession() {
         if ( !this.searchedSession ) {
             this.searchedSession = true;
-            this.cachedSession = this.control.adaptTo(Session.class);
+            this.cachedSession = this.control.adaptTo(this.context, Session.class);
         }
         return this.cachedSession;
     }
@@ -817,7 +827,7 @@ public class ResourceResolverImpl extend
         if (type == Session.class) {
             return (AdapterType) getSession();
         }
-        final AdapterType result = this.control.adaptTo(type);
+        final AdapterType result = this.control.adaptTo(this.context, type);
         if ( result != null ) {
             return result;
         }
@@ -1155,7 +1165,7 @@ public class ResourceResolverImpl extend
             return;
         }
         // if resource is null, we get an NPE as stated in the API
-        this.control.delete(resource);
+        this.control.delete(this.context, resource);
     }
 
     /**
@@ -1196,7 +1206,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void revert() {
-        this.control.revert();
+        this.control.revert(this.context);
     }
 
     /**
@@ -1204,7 +1214,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void commit() throws PersistenceException {
-        this.control.commit();
+        this.control.commit(this.context);
     }
 
     /**
@@ -1212,7 +1222,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public boolean hasChanges() {
-        return this.control.hasChanges();
+        return this.control.hasChanges(this.context);
     }
 
     /**
@@ -1283,7 +1293,7 @@ public class ResourceResolverImpl extend
      */
     @Override
     public void refresh() {
-        this.control.refresh();
+        this.control.refresh(this.context);
     }
 
     @Override

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=1728626&r1=1728625&r2=1728626&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 Fri Feb  5 10:19:24 2016
@@ -22,6 +22,8 @@ import org.apache.sling.resourceresolver
 
 /**
  * The resource resolver context.
+ *
+ * This class is not thread safe (same as the resource resolver).
  */
 public class ResourceResolverContext {
 

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java Fri Feb  5 10:19:24 2016
@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -47,8 +48,7 @@ import org.apache.sling.resource.path.Pa
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.stateful.ResourceProviderAuthenticator;
-import org.apache.sling.resourceresolver.impl.providers.stateful.StatefulResourceProvider;
+import org.apache.sling.resourceresolver.impl.providers.stateful.AuthenticatedResourceProvider;
 import org.apache.sling.resourceresolver.impl.providers.tree.Node;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
 import org.slf4j.Logger;
@@ -69,6 +69,9 @@ public class ResourceResolverControl {
     /** Is this a resource resolver for an admin? */
     private final boolean isAdmin;
 
+    /** The authentication info. */
+    private final Map<String, Object> authenticationInfo;
+
     /** Resource type resource resolver (admin resolver) */
     private volatile ResourceResolver resourceTypeResourceResolver;
 
@@ -77,48 +80,59 @@ public class ResourceResolverControl {
 
     private final ResourceProviderStorage storage;
 
-    private final ResourceProviderAuthenticator authenticator;
-
-    private final Map<String, Object> authenticationInfo;
+    private final Map<ResourceProviderHandler, Object> authenticatedProviders;
 
     /**
      * Create a new resource resolver context.
      */
     public ResourceResolverControl(final boolean isAdmin,
             final Map<String, Object> authenticationInfo,
-            ResourceProviderStorage storage,
-            ResourceProviderAuthenticator authenticator) {
+            final ResourceProviderStorage storage) {
+        this.authenticatedProviders = new IdentityHashMap<ResourceProviderHandler, Object>();
         this.authenticationInfo = authenticationInfo;
         this.isAdmin = isAdmin;
         this.storage = storage;
-        this.authenticator = authenticator;
     }
 
+    /**
+     * Is this an admin resource resolver?
+     * @return{@code true} if it is an admin resource resolver
+     */
     public boolean isAdmin() {
         return isAdmin;
     }
 
+    /**
+     * The authentication info
+     * @return The map with the auth info
+     */
     public Map<String, Object> getAuthenticationInfo() {
         return this.authenticationInfo;
     }
 
+    /**
+     * Is this already closed?
+     * @return {@code true} if it is closed.
+     */
     public boolean isClosed() {
         return this.isClosed.get();
     }
+
     /**
      * Logs out from all providers.
      */
     private void logout() {
-        for (StatefulResourceProvider p : authenticator.getAllUsedAuthenticated()) {
-            p.logout();
+        for(final Map.Entry<ResourceProviderHandler, Object> entry : this.authenticatedProviders.entrySet()) {
+            entry.getKey().getResourceProvider().logout(entry.getValue());
         }
+        this.authenticatedProviders.clear();
     }
 
     /**
      * Refreshes all refreshable providers.
      */
-    public void refresh() {
-        for (StatefulResourceProvider p : authenticator.getAllUsedRefreshable()) {
+    public void refresh(@Nonnull final ResourceResolverContext context) {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllUsedRefreshable()) {
             p.refresh();
         }
     }
@@ -126,8 +140,8 @@ public class ResourceResolverControl {
     /**
      * Returns {@code true} if all providers are live.
      */
-    public boolean isLive() {
-        for (StatefulResourceProvider p : authenticator.getAllUsedAuthenticated()) {
+    public boolean isLive(@Nonnull final ResourceResolverContext context) {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllAuthenticated()) {
             if (!p.isLive()) {
                 return false;
             }
@@ -145,21 +159,19 @@ public class ResourceResolverControl {
      */
     public Resource getParent(final ResourceResolverContext context, final Resource child) {
         final String path = child.getPath();
-        try {
-            final StatefulResourceProvider provider = getBestMatchingProvider(path);
-            if ( provider != null ) {
-                final Resource parentCandidate = provider.getParent(child);
-                if (parentCandidate != null) {
-                    return parentCandidate;
-                }
+        final AuthenticatedResourceProvider provider = getBestMatchingProvider(context, path);
+        if ( provider != null ) {
+            final Resource parentCandidate = provider.getParent(child);
+            if (parentCandidate != null) {
+                return parentCandidate;
             }
-        } catch ( final LoginException le ) {
-            // ignore
         }
+
         final String parentPath = ResourceUtil.getParent(path);
         if (parentPath != null && isIntermediatePath(parentPath)) {
             return new SyntheticResource(context.getResourceResolver(), parentPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC);
         }
+
         return null;
     }
 
@@ -185,17 +197,14 @@ public class ResourceResolverControl {
             return null; // path must be absolute
         }
 
-        try {
-            final StatefulResourceProvider provider = this.getBestMatchingProvider(path);
-            if ( provider != null ) {
-                final Resource resourceCandidate = provider.getResource(path, parent, parameters, isResolve);
-                if (resourceCandidate != null) {
-                    return resourceCandidate;
-                }
+        final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, path);
+        if ( provider != null ) {
+            final Resource resourceCandidate = provider.getResource(path, parent, parameters, isResolve);
+            if (resourceCandidate != null) {
+                return resourceCandidate;
             }
-        } catch ( LoginException le ) {
-            // ignore
         }
+
         // query: /libs/sling/servlet/default
         // resource Provider: libs/sling/servlet/default/GET.servlet
         // list will match libs, sling, servlet, default
@@ -233,13 +242,9 @@ public class ResourceResolverControl {
 
         // children of the 'parent' provider
         Iterator<Resource> realChildren = null;
-        try {
-            final StatefulResourceProvider provider = this.getBestMatchingProvider(parentPath);
-            if ( provider != null ) {
-                realChildren = provider.listChildren(parent);
-            }
-        } catch ( final LoginException le ) {
-            // ignore, realChildren will be null
+        final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, parentPath);
+        if ( provider != null ) {
+            realChildren = provider.listChildren(parent);
         }
 
         final Set<String> visitedNames = new HashSet<String>();
@@ -266,7 +271,8 @@ public class ResourceResolverControl {
                 } else {
                     Resource rsrc = null;
                     try {
-                        rsrc = authenticator.getStateful(handler, this).getResource(childPath, parent, null, false);
+                        final AuthenticatedResourceProvider rp = context.getResolveContextManager().getOrCreateProvider(handler, this);
+                        rsrc = rp == null ? null : rp.getResource(childPath, parent, null, false);
                     } catch ( final LoginException ignore) {
                         // ignore
                     }
@@ -299,10 +305,10 @@ public class ResourceResolverControl {
     /**
      * Returns the union of all attribute names.
      */
-    public Collection<String> getAttributeNames() {
+    public Collection<String> getAttributeNames(final ResourceResolverContext context) {
         final Set<String> names = new LinkedHashSet<String>();
-        for (StatefulResourceProvider p : authenticator.getAllBestEffort(storage.getAttributableHandlers(), this)) {
-            final Collection<String> newNames = p.getAttributeNames();
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllBestEffort(storage.getAttributableHandlers(), this)) {
+            final Collection<String> newNames = p.getAttributeNames(this.authenticationInfo);
             if (newNames != null) {
                 names.addAll(newNames);
             }
@@ -315,9 +321,9 @@ public class ResourceResolverControl {
      * {@link StatefulResourceProvider#getAttribute(String)} invocation on
      * the providers.
      */
-    public Object getAttribute(String name) {
-        for (StatefulResourceProvider p : authenticator.getAllBestEffort(storage.getAttributableHandlers(), this)) {
-            Object attribute = p.getAttribute(name);
+    public Object getAttribute(final ResourceResolverContext context, final String name) {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllBestEffort(storage.getAttributableHandlers(), this)) {
+            Object attribute = p.getAttribute(name, this.authenticationInfo);
             if (attribute != null) {
                 return attribute;
             }
@@ -337,16 +343,12 @@ public class ResourceResolverControl {
     public Resource create(final ResourceResolverContext context,
             final String path, final Map<String, Object> properties)
     throws PersistenceException {
-        try {
-            final StatefulResourceProvider provider = getBestMatchingModifiableProvider(path);
-            if ( provider != null ) {
-                final Resource creationResultResource = provider.create(context.getResourceResolver(), path, properties);
-                if (creationResultResource != null) {
-                    return creationResultResource;
-                }
+        final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
+        if ( provider != null ) {
+            final Resource creationResultResource = provider.create(context.getResourceResolver(), path, properties);
+            if (creationResultResource != null) {
+                return creationResultResource;
             }
-        } catch (LoginException le) {
-            // ignore and throw (see below)
         }
         throw new UnsupportedOperationException("create '" + ResourceUtil.getName(path) + "' at " + ResourceUtil.getParent(path));
     }
@@ -362,16 +364,12 @@ public class ResourceResolverControl {
      * @throws PersistenceException
      *             If deletion fails
      */
-    public void delete(final Resource resource) throws PersistenceException {
+    public void delete(final ResourceResolverContext context, final Resource resource) throws PersistenceException {
         final String path = resource.getPath();
-        try {
-            final StatefulResourceProvider provider = getBestMatchingModifiableProvider(path);
-            if ( provider != null ) {
-                provider.delete(resource);
-                return;
-            }
-        } catch (LoginException le) {
-            // ignore and throw (see below)
+        final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
+        if ( provider != null ) {
+            provider.delete(resource);
+            return;
         }
         throw new UnsupportedOperationException("delete at '" + path + "'");
     }
@@ -379,8 +377,8 @@ public class ResourceResolverControl {
     /**
      * Revert changes on all modifiable ResourceProviders.
      */
-    public void revert() {
-        for (StatefulResourceProvider p : authenticator.getAllUsedModifiable()) {
+    public void revert(final ResourceResolverContext context) {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllUsedModifiable()) {
             p.revert();
         }
     }
@@ -388,8 +386,8 @@ public class ResourceResolverControl {
     /**
      * Commit changes on all modifiable ResourceProviders.
      */
-    public void commit() throws PersistenceException {
-        for (StatefulResourceProvider p : authenticator.getAllUsedModifiable()) {
+    public void commit(final ResourceResolverContext context) throws PersistenceException {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllUsedModifiable()) {
             p.commit();
         }
     }
@@ -397,8 +395,8 @@ public class ResourceResolverControl {
     /**
      * Check if any modifiable ResourceProvider has uncommited changes.
      */
-    public boolean hasChanges() {
-        for (StatefulResourceProvider p : authenticator.getAllUsedModifiable()) {
+    public boolean hasChanges(final ResourceResolverContext context) {
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllUsedModifiable()) {
             if (p.hasChanges()) {
                 return true;
             }
@@ -409,9 +407,9 @@ public class ResourceResolverControl {
     /**
      * Return the union of query languages supported by the providers.
      */
-    public String[] getSupportedLanguages() {
-        Set<String> supportedLanguages = new LinkedHashSet<String>();
-        for (StatefulResourceProvider p : authenticator.getAllBestEffort(storage.getLanguageQueryableHandlers(), this)) {
+    public String[] getSupportedLanguages(final ResourceResolverContext context) {
+        final Set<String> supportedLanguages = new LinkedHashSet<String>();
+        for (AuthenticatedResourceProvider p : context.getResolveContextManager().getAllBestEffort(storage.getLanguageQueryableHandlers(), this)) {
             supportedLanguages.addAll(Arrays.asList(p.getSupportedLanguages()));
         }
         return supportedLanguages.toArray(new String[supportedLanguages.size()]);
@@ -420,18 +418,21 @@ public class ResourceResolverControl {
     /**
      * Queries all resource providers and combines the results.
      */
-    public Iterator<Resource> findResources(final String query, final String language) {
-        List<StatefulResourceProvider> queryableRP = getQueryableProviders(language);
-        List<Iterator<Resource>> iterators = new ArrayList<Iterator<Resource>>(queryableRP.size());
-        for (StatefulResourceProvider p : queryableRP) {
+    public Iterator<Resource> findResources(final ResourceResolverContext context,
+            final String query, final String language) {
+        final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
+        final List<Iterator<Resource>> iterators = new ArrayList<Iterator<Resource>>(queryableRP.size());
+        for (AuthenticatedResourceProvider p : queryableRP) {
             iterators.add(p.findResources(query, language));
         }
         return new ChainedIterator<Resource>(iterators.iterator());
     }
 
-    private List<StatefulResourceProvider> getQueryableProviders(String language) {
-        List<StatefulResourceProvider> queryableProviders = new ArrayList<StatefulResourceProvider>();
-        for (StatefulResourceProvider p : authenticator.getAllBestEffort(storage.getLanguageQueryableHandlers(), this)) {
+    private List<AuthenticatedResourceProvider> getQueryableProviders(
+            final ResourceResolverContext context,
+            final String language) {
+        final List<AuthenticatedResourceProvider> queryableProviders = new ArrayList<AuthenticatedResourceProvider>();
+        for (final AuthenticatedResourceProvider p : context.getResolveContextManager().getAllBestEffort(storage.getLanguageQueryableHandlers(), this)) {
             if (ArrayUtils.contains(p.getSupportedLanguages(), language)) {
                 queryableProviders.add(p);
             }
@@ -442,10 +443,11 @@ public class ResourceResolverControl {
     /**
      * Queries all resource providers and combines the results.
      */
-    public Iterator<Map<String, Object>> queryResources(final String query, final String language) {
-        List<StatefulResourceProvider> queryableRP = getQueryableProviders(language);
-        List<Iterator<Map<String, Object>>> iterators = new ArrayList<Iterator<Map<String, Object>>>(queryableRP.size());
-        for (StatefulResourceProvider p : queryableRP) {
+    public Iterator<Map<String, Object>> queryResources(final ResourceResolverContext context,
+            final String query, final String language) {
+        final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
+        final List<Iterator<Map<String, Object>>> iterators = new ArrayList<Iterator<Map<String, Object>>>(queryableRP.size());
+        for (AuthenticatedResourceProvider p : queryableRP) {
             iterators.add(p.queryResources(query, language));
         }
         return new ChainedIterator<Map<String, Object>>(iterators.iterator());
@@ -456,8 +458,9 @@ public class ResourceResolverControl {
      * providers.
      */
     @SuppressWarnings("unchecked")
-    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
-        for (StatefulResourceProvider p : authenticator.getAllBestEffort(storage.getAdaptableHandlers(), this)) {
+    public <AdapterType> AdapterType adaptTo(final ResourceResolverContext context, Class<AdapterType> type) {
+        // TODO - improve by providing an iterator instead of a list (getAllBestEffort)
+        for (AuthenticatedResourceProvider p : context.getResolveContextManager().getAllBestEffort(storage.getAdaptableHandlers(), this)) {
             final Object adaptee = p.adaptTo(type);
             if (adaptee != null) {
                 return (AdapterType) adaptee;
@@ -466,15 +469,16 @@ public class ResourceResolverControl {
         return null;
     }
 
-    private StatefulResourceProvider checkSourceAndDest(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
+    private AuthenticatedResourceProvider checkSourceAndDest(final ResourceResolverContext context,
+            final String srcAbsPath, final String destAbsPath) throws PersistenceException {
         // check source
         final Node<ResourceProviderHandler> srcNode = storage.getTree().getBestMatchingNode(srcAbsPath);
         if ( srcNode == null ) {
             throw new PersistenceException("Source resource does not exist.", null, srcAbsPath, null);
         }
-        StatefulResourceProvider srcProvider = null;
+        AuthenticatedResourceProvider srcProvider = null;
         try {
-            srcProvider = authenticator.getStateful(srcNode.getValue(), this);
+            srcProvider = context.getResolveContextManager().getOrCreateProvider(srcNode.getValue(), this);
         } catch (LoginException e) {
             // ignore
         }
@@ -491,9 +495,9 @@ public class ResourceResolverControl {
         if ( destNode == null ) {
             throw new PersistenceException("Destination resource does not exist.", null, destAbsPath, null);
         }
-        StatefulResourceProvider destProvider = null;
+        AuthenticatedResourceProvider destProvider = null;
         try {
-            destProvider = authenticator.getStateful(destNode.getValue(), this);
+            destProvider = context.getResolveContextManager().getOrCreateProvider(destNode.getValue(), this);
         } catch (LoginException e) {
             // ignore
         }
@@ -506,24 +510,25 @@ public class ResourceResolverControl {
         }
 
         // check for sub providers of src and dest
-        if ( srcProvider == destProvider && !collectProviders(srcNode) && !collectProviders(destNode) ) {
+        if ( srcProvider == destProvider && !collectProviders(context, srcNode) && !collectProviders(context, destNode) ) {
             return srcProvider;
         }
         return null;
     }
 
-    private boolean collectProviders(final Node<ResourceProviderHandler> parent) {
+    private boolean collectProviders(final ResourceResolverContext context,
+            final Node<ResourceProviderHandler> parent) {
         boolean hasMoreProviders = false;
         for (final Entry<String, Node<ResourceProviderHandler>> entry : parent.getChildren().entrySet()) {
             if ( entry.getValue().getValue() != null ) {
                 try {
-                    authenticator.getStateful(entry.getValue().getValue(), this);
+                    context.getResolveContextManager().getOrCreateProvider(entry.getValue().getValue(), this);
                     hasMoreProviders = true;
                 } catch ( final LoginException ignore) {
                     // ignore
                 }
             }
-            if ( collectProviders(entry.getValue())) {
+            if ( collectProviders(context, entry.getValue())) {
                 hasMoreProviders = true;
             }
         }
@@ -547,7 +552,7 @@ public class ResourceResolverControl {
      */
     public Resource copy(final ResourceResolverContext context,
             final String srcAbsPath, final String destAbsPath) throws PersistenceException {
-        final StatefulResourceProvider optimizedSourceProvider = checkSourceAndDest(srcAbsPath, destAbsPath);
+        final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
         if ( optimizedSourceProvider != null && optimizedSourceProvider.copy(srcAbsPath, destAbsPath) ) {
             return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
         }
@@ -562,7 +567,7 @@ public class ResourceResolverControl {
         } finally {
             if ( rollback ) {
                 for(final Resource rsrc : newResources) {
-                    this.delete(rsrc);
+                    this.delete(context, rsrc);
                 }
             }
         }
@@ -575,7 +580,7 @@ public class ResourceResolverControl {
      */
     public Resource move(final ResourceResolverContext context,
             String srcAbsPath, String destAbsPath) throws PersistenceException {
-        final StatefulResourceProvider optimizedSourceProvider = checkSourceAndDest(srcAbsPath, destAbsPath);
+        final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
         if ( optimizedSourceProvider != null && optimizedSourceProvider.move(srcAbsPath, destAbsPath) ) {
             return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
         }
@@ -584,13 +589,13 @@ public class ResourceResolverControl {
         boolean rollback = true;
         try {
             this.copy(context, srcResource, destAbsPath, newResources);
-            this.delete(srcResource);
+            this.delete(context, srcResource);
             rollback = false;
             return newResources.get(0);
         } finally {
             if ( rollback ) {
                 for(final Resource rsrc : newResources) {
-                    this.delete(rsrc);
+                    this.delete(context, rsrc);
                 }
             }
         }
@@ -600,33 +605,36 @@ public class ResourceResolverControl {
         return this.storage;
     }
 
-    public @CheckForNull StatefulResourceProvider getStatefulResourceProvider(@Nonnull final ResourceProviderHandler handler)
-    throws LoginException {
-        if ( handler != null ) {
-            return authenticator.getStateful(handler, this);
-        }
-        return null;
-    }
-
     /**
      * @param path
      * @return
-     * @throws LoginException
      */
-    private @CheckForNull StatefulResourceProvider getBestMatchingProvider(final String path) throws LoginException {
-        final Node<ResourceProviderHandler> node = storage.getTree().getBestMatchingNode(path);
-        return node == null ? null : authenticator.getStateful(node.getValue(), this);
+    private @CheckForNull AuthenticatedResourceProvider getBestMatchingProvider(final ResourceResolverContext context,
+            final String path) {
+        try {
+            final Node<ResourceProviderHandler> node = storage.getTree().getBestMatchingNode(path);
+            return node == null ? null : context.getResolveContextManager().getOrCreateProvider(node.getValue(), this);
+        } catch ( final LoginException le ) {
+            // ignore
+            return null;
+        }
     }
 
     /**
      * @param path
      * @return The modifiable provider or {@code null}
-     * @throws LoginException
      */
-    private @CheckForNull StatefulResourceProvider getBestMatchingModifiableProvider(final String path) throws LoginException {
+    private @CheckForNull AuthenticatedResourceProvider getBestMatchingModifiableProvider(
+            final ResourceResolverContext context,
+            final String path)  {
         final Node<ResourceProviderHandler> node = storage.getTree().getBestMatchingNode(path);
         if ( node != null && node.getValue().getInfo().isModifiable() ) {
-            return authenticator.getStateful(node.getValue(), this);
+            try {
+                return context.getResolveContextManager().getOrCreateProvider(node.getValue(), this);
+            } catch ( final LoginException le ) {
+                // ignore
+                return null;
+            }
         }
         return null;
     }
@@ -747,4 +755,13 @@ public class ResourceResolverControl {
 
         return null;
     }
+
+    public void registerAuthenticatedProvider(@Nonnull ResourceProviderHandler handler,
+            @CheckForNull Object providerState) {
+        this.authenticatedProviders.put(handler, providerState);
+    }
+
+    public void clearAuthenticatedProviders() {
+        this.authenticatedProviders.clear();
+    }
 }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java Fri Feb  5 10:19:24 2016
@@ -39,8 +39,6 @@ public class ResourceProviderStorage {
 
     private final List<ResourceProviderHandler> attributableHandlers;
 
-    private final List<ResourceProviderHandler> refreshableHandlers;
-
     private final List<ResourceProviderHandler> languageQueryableHandlers;
 
     private final PathTree<ResourceProviderHandler> handlersTree;
@@ -50,7 +48,6 @@ public class ResourceProviderStorage {
         this.authRequiredHandlers = new ArrayList<ResourceProviderHandler>();
         this.adaptableHandlers = new ArrayList<ResourceProviderHandler>();
         this.attributableHandlers = new ArrayList<ResourceProviderHandler>();
-        this.refreshableHandlers = new ArrayList<ResourceProviderHandler>();
         this.languageQueryableHandlers = new ArrayList<ResourceProviderHandler>();
         for (ResourceProviderHandler h : allHandlers) {
             ResourceProviderInfo info = h.getInfo();
@@ -63,9 +60,6 @@ public class ResourceProviderStorage {
             if (info.isAttributable()) {
                 this.attributableHandlers.add(h);
             }
-            if (info.isRefreshable()) {
-                this.refreshableHandlers.add(h);
-            }
             if (h.getResourceProvider().getQueryLanguageProvider() != null) {
                 this.languageQueryableHandlers.add(h);
             }
@@ -89,10 +83,6 @@ public class ResourceProviderStorage {
         return attributableHandlers;
     }
 
-    public List<ResourceProviderHandler> getRefreshableHandlers() {
-        return refreshableHandlers;
-    }
-
     public List<ResourceProviderHandler> getLanguageQueryableHandlers() {
         return languageQueryableHandlers;
     }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java Fri Feb  5 10:19:24 2016
@@ -24,22 +24,15 @@ import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 
-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.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
 import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
 import org.apache.sling.spi.resource.provider.ResolveContext;
 import org.apache.sling.spi.resource.provider.ResourceContext;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * This {@link StatefulResourceProvider} implementation authenticates the
@@ -47,105 +40,41 @@ import org.slf4j.LoggerFactory;
  * creation of the object (for {@link AuthType#required}) or before invoking the
  * first method (for {@link AuthType#lazy}).
  */
-public class AuthenticatedResourceProvider implements StatefulResourceProvider {
-
-    private static final Logger logger = LoggerFactory.getLogger(AuthenticatedResourceProvider.class);
+public class AuthenticatedResourceProvider {
 
     private static final String FORBIDDEN_ATTRIBUTE = ResourceResolverFactory.PASSWORD;
 
-    private final ResourceProviderHandler handler;
-
-    private final Map<String, Object> authInfo;
+    public static final AuthenticatedResourceProvider UNAUTHENTICATED_PROVIDER = new AuthenticatedResourceProvider(null, null);
 
-    private final ResourceResolver resolver;
+    private final ResourceProvider<Object> provider;
 
-    private final ResourceResolverControl resolverContext;
-
-    private volatile ResolveContext<Object> cachedContext;
+    private final ResolveContext<Object> cachedContext;
 
     private volatile boolean authenticated;
 
 
-    public AuthenticatedResourceProvider(final ResourceProviderHandler handler,
-            ResourceResolver resolver,
-            Map<String, Object> authInfo,
-            ResourceResolverControl resolverContext) throws LoginException {
-        this.handler = handler;
-        this.authInfo = authInfo;
-        this.resolver = resolver;
-        this.resolverContext = resolverContext;
-        if (handler.getInfo().getAuthType() == AuthType.required) {
-            authenticate();
-        }
-    }
-
-    private ResolveContext<Object> authenticate() throws LoginException {
-        if ( cachedContext  == null ) {
-            Object contextData = null;
-            if ( (handler.getInfo().getAuthType() == AuthType.required || handler.getInfo().getAuthType() == AuthType.lazy) ) {
-                try {
-                    contextData = handler.getResourceProvider().authenticate(authInfo);
-                } catch ( final LoginException le ) {
-                    logger.debug("Unable to login into resource provider " + handler.getResourceProvider(), le);
-                    throw le;
-                }
-                authenticated = true;
-            }
-
-            cachedContext = new BasicResolveContext<Object>(resolver, contextData, ResourceUtil.getParent(handler.getInfo().getPath()), this.resolverContext);
-        }
-
-        return cachedContext;
-    }
-
-    @Override
-    public ResolveContext<Object> getContext() throws LoginException {
-        return authenticate();
+    public AuthenticatedResourceProvider(final ResourceProvider<Object> provider,
+            final ResolveContext<Object> resolveContext) {
+        this.provider = provider;
+        this.cachedContext = resolveContext;
     }
 
-    @Override
-    public void logout() {
-        if (authenticated) {
-            try {
-                handler.getResourceProvider().logout(getContext().getProviderState());
-            } catch (LoginException e) {
-                logger.error("Can't create context", e);
-            }
-            authenticated = false;
-        }
-        cachedContext = null;
+    public ResolveContext<Object> getResolveContext() {
+        return this.cachedContext;
     }
 
-    @Override
     public void refresh() {
-        try {
-            handler.getResourceProvider().refresh(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        this.provider.refresh(this.cachedContext);
     }
 
-    @Override
     public boolean isLive() {
-        try {
-            return handler.getResourceProvider().isLive(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return false;
-        }
+        return this.provider.isLive(this.cachedContext);
     }
 
-    @Override
-    public Resource getParent(Resource child) {
-        try {
-            return handler.getResourceProvider().getParent(getContext(), child);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+    public Resource getParent(final Resource child) {
+        return this.provider.getParent(this.cachedContext, child);
     }
 
-    @Override
     public Resource getResource(String path, Resource parent, final Map<String, String> parameters, boolean isResolve) {
         ResourceContext resourceContext = ResourceContext.EMPTY_CONTEXT;
         if ( parameters != null ) {
@@ -157,34 +86,16 @@ public class AuthenticatedResourceProvid
                 }
             };
         }
-        try {
-            return handler.getResourceProvider().getResource(getContext(), path, resourceContext, parent);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
-
+        return this.provider.getResource(this.cachedContext, path, resourceContext, parent);
     }
 
-    @Override
     public Iterator<Resource> listChildren(Resource parent) {
-        try {
-            return handler.getResourceProvider().listChildren(getContext(), parent);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+        return this.provider.listChildren(this.cachedContext, parent);
     }
 
-    @Override
-    public Collection<String> getAttributeNames() {
+    public Collection<String> getAttributeNames(final Map<String, Object> authInfo) {
         Set<String> attributeNames = new LinkedHashSet<String>();
-        Collection<String> rpAttributeNames = null;
-        try {
-            rpAttributeNames = handler.getResourceProvider().getAttributeNames(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        Collection<String> rpAttributeNames = this.provider.getAttributeNames(this.cachedContext);
         if (rpAttributeNames != null) {
             attributeNames.addAll(rpAttributeNames);
         }
@@ -195,152 +106,80 @@ public class AuthenticatedResourceProvid
         return attributeNames;
     }
 
-    @Override
-    public Object getAttribute(String name) {
+    public Object getAttribute(final String name, final Map<String, Object> authInfo) {
         if (FORBIDDEN_ATTRIBUTE.equals(name)) {
             return null;
         }
-        Object attribute = null;
-        try {
-            attribute = handler.getResourceProvider().getAttribute(getContext(), name);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        Object attribute = this.provider.getAttribute(this.cachedContext, name);
         if (attribute == null) {
             attribute = authInfo.get(name);
         }
         return attribute;
     }
 
-    @Override
     public Resource create(final ResourceResolver resolver, String path, Map<String, Object> properties) throws PersistenceException {
-        try {
-            return handler.getResourceProvider().create(getContext(), path, properties);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+        return this.provider.create(this.cachedContext, path, properties);
     }
 
-    @Override
     public void delete(Resource resource) throws PersistenceException {
-        try {
-            handler.getResourceProvider().delete(getContext(), resource);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        this.provider.delete(this.cachedContext, resource);
     }
 
-    @Override
     public void revert() {
-        try {
-            handler.getResourceProvider().revert(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        this.provider.revert(this.cachedContext);
     }
 
-    @Override
     public void commit() throws PersistenceException {
-        try {
-            handler.getResourceProvider().commit(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-        }
+        this.provider.commit(this.cachedContext);
     }
 
-    @Override
     public boolean hasChanges() {
-        try {
-            return handler.getResourceProvider().hasChanges(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return false;
-        }
+        return this.provider.hasChanges(this.cachedContext);
     }
 
     private QueryLanguageProvider<Object> getQueryLanguageProvider() {
-        return handler.getResourceProvider().getQueryLanguageProvider();
+        return this.provider.getQueryLanguageProvider();
     }
 
-    @Override
     public String[] getSupportedLanguages() {
         final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
         if (jcrQueryProvider == null) {
             return null;
         }
-        try {
-            return jcrQueryProvider.getSupportedLanguages(getContext());
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return ArrayUtils.EMPTY_STRING_ARRAY;
-        }
+        return jcrQueryProvider.getSupportedLanguages(this.cachedContext);
     }
 
-    @Override
     public Iterator<Resource> findResources(String query, String language) {
         final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
         if (jcrQueryProvider == null) {
             return null;
         }
-        try {
-            return jcrQueryProvider.findResources(getContext(), query, language);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+        return jcrQueryProvider.findResources(this.cachedContext, query, language);
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Override
     public Iterator<Map<String, Object>> queryResources(String query, String language) {
         final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
         if (jcrQueryProvider == null) {
             return null;
         }
-        try {
-            return (Iterator) jcrQueryProvider.queryResources(getContext(), query, language);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+        return (Iterator) jcrQueryProvider.queryResources(this.cachedContext, query, language);
     }
 
-    @Override
     public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
-        try {
-            return handler.getResourceProvider().adaptTo(getContext(), type);
-        } catch (LoginException e) {
-            logger.error("Can't create context", e);
-            return null;
-        }
+        return this.provider.adaptTo(this.cachedContext, type);
     }
 
-    @Override
     public boolean copy(String srcAbsPath, String destAbsPath) throws PersistenceException {
-        try {
-            return handler.getResourceProvider().copy(getContext(), srcAbsPath, destAbsPath);
-        } catch (LoginException e) {
-            throw new PersistenceException("Unable to create context.", e);
-        }
+        return this.provider.copy(this.cachedContext, srcAbsPath, destAbsPath);
     }
 
-    @Override
     public boolean move(String srcAbsPath, String destAbsPath) throws PersistenceException {
-        try {
-            return handler.getResourceProvider().move(getContext(), srcAbsPath, destAbsPath);
-        } catch (LoginException e) {
-            throw new PersistenceException("Unable to create context.", e);
-        }
-    }
-
-    @Override
-    public ResourceProvider<Object> getResourceProvider() {
-        return handler.getResourceProvider();
+        return this.provider.move(this.cachedContext, srcAbsPath, destAbsPath);
     }
 
     @Override
     public String toString() {
-        return "[" + getClass().getSimpleName() + "# rp: " + getResourceProvider() + ", authenticated: " + authenticated + "]";
+        return "[" + getClass().getSimpleName() + "# rp: " + this.provider + ", authenticated: " + authenticated + "]";
     }
 }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java Fri Feb  5 10:19:24 2016
@@ -18,25 +18,34 @@
  */
 package org.apache.sling.resourceresolver.impl.providers.stateful;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
 import org.apache.sling.resourceresolver.impl.providers.tree.Node;
 import org.apache.sling.spi.resource.provider.ResolveContext;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
 
+/**
+ * Resolve context implementation for a resource provider.
+ *
+ * This class is not thread safe (same as the resource resolver).
+ */
 public class BasicResolveContext<T> implements ResolveContext<T> {
 
-    private final String parentPath;
+    private final ResourceResolver resolver;
+
+    private final ResolveContextManager resolveContextManager;
 
-    private final ResourceResolver resourceResolver;
+    private final ResourceResolverControl control;
 
     private final T providerState;
 
-    private final ResourceResolverControl combinedProvider;
+    private final String parentPath;
 
     private volatile boolean parentLookupDone = false;
 
@@ -44,24 +53,21 @@ public class BasicResolveContext<T> impl
 
     private volatile ResolveContext<Object> parentResolveContext;
 
-    public BasicResolveContext(ResourceResolver resourceResolver,
-            T providerState,
-            String parentPath,
-            ResourceResolverControl combinedProvider) {
-        this.resourceResolver = resourceResolver;
+    public BasicResolveContext(@Nonnull final ResourceResolver resolver,
+            @Nonnull final ResolveContextManager resolveContextManager,
+            @Nonnull final ResourceResolverControl control,
+            @CheckForNull final T providerState,
+            @Nonnull final String parentPath) {
+        this.resolver = resolver;
+        this.resolveContextManager = resolveContextManager;
         this.parentPath = parentPath;
         this.providerState = providerState;
-        this.combinedProvider = combinedProvider;
-    }
-
-    public BasicResolveContext(ResourceResolver resourceResolver,
-            T providerState, String parentPath) {
-        this(resourceResolver, providerState, parentPath, null);
+        this.control = control;
     }
 
     @Override
     public ResourceResolver getResourceResolver() {
-        return resourceResolver;
+        return this.resolver;
     }
 
     @Override
@@ -80,20 +86,18 @@ public class BasicResolveContext<T> impl
         if ( ! parentLookupDone ) {
             synchronized ( this ) {
                 if ( this.parentPath != null ) {
-                    final ResourceProviderStorage storage = this.combinedProvider.getResourceProviderStorage();
                     String path = this.parentPath;
                     while ( path != null && this.parentProvider != null ) {
-                        final Node<ResourceProviderHandler> node = storage.getTree().getBestMatchingNode(this.parentPath);
+                        final Node<ResourceProviderHandler> node = this.control.getResourceProviderStorage().getTree().getBestMatchingNode(this.parentPath);
                         if ( node != null ) {
+                            final ResourceProviderHandler handler = node.getValue();
                             try {
-                                final StatefulResourceProvider srp = this.combinedProvider.getStatefulResourceProvider(node.getValue());
-                                if ( srp != null ) {
-                                    this.parentProvider = srp.getResourceProvider();
-                                    this.parentResolveContext = srp.getContext();
+                                this.parentResolveContext = this.resolveContextManager.getOrCreateResolveContext(handler, this.control);
+                                if ( this.parentResolveContext != null ) {
+                                    this.parentProvider = handler.getResourceProvider();
                                 }
                             } catch ( final LoginException se) {
                                 // skip this, try next
-                                this.parentProvider = null;
                             }
                             if ( this.parentProvider == null ) {
                                 path = ResourceUtil.getParent(path);

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResolveContextManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResolveContextManager.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResolveContextManager.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResolveContextManager.java Fri Feb  5 10:19:24 2016
@@ -17,22 +17,185 @@
  */
 package org.apache.sling.resourceresolver.impl.providers.stateful;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.IdentityHashMap;
+import java.util.List;
 import java.util.Map;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.runtime.dto.AuthType;
+import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
 import org.apache.sling.spi.resource.provider.ResolveContext;
-
+import org.apache.sling.spi.resource.provider.ResourceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages resolve contexts for each resource provider including
+ * authentication.
+ *
+ * This class is not thread safe (same as the resource resolver).
+ */
 public class ResolveContextManager {
 
-    private final Map<ResourceProviderHandler, ResolveContext<Object>> contextMap;
+    private static final Logger logger = LoggerFactory.getLogger(ResolveContextManager.class);
+
+    private final ResourceResolver resolver;
+
+    private final Map<ResourceProviderHandler, AuthenticatedResourceProvider> contextMap;
+
+    /** Set of authenticated resource providers. */
+    private final List<AuthenticatedResourceProvider> authenticated = new ArrayList<AuthenticatedResourceProvider>();
+
+    /** Set of modifiable resource providers. */
+    private final List<AuthenticatedResourceProvider> modifiable = new ArrayList<AuthenticatedResourceProvider>();
+
+    /** Set of refreshable resource providers. */
+    private final List<AuthenticatedResourceProvider> refreshable = new ArrayList<AuthenticatedResourceProvider>();
+
+    public ResolveContextManager(@Nonnull final ResourceResolver resolver) {
+        this.contextMap = new IdentityHashMap<ResourceProviderHandler, AuthenticatedResourceProvider>();
+        this.resolver = resolver;
+    }
+
+    /**
+     * Get the context
+     * @param handler The resource handler
+     * @return The resource context or {@code null} if authentication failed previously.
+     */
+    public @CheckForNull AuthenticatedResourceProvider getOrCreateProvider(@Nonnull final ResourceProviderHandler handler,
+            @Nonnull final ResourceResolverControl control)
+    throws LoginException {
+        AuthenticatedResourceProvider provider = this.contextMap.get(handler);
+        if (provider == null) {
+            try {
+                provider = authenticate(handler, control);
+                this.contextMap.put(handler, provider);
+                if ( handler.getInfo().getAuthType() == AuthType.lazy || handler.getInfo().getAuthType() == AuthType.required ) {
+                    control.registerAuthenticatedProvider(handler, provider.getResolveContext().getProviderState());
+                }
+            } catch ( final LoginException le) {
+                logger.debug("Authentication to resource provider " + handler.getResourceProvider() + " failed: " + le.getMessage(), le);
+                this.contextMap.put(handler, AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER);
+
+                throw le;
+            }
+        }
+
+        return provider == AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER ? null : provider;
+    }
+
+    /**
+     * Get the context
+     * @param handler The resource handler
+     * @return The resource context or {@code null}.
+     */
+    public @CheckForNull ResolveContext<Object> getOrCreateResolveContext(@Nonnull final ResourceProviderHandler handler,
+            @Nonnull final ResourceResolverControl control)
+    throws LoginException {
+        AuthenticatedResourceProvider provider = this.getOrCreateProvider(handler, control);
+        return provider == null ? null : provider.getResolveContext();
+    }
+
+    /**
+     * Authenticate all handlers
+     * @param handlers List of handlers
+     * @param control the resource resolver control
+     * @throws LoginException If authentication fails to one provider
+     */
+    public void authenticateAll(@Nonnull final List<ResourceProviderHandler> handlers,
+            @Nonnull final ResourceResolverControl control)
+    throws LoginException {
+        for (final ResourceProviderHandler h : handlers) {
+            try {
+                this.getOrCreateProvider(h, control);
+            } catch ( final LoginException le ) {
+                // authentication failed, logout from all successful handlers
+                for(final Map.Entry<ResourceProviderHandler, AuthenticatedResourceProvider> entry : this.contextMap.entrySet()) {
+                    if ( entry.getValue() != null ) {
+                        entry.getKey().getResourceProvider().logout(entry.getValue().getResolveContext().getProviderState());
+                    }
+                }
+                this.contextMap.clear();
+                control.clearAuthenticatedProviders();
+                throw le;
+            }
+        }
+    }
+
+    /**
+     * Authenticate a single resource provider (handler)
+     * @param handler The resource provider handler
+     * @param control The resource control
+     * @return The resolve context
+     * @throws LoginException If authentication fails
+     */
+    private @Nonnull AuthenticatedResourceProvider authenticate(@Nonnull final ResourceProviderHandler handler,
+            @Nonnull final ResourceResolverControl control) throws LoginException {
+        final ResourceProvider<Object> provider = handler.getResourceProvider();
+        boolean isAuthenticated = false;
+        Object contextData = null;
+        if ( (handler.getInfo().getAuthType() == AuthType.required || handler.getInfo().getAuthType() == AuthType.lazy) ) {
+            try {
+                contextData = provider.authenticate(control.getAuthenticationInfo());
+                isAuthenticated = true;
+            } catch ( final LoginException le ) {
+                logger.debug("Unable to login into resource provider " + provider, le);
+                throw le;
+            }
+        }
+
+        final ResolveContext<Object> context = new BasicResolveContext<Object>(this.resolver,
+                this,
+                control,
+                contextData,
+                ResourceUtil.getParent(handler.getInfo().getPath()));
+        final AuthenticatedResourceProvider rp = new AuthenticatedResourceProvider(provider, context);
+        if ( isAuthenticated ) {
+            this.authenticated.add(rp);
+        }
+        if ( handler.getInfo().isModifiable() ) {
+            this.modifiable.add(rp);
+        }
+        if ( handler.getInfo().isRefreshable() ) {
+            this.refreshable.add(rp);
+        }
+
+        return rp;
+    }
+
+    public Collection<AuthenticatedResourceProvider> getAllAuthenticated() {
+        return authenticated;
+    }
+
+    public Collection<AuthenticatedResourceProvider> getAllUsedModifiable() {
+        return modifiable;
+    }
 
-    public ResolveContextManager(final ResourceResolver resolver) {
-        this.contextMap = new IdentityHashMap<ResourceProviderHandler, ResolveContext<Object>>();
+    public Collection<AuthenticatedResourceProvider> getAllUsedRefreshable() {
+        return refreshable;
     }
 
-    public ResolveContext<Object> getResolveContext(final ResourceProviderHandler handler) {
-        return this.contextMap.get(handler);
+    public Collection<AuthenticatedResourceProvider> getAllBestEffort(@Nonnull final List<ResourceProviderHandler> handlers,
+            @Nonnull final ResourceResolverControl control) {
+        final List<AuthenticatedResourceProvider> result = new ArrayList<AuthenticatedResourceProvider>(handlers.size());
+        for (final ResourceProviderHandler h : handlers) {
+            try {
+                final AuthenticatedResourceProvider rp = this.getOrCreateProvider(h, control);
+                if ( rp != null ) {
+                    result.add(rp);
+                }
+            } catch ( final LoginException le) {
+                // ignore
+            }
+        }
+        return result;
     }
 }

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecorator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecorator.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecorator.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecorator.java Fri Feb  5 10:19:24 2016
@@ -18,11 +18,9 @@
  */
 package org.apache.sling.resourceresolver.impl.providers.stateful;
 
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 
-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.ResourceResolver;
@@ -39,121 +37,58 @@ import org.slf4j.LoggerFactory;
  * This wrapper adds the Sling security layer (see
  * {@link ResourceAccessSecurity}) to the underlying {@link ResourceProvider}.
  */
-public class SecureResourceProviderDecorator implements StatefulResourceProvider {
+public class SecureResourceProviderDecorator extends AuthenticatedResourceProvider {
 
     private static final Logger logger = LoggerFactory.getLogger(ResourceResolverImpl.class);
 
-    private final StatefulResourceProvider rp;
-
     private final ResourceAccessSecurityTracker tracker;
 
-    public SecureResourceProviderDecorator(final StatefulResourceProvider rp, final ResourceAccessSecurityTracker tracker) {
-        this.rp = rp;
+    public SecureResourceProviderDecorator(final ResourceProvider<Object> provider,
+            final ResolveContext<Object> resolveContext,
+            final ResourceAccessSecurityTracker tracker) {
+        super(provider, resolveContext);
         if (tracker == null) {
             logger.warn("ResourceAccessSecurityTracker is null. Resource-level security will be disabled.");
         }
         this.tracker = tracker;
     }
 
-    @Override
-    public void logout() {
-        rp.logout();
-    }
-
-    @Override
-    public void refresh() {
-        rp.refresh();
-    }
-
-    @Override
-    public boolean isLive() {
-        return rp.isLive();
-    }
-
-    @Override
-    public Resource getParent(Resource child) {
-        return rp.getParent(child);
-    }
-
-    @Override
-    public Resource getResource(String path, Resource parent, Map<String, String> parameters, boolean isResolve) {
-        return rp.getResource(path, parent, parameters, isResolve);
-    }
-
-    @Override
-    public Iterator<Resource> listChildren(Resource parent) {
-        return rp.listChildren(parent);
-    }
-
-    @Override
-    public Collection<String> getAttributeNames() {
-        return rp.getAttributeNames();
-    }
-
-    @Override
-    public Object getAttribute(String name) {
-        return rp.getAttribute(name);
-    }
-
-    @Override
-    public void revert() {
-        rp.revert();
-    }
-
-    @Override
-    public void commit() throws PersistenceException {
-        rp.commit();
-    }
-
-    @Override
-    public boolean hasChanges() {
-        return rp.hasChanges();
-    }
-
-    @Override
-    public String[] getSupportedLanguages() {
-        return rp.getSupportedLanguages();
-    }
-
-    @Override
-    public Iterator<Map<String, Object>> queryResources(String query, String language) {
-        return rp.queryResources(query, language);
-    }
-
-    @Override
-    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
-        return rp.adaptTo(type);
+    private Resource wrapResource(Resource rsrc) {
+        if ( rsrc != null && tracker != null ) {
+            if (tracker.getProviderResourceAccessSecurity() != null) {
+                rsrc = tracker.getProviderResourceAccessSecurity().getReadableResource(rsrc);
+            }
+            if (rsrc != null && tracker.getApplicationResourceAccessSecurity() != null) {
+                rsrc = tracker.getApplicationResourceAccessSecurity().getReadableResource(rsrc);
+            }
+        }
+        return rsrc;
     }
 
     @Override
-    public boolean copy(String srcAbsPath, String destAbsPath) throws PersistenceException {
-        return rp.copy(srcAbsPath, destAbsPath);
+    public Resource getParent(final Resource child) {
+        return wrapResource(super.getParent(child));
     }
 
     @Override
-    public boolean move(String srcAbsPath, String destAbsPath) throws PersistenceException {
-        return rp.move(srcAbsPath, destAbsPath);
-    }
-
-   @Override
-    public ResourceProvider<Object> getResourceProvider() {
-        return rp.getResourceProvider();
+    public Resource getResource(final String path, final Resource parent, final Map<String, String> parameters, final boolean isResolve) {
+        return wrapResource(super.getResource(path, parent, parameters, isResolve));
     }
 
     @Override
-    public ResolveContext<Object> getContext() throws LoginException {
-        return rp.getContext();
+    public Iterator<Resource> listChildren(final Resource parent) {
+        return wrapIterator(super.listChildren(parent));
     }
 
     @Override
     public Resource create(final ResourceResolver resolver, final String path, Map<String, Object> properties) throws PersistenceException {
         if (isAllowed(new SecurityTest() {
-            @Override
-            public boolean isAllowed(ResourceAccessSecurity security) {
-                return security.canCreate(path, resolver);
-            }
-        })) {
-            return rp.create(resolver, path, properties);
+                @Override
+                public boolean isAllowed(ResourceAccessSecurity security) {
+                    return security.canCreate(path, resolver);
+                }
+            })) {
+            return super.create(resolver, path, properties);
         } else {
             return null;
         }
@@ -162,22 +97,24 @@ public class SecureResourceProviderDecor
     @Override
     public void delete(final Resource resource) throws PersistenceException {
         if (isAllowed(new SecurityTest() {
-            @Override
-            public boolean isAllowed(ResourceAccessSecurity security) {
-                return security.canDelete(resource);
-            }
-        })) {
-            rp.delete(resource);
+                @Override
+                public boolean isAllowed(ResourceAccessSecurity security) {
+                    return security.canDelete(resource);
+                }
+            })) {
+            super.delete(resource);
+        } else {
+            throw new PersistenceException("Unable to delete resource " + resource.getPath());
         }
     }
 
     @Override
     public Iterator<Resource> findResources(String query, String language) {
-        return wrapIterator(rp.findResources(query, language));
+        return wrapIterator(super.findResources(query, language));
     }
 
     private Iterator<Resource> wrapIterator(Iterator<Resource> iterator) {
-        if (tracker == null) {
+        if (tracker == null || iterator == null) {
             return iterator;
         } else {
             return new SecureIterator(iterator);

Modified: sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java (original)
+++ sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java Fri Feb  5 10:19:24 2016
@@ -51,7 +51,6 @@ import org.apache.sling.resourceresolver
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.stateful.ResourceProviderAuthenticator;
 import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
 import org.apache.sling.spi.resource.provider.ResolveContext;
 import org.apache.sling.spi.resource.provider.ResourceContext;
@@ -74,7 +73,6 @@ public class ResourceResolverControlTest
     // query definitions
     private static final String QUERY_MOCK_FIND_ALL = "FIND ALL";
 
-    private ResourceProviderAuthenticator authenticator;
     private ResourceResolverControl crp;
     private List<ResourceProviderHandler> handlers;
     private ResourceProvider<Object> subProvider;
@@ -140,9 +138,8 @@ public class ResourceResolverControlTest
 
         handlers = Arrays.asList(rootHandler, handler);
         ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
-        authenticator = new ResourceProviderAuthenticator(rr, authInfo, securityTracker);
 
-        crp = new ResourceResolverControl(false, authInfo, storage, authenticator);
+        crp = new ResourceResolverControl(false, authInfo, storage);
         context = new ResourceResolverContext(rr);
     }
 
@@ -178,7 +175,7 @@ public class ResourceResolverControlTest
     @Test
     public void loginLogout() throws LoginException {
 
-        authenticator.authenticateAll(handlers, crp);
+        context.getResolveContextManager().authenticateAll(handlers, crp);
 
         verify(subProvider).authenticate(authInfo);
 
@@ -360,7 +357,7 @@ public class ResourceResolverControlTest
     @Test
     public void queryLanguages() throws PersistenceException {
 
-        assertThat(crp.getSupportedLanguages(), arrayContainingInAnyOrder(QL_NOOP, QL_MOCK, QL_ANOTHER_MOCK));
+        assertThat(crp.getSupportedLanguages(context), arrayContainingInAnyOrder(QL_NOOP, QL_MOCK, QL_ANOTHER_MOCK));
     }
 
     /**
@@ -369,7 +366,7 @@ public class ResourceResolverControlTest
     @Test
     public void queryResources() throws PersistenceException {
 
-        Iterator<Map<String, Object>> queryResources = crp.queryResources(QUERY_MOCK_FIND_ALL, QL_MOCK);
+        Iterator<Map<String, Object>> queryResources = crp.queryResources(context, QUERY_MOCK_FIND_ALL, QL_MOCK);
 
         int count = 0;
 
@@ -387,7 +384,7 @@ public class ResourceResolverControlTest
     @Test
     public void findResource() throws PersistenceException {
 
-        Iterator<Resource> resources = crp.findResources(QUERY_MOCK_FIND_ALL, QL_MOCK);
+        Iterator<Resource> resources = crp.findResources(context, QUERY_MOCK_FIND_ALL, QL_MOCK);
 
         int count = 0;
 

Modified: sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/stateful/SecureResourceProviderDecoratorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/stateful/SecureResourceProviderDecoratorTest.java?rev=1728626&r1=1728625&r2=1728626&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/stateful/SecureResourceProviderDecoratorTest.java (original)
+++ sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/stateful/SecureResourceProviderDecoratorTest.java Fri Feb  5 10:19:24 2016
@@ -22,6 +22,7 @@ import static org.hamcrest.MatcherAssert
 import static org.hamcrest.Matchers.equalTo;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -36,7 +37,9 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.security.ResourceAccessSecurity;
 import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
 import org.apache.sling.resourceresolver.impl.providers.stateful.SecureResourceProviderDecorator;
-import org.apache.sling.resourceresolver.impl.providers.stateful.StatefulResourceProvider;
+import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -45,8 +48,9 @@ public class SecureResourceProviderDecor
 
     private ResourceAccessSecurity security;
     private ResourceResolver rr;
+    private ResolveContext resolveContext;
     private SecureResourceProviderDecorator src;
-    private StatefulResourceProvider rp;
+    private ResourceProvider rp;
     private Resource first;
     private Resource second;
 
@@ -54,6 +58,8 @@ public class SecureResourceProviderDecor
     public void prepare() throws PersistenceException {
 
         rr = mock(ResourceResolver.class);
+        resolveContext = mock(ResolveContext.class);
+        when(resolveContext.getResourceResolver()).thenReturn(rr);
 
         security = mock(ResourceAccessSecurity.class);
         first = mock(Resource.class);
@@ -62,9 +68,13 @@ public class SecureResourceProviderDecor
         when(security.getReadableResource(first)).thenReturn(first);
         when(security.getReadableResource(second)).thenReturn(null);
 
-        rp = mock(StatefulResourceProvider.class);
-        when(rp.create(rr, "/some/path", Collections.<String, Object> emptyMap())).thenReturn(mock(Resource.class));
-        when(rp.findResources("FIND ALL", "MockQueryLanguage")).thenReturn(Arrays.asList(first, second).iterator());
+        QueryLanguageProvider qlp = mock(QueryLanguageProvider.class);
+
+        rp = mock(ResourceProvider.class);
+        when(rp.getQueryLanguageProvider()).thenReturn(qlp);
+
+        when(rp.create(resolveContext, "/some/path", Collections.<String, Object> emptyMap())).thenReturn(mock(Resource.class));
+        when(qlp.findResources(resolveContext, "FIND ALL", "MockQueryLanguage")).thenReturn(Arrays.asList(first, second).iterator());
 
         ResourceAccessSecurityTracker securityTracker = new ResourceAccessSecurityTracker() {
             @Override
@@ -73,7 +83,7 @@ public class SecureResourceProviderDecor
             }
         };
 
-        src = new SecureResourceProviderDecorator(rp, securityTracker);
+        src = new SecureResourceProviderDecorator(rp, resolveContext, securityTracker);
 
     }
 
@@ -102,7 +112,7 @@ public class SecureResourceProviderDecor
 
         src.delete(toDelete);
 
-        verify(rp).delete(toDelete);
+        verify(rp).delete(resolveContext, toDelete);
     }
 
     @Test
@@ -112,7 +122,12 @@ public class SecureResourceProviderDecor
 
         when(security.canDelete(toDelete)).thenReturn(false);
 
-        src.delete(toDelete);
+        try {
+            src.delete(toDelete);
+            fail();
+        } catch ( PersistenceException pe ) {
+            // correct
+        }
 
         Mockito.verifyZeroInteractions(rp);
     }