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:34 UTC

[sling-org-apache-sling-resourceresolver] branch feature/order-resource-api created (now 7178783)

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

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


      at 7178783  SLING-7975 support ordering of resources

This branch includes the following new commits:

     new 7178783  SLING-7975 support ordering of resources

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


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

Posted by kw...@apache.org.
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 ) {