You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2012/06/06 15:57:29 UTC

svn commit: r1346895 - in /jackrabbit/oak/trunk: oak-core/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr...

Author: angela
Date: Wed Jun  6 13:57:28 2012
New Revision: 1346895

URL: http://svn.apache.org/viewvc?rev=1346895&view=rev
Log:
OAK-64 : Privilege Management

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConstants.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeRegistry.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeDefinition.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeProvider.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/
      - copied from r1344688, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImpl.java
      - copied, changed from r1346832, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/PrivilegeManagerImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImplTest.java
Removed:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/
Modified:
    jackrabbit/oak/trunk/oak-core/pom.xml
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java

Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1346895&r1=1346894&r2=1346895&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Wed Jun  6 13:57:28 2012
@@ -46,6 +46,8 @@
               org.apache.jackrabbit.oak.plugins.name,
               org.apache.jackrabbit.oak.spi.security.authentication,
               org.apache.jackrabbit.oak.spi.security.principal,
+              org.apache.jackrabbit.oak.spi.security.privilege,
+              org.apache.jackrabbit.oak.security.privilege,
               org.apache.jackrabbit.oak.spi.security.user
             </Export-Package>
             <Bundle-Activator>

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConstants.java?rev=1346895&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConstants.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConstants.java Wed Jun  6 13:57:28 2012
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.privilege;
+
+/**
+ * PrivilegeConstants... TODO
+ */
+interface PrivilegeConstants {
+    
+    String JCR_READ = "jcr:read";
+    String JCR_MODIFY_PROPERTIES = "jcr:modifyProperties";
+    String JCR_ADD_CHILD_NODES = "jcr:addChildNodes";
+    String JCR_REMOVE_NODE = "jcr:removeNode";
+    String JCR_REMOVE_CHILD_NODES = "jcr:removeChildNodes";
+    String JCR_WRITE = "jcr:write";
+    String JCR_READ_ACCESS_CONTROL = "jcr:readAccessControl";
+    String JCR_MODIFY_ACCESS_CONTROL = "jcr:modifyAccessControl";
+    String JCR_LOCK_MANAGEMENT = "jcr:lockManagement";
+    String JCR_VERSION_MANAGEMENT = "jcr:versionManagement";
+    String JCR_NODE_TYPE_MANAGEMENT = "jcr:nodeTypeManagement";
+    String JCR_RETENTION_MANAGEMENT = "jcr:retentionManagement";
+    String JCR_LIFECYCLE_MANAGEMENT = "jcr:lifecycleManagement";
+    String JCR_WORKSPACE_MANAGEMENT = "jcr:workspaceManagement";
+    String JCR_NODE_TYPE_DEFINITION_MANAGEMENT = "jcr:nodeTypeDefinitionManagement";
+    String JCR_NAMESPACE_MANAGEMENT = "jcr:namespaceManagement";
+    String JCR_ALL = "jcr:all";
+
+    String REP_PRIVILEGE_MANAGEMENT = "rep:privilegeManagement";
+    String REP_WRITE = "rep:write";
+    String REP_ADD_PROPERTIES = "rep:addProperties";
+    String REP_ALTER_PROPERTIES = "rep:alterProperties";
+    String REP_REMOVE_PROPERTIES = "rep:removeProperties";
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeRegistry.java?rev=1346895&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeRegistry.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeRegistry.java Wed Jun  6 13:57:28 2012
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.privilege;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.commons.ArrayUtils;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeProvider;
+
+/**
+ * PrivilegeProviderImpl... TODO
+ */
+public class PrivilegeRegistry implements PrivilegeProvider, PrivilegeConstants {
+
+    private static final String[] SIMPLE_PRIVILEGES = new String[] {
+            JCR_READ, REP_ADD_PROPERTIES, REP_ALTER_PROPERTIES, REP_REMOVE_PROPERTIES,
+            JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, JCR_REMOVE_NODE,
+            JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL, JCR_NODE_TYPE_MANAGEMENT,
+            JCR_VERSION_MANAGEMENT, JCR_LOCK_MANAGEMENT, JCR_LIFECYCLE_MANAGEMENT,
+            JCR_RETENTION_MANAGEMENT, JCR_WORKSPACE_MANAGEMENT, JCR_NODE_TYPE_DEFINITION_MANAGEMENT,
+            JCR_NAMESPACE_MANAGEMENT, REP_PRIVILEGE_MANAGEMENT};
+
+    private static final Map<String, String[]> AGGREGATE_PRIVILEGES = new HashMap<String,String[]>();
+    static {
+        AGGREGATE_PRIVILEGES.put(JCR_MODIFY_PROPERTIES,
+                new String[] {REP_ADD_PROPERTIES, REP_ALTER_PROPERTIES, REP_REMOVE_PROPERTIES});
+        AGGREGATE_PRIVILEGES.put(JCR_WRITE,
+                new String[] {JCR_MODIFY_PROPERTIES, JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, JCR_REMOVE_NODE});
+        AGGREGATE_PRIVILEGES.put(REP_WRITE,
+                new String[] {JCR_WRITE, JCR_NODE_TYPE_MANAGEMENT});
+    }
+
+    private final ContentSession contentSession;
+    private final Map<String, PrivilegeDefinition> definitions = new HashMap<String, PrivilegeDefinition>();
+
+    public PrivilegeRegistry(ContentSession contentSession) {
+        this.contentSession = contentSession;
+
+        // TODO: define if/how built-in privileges are reflected in the mk
+        // TODO: define where custom privileges are being stored.
+
+        for (String privilegeName : SIMPLE_PRIVILEGES) {
+            PrivilegeDefinition def = new PrivilegeDefinitionImpl(privilegeName, false, new String[0]);
+            definitions.put(privilegeName, def);
+        }
+
+        for (String privilegeName : AGGREGATE_PRIVILEGES.keySet()) {
+            PrivilegeDefinition def = new PrivilegeDefinitionImpl(privilegeName, false, AGGREGATE_PRIVILEGES.get(privilegeName));
+            definitions.put(privilegeName, def);
+        }
+
+        // TODO: jcr:all needs to be recalculated if custom privileges are registered
+        definitions.put(JCR_ALL, new PrivilegeDefinitionImpl(JCR_ALL, false, new String[] {
+            JCR_READ, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL,
+            JCR_VERSION_MANAGEMENT, JCR_LOCK_MANAGEMENT, JCR_LIFECYCLE_MANAGEMENT,
+            JCR_RETENTION_MANAGEMENT, JCR_WORKSPACE_MANAGEMENT, JCR_NODE_TYPE_DEFINITION_MANAGEMENT,
+            JCR_NAMESPACE_MANAGEMENT, REP_PRIVILEGE_MANAGEMENT, REP_WRITE}));
+    }
+
+    //--------------------------------------------------< PrivilegeProvider >---
+    @Nonnull
+    @Override
+    public PrivilegeDefinition[] getPrivilegeDefinitions() {
+        return definitions.values().toArray(new PrivilegeDefinition[definitions.size()]);
+    }
+
+    @Override
+    public PrivilegeDefinition getPrivilegeDefinition(String name) {
+        return definitions.get(name);
+    }
+
+    @Override
+    public PrivilegeDefinition registerDefinition(String privilegeName,
+                                                  boolean isAbstract,
+                                                  Set<String> declaredAggregateNames) throws RepositoryException {
+        // TODO: check permission, validate and register the custom definition
+        throw new UnsupportedOperationException("TODO: Register Privileges");
+    }
+
+
+    //--------------------------------------------------------------------------
+
+    private static class PrivilegeDefinitionImpl implements PrivilegeDefinition {
+
+        private final String name;
+        private final boolean isAbstract;
+        private final Set<String> declaredAggregateNames;
+
+        private PrivilegeDefinitionImpl(String name, boolean isAbstract,
+                                        String[] declaredAggregateNames) {
+            this.name = name;
+            this.isAbstract = isAbstract;
+            this.declaredAggregateNames = ArrayUtils.toSet(declaredAggregateNames);
+        }
+
+        //--------------------------------------------< PrivilegeDefinition >---
+        @Nonnull
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean isAbstract() {
+            return isAbstract;
+        }
+
+        @Nonnull
+        @Override
+        public String[] getDeclaredAggregateNames() {
+            return declaredAggregateNames.toArray(new String[declaredAggregateNames.size()]);
+        }
+
+        //---------------------------------------------------------< Object >---
+        @Override
+        public int hashCode() {
+            int result = name.hashCode();
+            result = 31 * result + (isAbstract ? 1 : 0);
+            result = 31 * result + declaredAggregateNames.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (o instanceof PrivilegeDefinitionImpl) {
+                PrivilegeDefinitionImpl other = (PrivilegeDefinitionImpl) o;
+                return name.equals(other.name) &&
+                        isAbstract == other.isAbstract &&
+                        declaredAggregateNames.equals(other.declaredAggregateNames);
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "PrivilegeDefinition: " + name;
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeDefinition.java?rev=1346895&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeDefinition.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeDefinition.java Wed Jun  6 13:57:28 2012
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.security.privilege;
+
+import javax.annotation.Nonnull;
+
+/**
+ * The {@code PrivilegeDefinition} interface defines the characteristics of
+ * a JCR {@link javax.jcr.security.Privilege}.
+ */
+public interface PrivilegeDefinition {
+
+    /**
+     * The internal name of this privilege.
+     *
+     * @return the internal name.
+     */
+    @Nonnull
+    String getName();
+
+    /**
+     * Returns {@code true} if the privilege described by this definition
+     * is abstract.
+     *
+     * @return {@code true} if the resulting privilege is abstract;
+     * {@code false} otherwise.
+     */
+    boolean isAbstract();
+
+    /**
+     * Returns the internal names of the declared aggregated privileges or
+     * an empty array if the privilege defined by this definition isn't
+     * an aggregate.
+     *
+     * @return The internal names of the aggregated privileges or an empty array.
+     */
+    @Nonnull
+    String[] getDeclaredAggregateNames();
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeProvider.java?rev=1346895&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeProvider.java Wed Jun  6 13:57:28 2012
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.security.privilege;
+
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+
+/**
+ * PrivilegeProvider... TODO
+ */
+public interface PrivilegeProvider {
+
+    /**
+     * Returns all privilege definitions accessible to a given
+     * {@link org.apache.jackrabbit.oak.api.ContentSession}.
+     *
+     * @return all privilege definitions.
+     */
+    @Nonnull
+    PrivilegeDefinition[] getPrivilegeDefinitions();
+
+    /**
+     * Returns the privilege definition with the specified internal name.
+     *
+     * @param name The internal name of the privilege definition to be
+     * retrieved.
+     * @return The privilege definition with the given name or {@code null} if
+     * no such definition exists.
+     */
+    @Nullable
+    PrivilegeDefinition getPrivilegeDefinition(String name);
+
+    PrivilegeDefinition registerDefinition(String privilegeName, boolean isAbstract, Set<String> declaredAggregateNames) throws RepositoryException;
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java?rev=1346895&r1=1346894&r2=1346895&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java Wed Jun  6 13:57:28 2012
@@ -21,7 +21,7 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.jcr.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.oak.jcr.query.QueryManagerImpl;
-import org.apache.jackrabbit.oak.jcr.security.privileges.PrivilegeManagerImpl;
+import org.apache.jackrabbit.oak.jcr.security.privilege.PrivilegeManagerImpl;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceRegistryImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

Copied: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImpl.java (from r1346832, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/PrivilegeManagerImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImpl.java?p2=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImpl.java&p1=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/PrivilegeManagerImpl.java&r1=1346832&r2=1346895&rev=1346895&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privileges/PrivilegeManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImpl.java Wed Jun  6 13:57:28 2012
@@ -14,30 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.oak.jcr.security.privileges;
+package org.apache.jackrabbit.oak.jcr.security.privilege;
 
-import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
-import org.apache.jackrabbit.oak.jcr.NodeImpl;
-import org.apache.jackrabbit.oak.jcr.SessionDelegate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.Workspace;
-import javax.jcr.security.AccessControlException;
-import javax.jcr.security.Privilege;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.jcr.SessionDelegate;
+import org.apache.jackrabbit.oak.security.privilege.PrivilegeRegistry;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * PrivilegeManagerImpl...
+ * PrivilegeManagerImpl... TODO
  */
 public class PrivilegeManagerImpl implements PrivilegeManager {
 
@@ -46,130 +42,98 @@ public class PrivilegeManagerImpl implem
      */
     private static final Logger log = LoggerFactory.getLogger(PrivilegeManagerImpl.class);
 
-    // TODO: move to an appropriate place
-    // TODO: proper namespace handling once this is present in oak-jcr
-    private static final String PRIVILEGE_ROOT = Workspace.NAME_SYSTEM_NODE + "/{internal}privileges";
-
-    private static final String NT_REP_PRIVILEGE = "rep:Privilege";
-    private static final String REP_IS_ABSTRACT = "rep:isAbstract";
-    private static final String REP_CONTAINS = "rep:contains";
-
+    private final PrivilegeProvider provider;
     private final SessionDelegate sessionDelegate;
 
     public PrivilegeManagerImpl(SessionDelegate sessionDelegate) {
+        this.provider = new PrivilegeRegistry(sessionDelegate.getContentSession());
         this.sessionDelegate = sessionDelegate;
-        // TODO: add additional validation ??
     }
 
     @Override
     public Privilege[] getRegisteredPrivileges() throws RepositoryException {
-        Map<String, Privilege> privileges = new HashMap<String, Privilege>();
-        NodeIterator it = getPrivilegeRoot().getNodes();
-        while (it.hasNext()) {
-            Node privilegeNode = it.nextNode();
-            Privilege p = getPrivilege(privilegeNode, privileges);
-            if (p != null) {
-                privileges.put(p.getName(),  p);
-            }
+        Set<Privilege> privileges = new HashSet<Privilege>();
+        for (PrivilegeDefinition def : provider.getPrivilegeDefinitions()) {
+            privileges.add(new PrivilegeImpl(def));
         }
-        return privileges.values().toArray(new Privilege[privileges.size()]);
+        return privileges.toArray(new Privilege[privileges.size()]);
     }
 
     @Override
     public Privilege getPrivilege(String privilegeName) throws RepositoryException {
-        NodeImpl privilegeRoot = getPrivilegeRoot();
-        if (privilegeRoot.hasNode(privilegeName)) {
-            return getPrivilege(privilegeRoot.getNode(privilegeName), new HashMap<String, Privilege>(1));
-        } else {
+        PrivilegeDefinition def = provider.getPrivilegeDefinition(getOakName(privilegeName));
+        if (def == null) {
             throw new AccessControlException("No such privilege " + privilegeName);
+        } else {
+            return new PrivilegeImpl(def);
         }
     }
 
     @Override
     public Privilege registerPrivilege(String privilegeName, boolean isAbstract,
-                                       String[] declaredAggregateNames)
-            throws RepositoryException {
-
-        // TODO
-        return null;
+                                       String[] declaredAggregateNames) throws RepositoryException {
+        PrivilegeDefinition def = provider.registerDefinition(getOakName(privilegeName), isAbstract, getOakNames(declaredAggregateNames));
+        return new PrivilegeImpl(def);
     }
 
     //--------------------------------------------------------------------------
-    private NodeImpl getPrivilegeRoot() throws RepositoryException {
-        // FIXME use NodeDelegate instead of NodeImpl
-        return (NodeImpl) sessionDelegate.getSession().getNode(PRIVILEGE_ROOT);
-    }
-
-    private Privilege getPrivilege(Node privilegeNode, Map<String, Privilege> collected) throws RepositoryException {
-        Privilege privilege = null;
-        if (privilegeNode.isNodeType(NT_REP_PRIVILEGE)) {
-            String name = privilegeNode.getName();
-            boolean isAbstract = privilegeNode.getProperty(REP_IS_ABSTRACT).getBoolean();
-
-            Set<String> declaredAggrNames;
-            if (privilegeNode.hasProperty(REP_CONTAINS)) {
-                Value[] vs = privilegeNode.getProperty(REP_CONTAINS).getValues();
-                declaredAggrNames = new HashSet<String>(vs.length);
-                for (Value v : vs) {
-                    String privName = v.getString();
-                    if (getPrivilegeRoot().hasNode(privName)) {
-                        declaredAggrNames.add(privName);
-                    }
-                }
-            } else {
-                declaredAggrNames = Collections.emptySet();
+    private String getOakName(String jcrName) {
+        return sessionDelegate.getNamePathMapper().getOakName(jcrName);
+    }
+
+    private Set<String> getOakNames(String[] jcrNames) {
+        Set<String> oakNames;
+        if (jcrNames == null || jcrNames.length == 0) {
+            oakNames = Collections.emptySet();
+        } else {
+            oakNames = new HashSet<String>(jcrNames.length);
+            for (String jcrName : jcrNames) {
+                oakNames.add(getOakName(jcrName));
             }
-            privilege = new PrivilegeImpl(name, isAbstract, declaredAggrNames);
         }
-
-        return privilege;
+        return oakNames;
     }
 
     //--------------------------------------------------------------------------
+    /**
+     * Privilege implementation based on a {@link PrivilegeDefinition}.
+     */
     private class PrivilegeImpl implements Privilege {
 
-        private final String name;
-        private final boolean isAbstract;
-        private final Set<String> declaredAggregateNames;
-
-        private Privilege[] declaredAggregates;
-
-        private PrivilegeImpl(String name, boolean isAbstract, Set<String> declaredAggregateNames) {
-            this.name = name;
-            this.isAbstract = isAbstract;
-            this.declaredAggregateNames = declaredAggregateNames;
+        private final PrivilegeDefinition definition;
+
+        private PrivilegeImpl(PrivilegeDefinition definition) {
+            this.definition = definition;
         }
 
         //------------------------------------------------------< Privilege >---
         @Override
         public String getName() {
-            return name;
+            return getOakName(definition.getName());
         }
 
         @Override
         public boolean isAbstract() {
-            return isAbstract;
+            return definition.isAbstract();
         }
 
         @Override
         public boolean isAggregate() {
-            return !declaredAggregateNames.isEmpty();
+            return definition.getDeclaredAggregateNames().length > 0;
         }
 
         @Override
         public Privilege[] getDeclaredAggregatePrivileges() {
-            if (declaredAggregates == null) {
-                Set<Privilege> dagrPrivs = new HashSet<Privilege>(declaredAggregateNames.size());
-                for (String pName : declaredAggregateNames) {
-                    try {
-                        dagrPrivs.add(getPrivilege(pName));
-                    } catch (RepositoryException e) {
-                        log.warn("Error while retrieving privilege "+ pName +" contained in " + getName(), e.getMessage());
-                    }
+            String[] declaredAggregateNames = definition.getDeclaredAggregateNames();
+            Set<Privilege> declaredAggregates = new HashSet<Privilege>(declaredAggregateNames.length);
+            for (String pName : declaredAggregateNames) {
+                try {
+                    declaredAggregates.add(getPrivilege(pName));
+                } catch (RepositoryException e) {
+                    log.warn("Error while retrieving privilege "+ pName +" contained in " + getName(), e.getMessage());
                 }
-                declaredAggregates = dagrPrivs.toArray(new Privilege[dagrPrivs.size()]);
             }
-            return declaredAggregates;
+            return declaredAggregates.toArray(new Privilege[declaredAggregates.size()]);
         }
 
         @Override
@@ -178,11 +142,34 @@ public class PrivilegeManagerImpl implem
             for (Privilege decl : getDeclaredAggregatePrivileges()) {
                 aggr.add(decl);
                 if (decl.isAggregate()) {
-                    // TODO: defensive check to prevent circular aggregation
+                    // TODO: defensive check to prevent circular aggregation that might occur with inconsistent repositories
                     aggr.addAll(Arrays.asList(decl.getAggregatePrivileges()));
                 }
             }
             return aggr.toArray(new Privilege[aggr.size()]);
         }
+
+        //---------------------------------------------------------< Object >---
+        @Override
+        public int hashCode() {
+            return definition.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (o instanceof PrivilegeImpl) {
+                return definition.equals(((PrivilegeImpl) o).definition);
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "Privilege " + definition.getName();
+        }
     }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImplTest.java?rev=1346895&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImplTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerImplTest.java Wed Jun  6 13:57:28 2012
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.jcr.security.privilege;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * PrivilegeManagerTest...
+ */
+public class PrivilegeManagerImplTest extends AbstractJCRTest {
+
+    private PrivilegeManager privilegeMgr;
+
+    @Before
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        privilegeMgr = ((JackrabbitWorkspace) superuser.getWorkspace()).getPrivilegeManager();
+    }
+
+    @Test
+    public void testRegisteredPrivileges() throws RepositoryException {
+        Privilege[] ps = privilegeMgr.getRegisteredPrivileges();
+
+        List<Privilege> l = new ArrayList<Privilege>(Arrays.asList(ps));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_ADD_CHILD_NODES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_REMOVE_CHILD_NODES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_MODIFY_PROPERTIES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_REMOVE_NODE)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_MODIFY_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_WRITE)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_ALL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LIFECYCLE_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LOCK_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_NODE_TYPE_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_RETENTION_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:write")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:addProperties")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:alterProperties")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:removeProperties")));
+        // including repo-level operation privileges
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:namespaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:nodeTypeDefinitionManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:workspaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:privilegeManagement")));
+
+        assertTrue(l.isEmpty());
+    }
+
+    @Test
+    public void testAllPrivilege() throws RepositoryException {
+        Privilege p = privilegeMgr.getPrivilege(Privilege.JCR_ALL);
+        assertEquals("jcr:all",p.getName());
+        assertTrue(p.isAggregate());
+        assertFalse(p.isAbstract());
+
+        List<Privilege> l = new ArrayList<Privilege>(Arrays.asList(p.getAggregatePrivileges()));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_ADD_CHILD_NODES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_REMOVE_CHILD_NODES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_MODIFY_PROPERTIES)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_REMOVE_NODE)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_MODIFY_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LIFECYCLE_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LOCK_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_NODE_TYPE_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_RETENTION_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_WRITE)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:write")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:addProperties")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:alterProperties")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:removeProperties")));
+        // including repo-level operation privileges
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:namespaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:nodeTypeDefinitionManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:workspaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:privilegeManagement")));
+        assertTrue(l.isEmpty());
+
+        l = new ArrayList<Privilege>(Arrays.asList(p.getDeclaredAggregatePrivileges()));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:write")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_READ_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_MODIFY_ACCESS_CONTROL)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LIFECYCLE_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_LOCK_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_RETENTION_MANAGEMENT)));
+        assertTrue(l.remove(privilegeMgr.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT)));
+        // including repo-level operation privileges
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:namespaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:nodeTypeDefinitionManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("jcr:workspaceManagement")));
+        assertTrue(l.remove(privilegeMgr.getPrivilege("rep:privilegeManagement")));
+
+        assertTrue(l.isEmpty());
+    }
+
+    @Test
+    public void testGetPrivilegeFromName() throws AccessControlException, RepositoryException {
+        Privilege p = privilegeMgr.getPrivilege(Privilege.JCR_READ);
+
+        assertTrue(p != null);
+        assertEquals("jcr:read", p.getName());
+        assertFalse(p.isAggregate());
+
+        p = privilegeMgr.getPrivilege(Privilege.JCR_WRITE);
+
+        assertTrue(p != null);
+        assertEquals("jcr:write", p.getName());
+        assertTrue(p.isAggregate());
+    }
+
+    @Test
+    public void testGetPrivilegesFromInvalidName() throws RepositoryException {
+        try {
+            privilegeMgr.getPrivilege("unknown");
+            fail("invalid privilege name");
+        } catch (AccessControlException e) {
+            // OK
+        }
+    }
+
+    @Test
+    public void testGetPrivilegesFromEmptyNames() {
+        try {
+            privilegeMgr.getPrivilege("");
+            fail("invalid privilege name array");
+        } catch (AccessControlException e) {
+            // OK
+        } catch (RepositoryException e) {
+            // OK
+        }
+    }
+
+    @Test
+    public void testGetPrivilegesFromNullNames() {
+        try {
+            privilegeMgr.getPrivilege(null);
+            fail("invalid privilege name (null)");
+        } catch (Exception e) {
+            // OK
+        }
+    }
+
+    // TODO test privilege registration
+}
\ No newline at end of file