You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by an...@apache.org on 2021/05/20 09:42:08 UTC

[sling-org-apache-sling-jcr-repoinit] 01/01: SLING-10406 : AclVisitor.visitCreatePath: retry if no default primary type can be found

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

angela pushed a commit to branch SLING-10406
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git

commit e28553cafe4c896cd40fd94ce30d8bb0d33e8a2e
Author: angela <an...@adobe.com>
AuthorDate: Thu May 20 11:41:50 2021 +0200

    SLING-10406 : AclVisitor.visitCreatePath: retry if no default primary type can be found
---
 .../apache/sling/jcr/repoinit/impl/AclVisitor.java | 89 ++++++++++++++--------
 .../apache/sling/jcr/repoinit/CreatePathsTest.java | 15 ++++
 2 files changed, 72 insertions(+), 32 deletions(-)

diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
index 45659f6..9e363ef 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
@@ -26,6 +26,7 @@ import java.util.List;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.ConstraintViolationException;
 
 import org.apache.sling.repoinit.parser.operations.AclLine;
 import org.apache.sling.repoinit.parser.operations.CreatePath;
@@ -37,16 +38,24 @@ import org.apache.sling.repoinit.parser.operations.RestrictionClause;
 import org.apache.sling.repoinit.parser.operations.SetAclPaths;
 import org.apache.sling.repoinit.parser.operations.SetAclPrincipalBased;
 import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-/** OperationVisitor which processes only operations related to ACLs.
+/**
+ * OperationVisitor which processes only operations related to ACLs.
  * Having several such specialized visitors
  * makes it easy to control the execution order.
  */
 class AclVisitor extends DoNothingVisitor {
 
-    /** Create a visitor using the supplied JCR Session.
+    private static final Logger log = LoggerFactory.getLogger(AclVisitor.class);
+    
+    /**
+     * Create a visitor using the supplied JCR Session.
+     *
      * @param s must have sufficient rights to create users
-     *      and set ACLs.
+     *          and set ACLs.
      */
     public AclVisitor(Session s) {
         super(s);
@@ -54,7 +63,7 @@ class AclVisitor extends DoNothingVisitor {
 
     private List<String> require(AclLine line, String propertyName) {
         final List<String> result = line.getProperty(propertyName);
-        if(result == null) {
+        if (result == null) {
             throw new IllegalStateException("Missing property " + propertyName + " on " + line);
         }
         return result;
@@ -72,7 +81,7 @@ class AclVisitor extends DoNothingVisitor {
                 List<RestrictionClause> restrictions = line.getRestrictions();
                 AclUtil.setAcl(s, principals, paths, privileges, isAllow, restrictions);
             }
-        } catch(Exception e) {
+        } catch (Exception e) {
             throw new RuntimeException("Failed to set ACL (" + e.toString() + ") " + line, e);
         }
     }
@@ -89,7 +98,7 @@ class AclVisitor extends DoNothingVisitor {
                 List<RestrictionClause> restrictions = line.getRestrictions();
                 AclUtil.setRepositoryAcl(s, principals, privileges, isAllow, restrictions);
             }
-        } catch(Exception e) {
+        } catch (Exception e) {
             throw new RuntimeException("Failed to set repository level ACL (" + e.toString() + ") " + line, e);
         }
     }
@@ -99,13 +108,13 @@ class AclVisitor extends DoNothingVisitor {
         final List<String> principals = s.getPrincipals();
         for (AclLine line : s.getLines()) {
             final List<String> paths = line.getProperty(PROP_PATHS);
-            if (paths != null && ! paths.isEmpty()) {
+            if (paths != null && !paths.isEmpty()) {
                 setAcl(line, session, principals, paths, require(line, PROP_PRIVILEGES), line.getAction());
             } else {
                 setRepositoryAcl(line, session, principals, require(line, PROP_PRIVILEGES), line.getAction());
             }
         }
-     }
+    }
 
     @Override
     public void visitSetAclPaths(SetAclPaths s) {
@@ -121,7 +130,7 @@ class AclVisitor extends DoNothingVisitor {
             try {
                 log.info("Adding principal-based access control entry for {}", principalName);
                 AclUtil.setPrincipalAcl(session, principalName, s.getLines());
-            } catch(Exception e) {
+            } catch (Exception e) {
                 throw new RuntimeException("Failed to set principal-based ACL (" + e.getMessage() + ")", e);
             }
         }
@@ -130,35 +139,51 @@ class AclVisitor extends DoNothingVisitor {
     @Override
     public void visitCreatePath(CreatePath cp) {
         String parentPath = "";
-            for(PathSegmentDefinition psd : cp.getDefinitions()) {
-                final String fullPath = parentPath + "/" + psd.getSegment();
-                try {
-                    if(session.itemExists(fullPath)) {
-                        log.info("Path already exists, nothing to do (and not checking its primary type for now): {}", fullPath);
-                    } else {
-                        final Node parent = parentPath.equals("") ? session.getRootNode() : session.getNode(parentPath);
-                        log.info("Creating node {} with primary type {}", fullPath, psd.getPrimaryType());
-                        Node node = parent.addNode(psd.getSegment(), psd.getPrimaryType());
-                        List<String> mixins = psd.getMixins();
-                        if (mixins != null) {
-                            log.info("Adding mixins {} to node {}", mixins, fullPath);
-                            for (String mixin : mixins) {
-                                node.addMixin(mixin);
-                            }
+        for (PathSegmentDefinition psd : cp.getDefinitions()) {
+            final String fullPath = parentPath + "/" + psd.getSegment();
+            try {
+                if (session.itemExists(fullPath)) {
+                    log.info("Path already exists, nothing to do (and not checking its primary type for now): {}", fullPath);
+                } else {
+                    final Node parent = parentPath.equals("") ? session.getRootNode() : session.getNode(parentPath);
+                    log.info("Creating node {} with primary type {}", fullPath, psd.getPrimaryType());
+                    Node node = addChildNode(parent, psd);
+                    List<String> mixins = psd.getMixins();
+                    if (mixins != null) {
+                        log.info("Adding mixins {} to node {}", mixins, fullPath);
+                        for (String mixin : mixins) {
+                            node.addMixin(mixin);
                         }
                     }
-                } catch(Exception e) {
-                    throw new RuntimeException("CreatePath execution failed at " + psd + ": " + e, e);
                 }
-                parentPath += "/" + psd.getSegment();
+            } catch (Exception e) {
+                throw new RuntimeException("CreatePath execution failed at " + psd + ": " + e, e);
             }
+            parentPath += "/" + psd.getSegment();
+        }
         try {
             session.save();
-        } catch(Exception e) {
-            throw new RuntimeException("Session.save failed: "+ e, e);
+        } catch (Exception e) {
+            throw new RuntimeException("Session.save failed: " + e, e);
         }
     }
     
+    @NotNull
+    private static Node addChildNode(@NotNull Node parent, @NotNull PathSegmentDefinition psd) throws RepositoryException {
+        String primaryType = psd.getPrimaryType();
+        if (primaryType == null) {
+            try {
+                return parent.addNode(psd.getSegment());
+            } catch (ConstraintViolationException e) {
+                // assume that no default primary type could be detected -> retry with a default
+                log.info("Adding Node without node type failed ('{}'), retry with sling:Folder", e.getMessage());
+                return parent.addNode(psd.getSegment(), "sling:Folder");
+            }
+        } else {
+            return parent.addNode(psd.getSegment(), psd.getPrimaryType());
+        }
+    }
+
     @Override
     public void visitDeleteAclPrincipals(DeleteAclPrincipals s) {
         for (String principalName : s.getPrincipals()) {
@@ -166,7 +191,7 @@ class AclVisitor extends DoNothingVisitor {
                 log.info("Removing access control policy for {}", principalName);
                 AclUtil.removePolicy(session, principalName);
             } catch (RepositoryException e) {
-                throw new RuntimeException("Failed to remove ACL ("+e.getMessage()+")");
+                throw new RuntimeException("Failed to remove ACL (" + e.getMessage() + ")");
             }
         }
     }
@@ -176,7 +201,7 @@ class AclVisitor extends DoNothingVisitor {
         try {
             AclUtil.removePolicies(session, s.getPaths());
         } catch (RepositoryException e) {
-            throw new RuntimeException("Failed to remove ACL ("+e.getMessage()+")");
+            throw new RuntimeException("Failed to remove ACL (" + e.getMessage() + ")");
         }
     }
 
@@ -187,7 +212,7 @@ class AclVisitor extends DoNothingVisitor {
                 log.info("Removing principal-based access control policy for {}", principalName);
                 AclUtil.removePrincipalPolicy(session, principalName);
             } catch (RepositoryException e) {
-                throw new RuntimeException("Failed to remove principal-based ACL ("+e.getMessage()+")");
+                throw new RuntimeException("Failed to remove principal-based ACL (" + e.getMessage() + ")");
             }
         }
     }
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/CreatePathsTest.java b/src/test/java/org/apache/sling/jcr/repoinit/CreatePathsTest.java
index 38b33e6..cb356d9 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/CreatePathsTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/CreatePathsTest.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
 
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
 import org.apache.sling.commons.testing.jcr.RepositoryUtil;
@@ -30,6 +31,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
+
 /** Test the creation of paths with specific node types */
 public class CreatePathsTest {
     
@@ -124,4 +127,16 @@ public class CreatePathsTest {
         U.assertNodeExists("/thirteen/fourteen", "nt:unstructured", Collections.singletonList("mix:lockable"));
         U.assertNodeExists("/thirteen/fourteen/fifteen", "nt:unstructured", Collections.singletonList("mix:lockable"));
     }
+    
+    @Test
+    public void createPathNoDefaultPrimaryType() throws Exception {
+        U.adminSession.getRootNode().addNode("folder", "nt:folder");
+        U.parseAndExecute("create path /folder/subfolder/subfolder2");
+        
+        Node subFolder = U.adminSession.getNode("/folder/subfolder");
+        assertEquals("sling:Folder", subFolder.getPrimaryNodeType().getName());
+
+        Node subFolder2 = subFolder.getNode("subfolder2");
+        assertEquals("sling:Folder", subFolder2.getPrimaryNodeType().getName());
+    }
 }