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

[sling-org-apache-sling-resourceresolver] 01/01: SLING-7975 support ordering of resources

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/order-resource-api
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git

commit 7178783fc2a801f13b6f382d119008e666bede2e
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Oct 27 11:23:23 2021 +0200

    SLING-7975 support ordering of resources
---
 pom.xml                                            |  2 +-
 .../impl/ResourceResolverImpl.java                 | 11 +++-
 .../impl/helper/ResourceResolverControl.java       | 28 ++++++++
 .../stateful/AuthenticatedResourceProvider.java    | 75 ++++++++++++++++------
 4 files changed, 92 insertions(+), 24 deletions(-)

diff --git a/pom.xml b/pom.xml
index 309835e..074f496 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,7 +106,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.21.0</version>
+            <version>2.23.7-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
index 255176d..940ac1f 100644
--- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
+++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
@@ -32,11 +32,10 @@ import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.commons.lang3.StringUtils;
-import org.jetbrains.annotations.Nullable;
 import javax.jcr.Session;
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.adapter.annotations.Adaptable;
 import org.apache.sling.adapter.annotations.Adapter;
 import org.apache.sling.api.SlingException;
@@ -64,6 +63,8 @@ import org.apache.sling.resourceresolver.impl.mapping.ResourceMapperImpl;
 import org.apache.sling.resourceresolver.impl.params.ParsedParameters;
 import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -989,6 +990,12 @@ public class ResourceResolverImpl extends SlingAdaptable implements ResourceReso
         return this.factory.getResourceDecoratorTracker().decorate(rsrc);
     }
 
+    @Override
+    public boolean orderBefore(@NotNull Resource parent, @NotNull String name, @Nullable String followingSiblingName)
+            throws UnsupportedOperationException, PersistenceException, IllegalArgumentException {
+        return this.control.orderBefore(this.context, parent, name, followingSiblingName);
+    }
+
     /**
      * @see org.apache.sling.api.resource.ResourceResolver#revert()
      */
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
index efe76f5..10c3522 100644
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
+++ b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
@@ -395,6 +395,34 @@ public class ResourceResolverControl {
         throw new UnsupportedOperationException("create '" + ResourceUtil.getName(path) + "' at " + ResourceUtil.getParent(path));
     }
 
+    /*
+     * @see ResourceResolver#orderBefore(Resource, String, String)
+     */
+    public boolean orderBefore(@NotNull final ResourceResolverContext context,  @NotNull final Resource parent, @NotNull final String name, @Nullable final String followingSiblingName)
+            throws UnsupportedOperationException, PersistenceException, IllegalArgumentException {
+        final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, parent.getPath());
+        if (provider != null) {
+            // make sure all children are from the same provider and both names are valid
+            AuthenticatedResourceProvider childProvider = getBestMatchingModifiableProvider(context, parent.getPath() + "/" + name);
+            if (childProvider == null) {
+                throw new IllegalArgumentException("The given name '" + name + "' is not a valid child name in resource " + parent.getPath());
+            }
+            if (provider != childProvider) {
+                throw new UnsupportedOperationException("orderBefore '" + name + "' at " + parent.getPath() + " as children are not provided by the same provider as the parent resource");
+            }
+            if (followingSiblingName != null) {
+                childProvider = getBestMatchingModifiableProvider(context, parent.getPath() + "/" + followingSiblingName);
+                if (childProvider == null) {
+                    throw new IllegalArgumentException("The given name '" + followingSiblingName + "' is not a valid child name in resource " + parent.getPath());
+                }
+                if (provider != childProvider) {
+                    throw new UnsupportedOperationException("orderBefore '" + name + "' at " + parent.getPath() + " as sibling child resources are not provided by the same provider");
+                }
+            }
+            return provider.orderBefore(parent, name, followingSiblingName);
+        }
+        throw new UnsupportedOperationException("orderBefore '" + name + "' at " + parent.getPath());
+    }
     /**
      * Delete the resource. Iterate over all modifiable ResourceProviders
      * giving each an opportunity to delete the resource if they are able.
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
index 1b0807c..9b49c3d 100644
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
+++ b/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
@@ -44,9 +44,9 @@ import org.slf4j.LoggerFactory;
 
 /**
  * This {@link AuthenticatedResourceProvider} implementation keeps a resource
- * provider and the authentication information (through the {@link ResolveContext}.
+ * provider and the authentication information (through the {@link ResolveContext}).
  *
- * The methods are similar to {@link ResourceProvider}.
+ * The methods are similar to those of {@link ResourceProvider}.
  */
 public class AuthenticatedResourceProvider {
 
@@ -81,7 +81,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#refresh(ResolveContext)}
+     * @see {@link ResourceProvider#refresh(ResolveContext)}
      */
     public void refresh() {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -91,7 +91,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#isLive(ResolveContext)}
+     * @see {@link ResourceProvider#isLive(ResolveContext)}
      */
     public boolean isLive() {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -102,7 +102,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#getParent(ResolveContext, Resource)}
+     * @see {@link ResourceProvider#getParent(ResolveContext, Resource)}
      */
     public Resource getParent(final Resource child) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -113,7 +113,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#getResource(ResolveContext, String, ResourceContext, Resource)}
+     * @see {@link ResourceProvider#getResource(ResolveContext, String, ResourceContext, Resource)}
      */
     public Resource getResource(final String path, final Resource parent, final Map<String, String> parameters) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -136,7 +136,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#listChildren(ResolveContext, Resource)}
+     * @see {@link ResourceProvider#listChildren(ResolveContext, Resource)}
      */
     public Iterator<Resource> listChildren(final Resource parent) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -147,7 +147,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#getAttributeNames(ResolveContext)}
+     * @see {@link ResourceProvider#getAttributeNames(ResolveContext)}
      */
     public void getAttributeNames(final Set<String> attributeNames) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -160,7 +160,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#getAttribute(ResolveContext, String)}
+     * @see {@link ResourceProvider#getAttribute(ResolveContext, String)}
      */
     public Object getAttribute(final String name) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -171,7 +171,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#create(ResolveContext, String, Map)}
+     * @see {@link ResourceProvider#create(ResolveContext, String, Map)}
      */
     public Resource create(final ResourceResolver resolver,
             final String path,
@@ -185,7 +185,20 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#delete(ResolveContext, Resource)}
+     * @see {@link ResourceProvider#orderBefore(ResolveContext, Resource, String, String)
+     */
+    public boolean orderBefore(final @NotNull Resource parent, final @NotNull String name, final @Nullable String followingSiblingName) 
+        throws PersistenceException {
+        final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
+        if (rp != null && this.canReorderChildren(parent)) {
+            return rp.orderBefore(this.resolveContext, parent, name, followingSiblingName);
+        } else {
+            throw new PersistenceException("Unable to order child resources of " + parent.getPath());
+        }
+    }
+    
+    /**
+     * @see {@link ResourceProvider#delete(ResolveContext, Resource)}
      */
     public void delete(final Resource resource) throws PersistenceException {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -197,7 +210,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#revert(ResolveContext)}
+     * @see {@link ResourceProvider#revert(ResolveContext)}
      */
     public void revert() {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -207,7 +220,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#commit(ResolveContext)}
+     * @see {@link ResourceProvider#commit(ResolveContext)}
      */
     public void commit() throws PersistenceException {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -217,7 +230,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#hasChanges(ResolveContext)}
+     * @see {@link ResourceProvider#hasChanges(ResolveContext)}
      */
     public boolean hasChanges() {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -228,7 +241,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#getQueryLanguageProvider()}
+     * @see {@link ResourceProvider#getQueryLanguageProvider()}
      */
     private QueryLanguageProvider<Object> getQueryLanguageProvider() {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -239,7 +252,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link QueryLanguageProvider#getSupportedLanguages(ResolveContext)}
+     * @see {@link QueryLanguageProvider#getSupportedLanguages(ResolveContext)}
      */
     public String[] getSupportedLanguages() {
         final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
@@ -250,7 +263,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link QueryLanguageProvider}{@link #findResources(String, String)}
+     * @see {@link QueryLanguageProvider}{@link #findResources(String, String)}
      */
     public Iterator<Resource> findResources(final String query, final String language) {
         final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
@@ -261,7 +274,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link QueryLanguageProvider#queryResources(ResolveContext, String, String)}
+     * @see {@link QueryLanguageProvider#queryResources(ResolveContext, String, String)}
      */
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public Iterator<Map<String, Object>> queryResources(final String query, final String language) {
@@ -273,7 +286,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#adaptTo(ResolveContext, Class)}
+     * @see {@link ResourceProvider#adaptTo(ResolveContext, Class)}
      */
     public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -284,7 +297,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#copy(ResolveContext, String, String)}
+     * @see {@link ResourceProvider#copy(ResolveContext, String, String)}
      */
     public boolean copy(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -295,7 +308,7 @@ public class AuthenticatedResourceProvider {
     }
 
     /**
-     * #see {@link ResourceProvider#move(ResolveContext, String, String)}
+     * @see {@link ResourceProvider#move(ResolveContext, String, String)}
      */
     public boolean move(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
         final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
@@ -325,6 +338,26 @@ public class AuthenticatedResourceProvider {
         return allowed;
     }
 
+    private boolean canReorderChildren(final Resource resource) {
+        boolean allowed = true;
+        if ( this.useRAS ) {
+            final ResourceAccessSecurity security = tracker.getProviderResourceAccessSecurity();
+            if ( security != null ) {
+                allowed = security.canReorderChildren(resource);
+            } else {
+                allowed = false;
+            }
+        }
+
+        if ( allowed ) {
+            final ResourceAccessSecurity security = tracker.getApplicationResourceAccessSecurity();
+            if (security != null) {
+                allowed = security.canReorderChildren(resource);
+            }
+        }
+        return allowed;
+    }
+
     private boolean canDelete(final Resource resource) {
         boolean allowed = true;
         if ( this.useRAS ) {