You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2016/09/26 06:50:47 UTC

svn commit: r1762277 - in /jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs: impl/io/DocViewSAXImporter.java impl/io/JackrabbitACLImporter.java spi/ACLManagement.java spi/impl/jcr20/JcrACLManagement.java

Author: tripod
Date: Mon Sep 26 06:50:47 2016
New Revision: 1762277

URL: http://svn.apache.org/viewvc?rev=1762277&view=rev
Log:
JCRVLT-111 Add support for o.a.j.api.security.authorization.PrincipalSetPolicy

Modified:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ACLManagement.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java?rev=1762277&r1=1762276&r2=1762277&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java Mon Sep 26 06:50:47 2016
@@ -613,9 +613,9 @@ public class DocViewSAXImporter extends
                         DocViewNode ni = new DocViewNode(name, label, attributes, npResolver);
                         if (aclManagement.isACLNodeType(ni.primary)) {
                             if (aclHandling != AccessControlHandling.CLEAR && aclHandling != AccessControlHandling.IGNORE) {
-                                log.debug("ACL element detected. starting special transformation {}/{}", node.getPath(), name);
-                                if (aclManagement.ensureAccessControllable(node)) {
-                                    log.info("Adding ACL element to non ACL parent - adding mixin: {}", node.getPath());
+                                log.debug("Access control policy element detected. starting special transformation {}/{}", node.getPath(), name);
+                                if (aclManagement.ensureAccessControllable(node, ni.primary)) {
+                                    log.info("Adding access control policy element to non access-controllable parent - adding mixin: {}", node.getPath());
                                 }
                                 stack = stack.push();
                                 if ("rep:repoPolicy".equals(name)) {

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java?rev=1762277&r1=1762276&r2=1762277&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java Mon Sep 26 06:50:47 2016
@@ -39,6 +39,7 @@ import javax.jcr.security.Privilege;
 
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.authorization.PrincipalSetPolicy;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
 import org.apache.jackrabbit.vault.util.DocViewNode;
@@ -67,16 +68,15 @@ public class JackrabbitACLImporter imple
 
     private final String accessControlledPath;
 
-    private Map<String, List<ACE>> aceMap = new LinkedHashMap<String, List<ACE>>();
+    private ImportedPolicy importPolicy;
 
-    private ACE currentACE;
-
-    private static enum State {
+    private enum State {
         INITIAL,
         ACL,
         ACE,
         RESTRICTION,
         ERROR,
+        PRINCIPAL_SET_POLICY
     }
 
     private final Stack<State> states = new Stack<State>();
@@ -104,35 +104,28 @@ public class JackrabbitACLImporter imple
         this.states.push(State.INITIAL);
     }
 
-
     public void startNode(DocViewNode node) throws SAXException {
         State state = states.peek();
         switch (state) {
             case INITIAL:
                 if ("rep:ACL".equals(node.primary)) {
+                    importPolicy = new ImportedAcList();
                     state = State.ACL;
+                } else if ("rep:CugPolicy".equals(node.primary)) {
+                    importPolicy = new ImportedPrincipalSet(node);
+                    state = State.PRINCIPAL_SET_POLICY;
                 } else {
-                    log.error("Error while reading access control content: Expected rep:ACL but was: {}", node.primary);
+                    log.error("Error while reading access control content: Expected rep:ACL or rep:CugPolicy but was: {}", node.primary);
                     state = State.ERROR;
                 }
                 break;
-
             case ACL:
-                try {
-                    currentACE = addACE(aceMap, new ACE(node));
-                    state = State.ACE;
-                } catch (IllegalArgumentException e) {
-                    log.error("Error while reading access control content: {}", e);
-                    state = State.ERROR;
-                }
-                break;
             case ACE:
-                currentACE.addRestrictions(node);
-                state = State.RESTRICTION;
-                break;
             case RESTRICTION:
-                log.error("Error while reading access control content: Unexpected node: {} for state {}", node.primary, state);
-                state = State.ERROR;
+                state = importPolicy.append(state, node);
+                break;
+            case PRINCIPAL_SET_POLICY:
+                state = importPolicy.append(state, node);
                 break;
             case ERROR:
                 // stay in error
@@ -153,9 +146,7 @@ public class JackrabbitACLImporter imple
 
     public void endNode() throws SAXException {
         State state = states.pop();
-        if (state == State.ACE) {
-            currentACE = null;
-        }
+        importPolicy.endNode(state);
     }
 
     public List<String> close() throws SAXException {
@@ -164,16 +155,7 @@ public class JackrabbitACLImporter imple
         }
         List<String> paths = new ArrayList<String>();
         try {
-            apply();
-
-            // currently cheat a little here
-            if (accessControlledPath == null) {
-                addPathIfExists(paths, "/rep:repoPolicy");
-            } else if ("/".equals(accessControlledPath)) {
-                addPathIfExists(paths, "/rep:policy");
-            } else {
-                addPathIfExists(paths, accessControlledPath + "/rep:policy");
-            }
+            importPolicy.apply(paths);
         } catch (RepositoryException e) {
             log.error("Error while applying access control content.", e);
         }
@@ -186,42 +168,107 @@ public class JackrabbitACLImporter imple
         }
     }
 
-    private void apply() throws RepositoryException {
-        final ValueFactory valueFactory = session.getValueFactory();
+    private abstract class ImportedPolicy<T extends AccessControlPolicy> {
 
-        // find principals of existing ACL
-        JackrabbitAccessControlList acl = null;
-        Set<String> existingPrincipals = new HashSet<String>();
-        for (AccessControlPolicy p: acMgr.getPolicies(accessControlledPath)) {
-            if (p instanceof JackrabbitAccessControlList) {
-                acl = (JackrabbitAccessControlList) p;
-                for (AccessControlEntry ace: acl.getAccessControlEntries()) {
-                    existingPrincipals.add(ace.getPrincipal().getName());
-                }
+        abstract State append(State state, DocViewNode childNode);
+
+        abstract void endNode(State state);
+
+        abstract void apply(List<String> paths) throws RepositoryException;
+
+        Principal getPrincipal(final String principalName) {
+            Principal principal = pMgr.getPrincipal(principalName);
+            if (principal == null) {
+                principal = new Principal() {
+                    public String getName() {
+                        return principalName;
+                    }
+                };
             }
+            return principal;
         }
 
-        // remove existing policy for 'overwrite'
-        if (aclHandling == AccessControlHandling.OVERWRITE && acl != null) {
-            acMgr.removePolicy(accessControlledPath, acl);
-            acl = null;
+        T getPolicy(Class<T> clz) throws RepositoryException {
+            for (AccessControlPolicy p : acMgr.getPolicies(accessControlledPath)) {
+                if (clz.isAssignableFrom(p.getClass())) {
+                    return (T) p;
+                }
+            }
+            return null;
         }
 
-        if (acl == null) {
+        T getApplicablePolicy(Class<T> clz) throws RepositoryException {
             AccessControlPolicyIterator iter = acMgr.getApplicablePolicies(accessControlledPath);
             while (iter.hasNext()) {
                 AccessControlPolicy p = iter.nextAccessControlPolicy();
-                if (p instanceof JackrabbitAccessControlList) {
-                    acl = (JackrabbitAccessControlList) p;
-                    break;
+                if (clz.isAssignableFrom(p.getClass())) {
+                    return (T) p;
+                }
+            }
+
+            // no applicable policy
+            throw new RepositoryException("no applicable AccessControlPolicy of type "+ clz + " on " +
+                                    (accessControlledPath == null ? "'root'" : accessControlledPath));
+        }
+    }
+
+    private final class ImportedAcList extends ImportedPolicy<JackrabbitAccessControlList> {
+
+        private Map<String, List<ACE>> aceMap = new LinkedHashMap<String, List<ACE>>();
+        private ACE currentACE;
+
+        private ImportedAcList() {
+        }
+
+        @Override
+        State append(State state, DocViewNode childNode) {
+            if (state == State.ACL) {
+                try {
+                    currentACE = addACE(aceMap, new ACE(childNode));
+                    return State.ACE;
+                } catch (IllegalArgumentException e) {
+                    log.error("Error while reading access control content: {}", e);
+                    return State.ERROR;
                 }
+            } else if (state == State.ACE) {
+                currentACE.addRestrictions(childNode);
+                return State.RESTRICTION;
+            } else {
+                log.error("Error while reading access control content: Unexpected node: {} for state {}", childNode.primary, state);
+                return State.ERROR;
             }
         }
-        if (acl == null) {
-            throw new RepositoryException("not JackrabbitAccessControlList applicable on " +
-                    (accessControlledPath == null ? "'root'" : accessControlledPath));
+
+        @Override
+        void endNode(State state) {
+            if (state == State.ACE) {
+                currentACE = null;
+            }
         }
 
+        @Override
+        void apply(List<String> paths) throws RepositoryException {
+            final ValueFactory valueFactory = session.getValueFactory();
+
+            // find principals of existing ACL
+            JackrabbitAccessControlList acl = getPolicy(JackrabbitAccessControlList.class);
+            Set<String> existingPrincipals = new HashSet<String>();
+            if (acl != null) {
+                for (AccessControlEntry ace: acl.getAccessControlEntries()) {
+                    existingPrincipals.add(ace.getPrincipal().getName());
+                }
+
+                // remove existing policy for 'overwrite'
+                if (aclHandling == AccessControlHandling.OVERWRITE) {
+                    acMgr.removePolicy(accessControlledPath, acl);
+                    acl = null;
+                }
+            }
+
+            if (acl == null) {
+                acl = getApplicablePolicy(JackrabbitAccessControlList.class);
+            }
+
         // clear all ACEs of the package principals for merge (VLT-94), otherwise the `acl.addEntry()` below
         // might just combine the privileges.
         if (aclHandling == AccessControlHandling.MERGE) {
@@ -234,48 +281,102 @@ public class JackrabbitACLImporter imple
             }
         }
 
-        // apply ACEs of package
-        for (Map.Entry<String, List<ACE>> entry: aceMap.entrySet()) {
-            final String principalName = entry.getKey();
-            if (aclHandling == AccessControlHandling.MERGE_PRESERVE && existingPrincipals.contains(principalName)) {
-                // skip principal if it already has an ACL
-                continue;
-            }
-            Principal principal = pMgr.getPrincipal(principalName);
-            if (principal == null) {
-                principal = new Principal(){
-                    public String getName() {
-                        return principalName;
-                    }
-                };
-            }
+            // apply ACEs of package
+            for (Map.Entry<String, List<ACE>> entry: aceMap.entrySet()) {
+                final String principalName = entry.getKey();
+                if (aclHandling == AccessControlHandling.MERGE_PRESERVE && existingPrincipals.contains(principalName)) {
+                    // skip principal if it already has an ACL
+                    continue;
+                }
+                Principal principal = getPrincipal(principalName);
 
-            for (ACE ace: entry.getValue()) {
-                Privilege[] privileges = new Privilege[ace.privileges.length];
-                for (int i = 0; i < privileges.length; i++) {
-                    privileges[i] = acMgr.privilegeFromName(ace.privileges[i]);
-                }
-                Map<String, Value> svRestrictions = new HashMap<String, Value>();
-                Map<String, Value[]> mvRestrictions = new HashMap<String, Value[]>();
-                for (String restName : acl.getRestrictionNames()) {
-                    DocViewProperty restriction = ace.restrictions.get(restName);
-                    if (restriction != null) {
-                        Value[] values = new Value[restriction.values.length];
-                        int type = acl.getRestrictionType(restName);
-                        for (int i=0; i<values.length; i++) {
-                            values[i] = valueFactory.createValue(restriction.values[i], type);
-                        }
-                        if (restriction.isMulti) {
-                            mvRestrictions.put(restName, values);
-                        } else {
-                            svRestrictions.put(restName, values[0]);
+                for (ACE ace: entry.getValue()) {
+                    Privilege[] privileges = new Privilege[ace.privileges.length];
+                    for (int i = 0; i < privileges.length; i++) {
+                        privileges[i] = acMgr.privilegeFromName(ace.privileges[i]);
+                    }
+                    Map<String, Value> svRestrictions = new HashMap<String, Value>();
+                    Map<String, Value[]> mvRestrictions = new HashMap<String, Value[]>();
+                    for (String restName : acl.getRestrictionNames()) {
+                        DocViewProperty restriction = ace.restrictions.get(restName);
+                        if (restriction != null) {
+                            Value[] values = new Value[restriction.values.length];
+                            int type = acl.getRestrictionType(restName);
+                            for (int i=0; i<values.length; i++) {
+                                values[i] = valueFactory.createValue(restriction.values[i], type);
+                            }
+                            if (restriction.isMulti) {
+                                mvRestrictions.put(restName, values);
+                            } else {
+                                svRestrictions.put(restName, values[0]);
+                            }
                         }
                     }
+                    acl.addEntry(principal, privileges, ace.allow, svRestrictions, mvRestrictions);
                 }
-                acl.addEntry(principal, privileges, ace.allow, svRestrictions, mvRestrictions);
+            }
+            acMgr.setPolicy(accessControlledPath, acl);
+
+            if (accessControlledPath == null) {
+                addPathIfExists(paths, "/rep:repoPolicy");
+            } else if ("/".equals(accessControlledPath)) {
+                addPathIfExists(paths, "/rep:policy");
+            } else {
+                addPathIfExists(paths, accessControlledPath + "/rep:policy");
+            }
+        }
+    }
+
+    private final class ImportedPrincipalSet extends ImportedPolicy<PrincipalSetPolicy> {
+
+        private final String[] principalNames;
+
+        private ImportedPrincipalSet(DocViewNode node) {
+            // don't change the status as a cug policy may not have child nodes.
+            // just collect the rep:principalNames property
+            // any subsequent state would indicate an error
+            principalNames = node.getValues("rep:principalNames");
+        }
+
+        @Override
+        State append(State state, DocViewNode childNode) {
+            log.error("Error while reading access control content: Unexpected node: {} for state {}", childNode.primary, state);
+            return State.ERROR;
+        }
+
+        @Override
+        void endNode(State state) {
+            // nothing to do
+        }
+
+        @Override
+        void apply(List<String> paths) throws RepositoryException {
+            PrincipalSetPolicy psPolicy = getPolicy(PrincipalSetPolicy.class);
+            if (psPolicy != null) {
+                Set<Principal> existingPrincipals = psPolicy.getPrincipals();
+                // remove existing policy for 'overwrite'
+                if (aclHandling == AccessControlHandling.OVERWRITE) {
+                    psPolicy.removePrincipals(existingPrincipals.toArray(new Principal[existingPrincipals.size()]));
+                }
+            } else {
+                psPolicy = getApplicablePolicy(PrincipalSetPolicy.class);
+            }
+
+            // TODO: correct behavior for MERGE and MERGE_PRESERVE?
+            Principal[] principals = new Principal[principalNames.length];
+            for (int i = 0; i < principals.length; i++) {
+                principals[i] = getPrincipal(principalNames[i]);
+            }
+
+            psPolicy.addPrincipals(principals);
+            acMgr.setPolicy(accessControlledPath, psPolicy);
+
+            if ("/".equals(accessControlledPath)) {
+                addPathIfExists(paths, "/rep:cugPolicy");
+            } else {
+                addPathIfExists(paths, accessControlledPath + "/rep:cugPolicy");
             }
         }
-        acMgr.setPolicy(accessControlledPath, acl);
     }
 
     private static class ACE {

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ACLManagement.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ACLManagement.java?rev=1762277&r1=1762276&r2=1762277&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ACLManagement.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ACLManagement.java Mon Sep 26 06:50:47 2016
@@ -54,10 +54,11 @@ public interface ACLManagement {
      * mixin and adds it if missing.
      *
      * @param node the node to check
+     * @param policyPrimaryType Primary node type of policy
      * @return <code>true</code> if was made access controllable
      * @throws RepositoryException if an error occurs
      */
-    boolean ensureAccessControllable(Node node) throws RepositoryException;
+    boolean ensureAccessControllable(Node node, String policyPrimaryType) throws RepositoryException;
 
     /**
      * Removes all ACLs from the given node.

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java?rev=1762277&r1=1762276&r2=1762277&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java Mon Sep 26 06:50:47 2016
@@ -33,14 +33,16 @@ public class JcrACLManagement implements
      * {@inheritDoc}
      */
     public boolean isACLNodeType(String name) {
-        return name.equals("rep:ACL");
+        return name.equals("rep:ACL") || name.equals("rep:CugPolicy");
     }
 
     /**
      * {@inheritDoc}
      */
     public boolean isAccessControllableMixin(String name) {
-        return name.equals("rep:AccessControllable") || name.equals("rep:RepoAccessControllable");
+        return name.equals("rep:AccessControllable")
+                || name.equals("rep:RepoAccessControllable")
+                || name.equals("rep:CugMixin");
     }
 
     /**
@@ -53,15 +55,22 @@ public class JcrACLManagement implements
     /**
      * {@inheritDoc}
      */
-    public boolean ensureAccessControllable(Node node) throws RepositoryException {
+    public boolean ensureAccessControllable(Node node, String policyPrimaryType) throws RepositoryException {
         boolean modified = false;
-        if (!node.isNodeType("rep:AccessControllable")) {
-            node.addMixin("rep:AccessControllable");
-            modified = true;
-        }
-        if (isRootNode(node) && !node.isNodeType("rep:RepoAccessControllable")) {
-            node.addMixin("rep:RepoAccessControllable");
-            modified = true;
+        if ("rep:ACL".equals(policyPrimaryType)) {
+            if (!node.isNodeType("rep:AccessControllable")) {
+                node.addMixin("rep:AccessControllable");
+                modified = true;
+            }
+            if (isRootNode(node) && !node.isNodeType("rep:RepoAccessControllable")) {
+                node.addMixin("rep:RepoAccessControllable");
+                modified = true;
+            }
+        } else if ("rep:CugPolicy".equals(policyPrimaryType)) {
+            if (!node.isNodeType("rep:CugMixin")) {
+                node.addMixin("rep:CugMixin");
+                modified = true;
+            }
         }
         return modified;
     }