You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2009/06/25 20:02:05 UTC

svn commit: r788450 - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/ jackrabbit-core/sr...

Author: angela
Date: Thu Jun 25 18:02:04 2009
New Revision: 788450

URL: http://svn.apache.org/viewvc?rev=788450&view=rev
Log:
 JCR-1588: JSR 283: Access Control

- align principalbased ac editing with latest changes made to JSR 283
   -> getApplicablePolicies(Principal) only returns policies that have not yet been set
   -> getPolicies(Principal) added -> used to modify policies that have been set before

- WorkspaceAccessManagerImpl.grants throws NoSuchWorkspaceException if an invalid
   wspName gets passed... TCK tests would fail if not executed with admin user that
   is covered by shortcut.

- Various improvements to AccessControlProvider handling
   > prevent closure of used provider
   > add AccessControlProvider#isLive that allows to rebuild the provider if it was closed before

- Simplify WriteTest and add test for changes made to principal-based ACLEditor

JCR-2087 Upgrade to Java 5 as the base platform
- use generics in security code (work in progress)

Modified:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java

Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java (original)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java Thu Jun 25 18:02:04 2009
@@ -30,7 +30,8 @@
 public interface JackrabbitAccessControlManager extends AccessControlManager {
 
     /**
-     * Returns the editable policies for the specified <code>principal</code>.
+     * Returns the applicable policies for the specified <code>principal</code>
+     * or an empty array if no additional policies can be applied.
      *
      * @param principal A principal known to the editing session.
      * @return array of policies for the specified <code>principal</code>. Note
@@ -46,4 +47,19 @@
      * @see JackrabbitAccessControlPolicy#getPath()
      */
     JackrabbitAccessControlPolicy[] getApplicablePolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
+
+    /**
+     * Returns the <code>AccessControlPolicy</code> objects that have been set
+     * for the given <code>principal</code> or an empty array if no policy has
+     * been set. This method reflects the binding state, including transient
+     * policy modifications.
+     *
+     * @param principal
+     * @return
+     * @throws AccessDeniedException
+     * @throws AccessControlException
+     * @throws UnsupportedRepositoryOperationException
+     * @throws RepositoryException
+     */
+    JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java Thu Jun 25 18:02:04 2009
@@ -299,8 +299,7 @@
     /**
      * @see JackrabbitSecurityManager#getPrincipalManager(Session)
      */
-    public synchronized PrincipalManager getPrincipalManager(Session session)
-            throws RepositoryException {
+    public PrincipalManager getPrincipalManager(Session session) throws RepositoryException {
         checkInitialized();
         if (session == securitySession) {
             return systemPrincipalManager;
@@ -411,17 +410,22 @@
     private AccessControlProvider getAccessControlProvider(String workspaceName)
             throws NoSuchWorkspaceException, RepositoryException {
         checkInitialized();
-        synchronized (acProviders) {
-            AccessControlProvider provider = acProviders.get(workspaceName);
-            if (provider == null) {
-                SystemSession systemSession = repository.getSystemSession(workspaceName);
-                WorkspaceConfig conf = repository.getConfig().getWorkspaceConfig(workspaceName);
-                WorkspaceSecurityConfig secConf = (conf == null) ?  null : conf.getSecurityConfig();
+        AccessControlProvider provider = acProviders.get(workspaceName);
+        if (provider == null || !provider.isLive()) {
+            SystemSession systemSession = repository.getSystemSession(workspaceName);
+            // mark this session as 'active' so the workspace does not get disposed
+            // by the workspace-janitor until the garbage collector is done
+            // TODO: review again... this workaround is now used in several places.
+            repository.onSessionCreated(systemSession);
+            
+            WorkspaceConfig conf = repository.getConfig().getWorkspaceConfig(workspaceName);
+            WorkspaceSecurityConfig secConf = (conf == null) ?  null : conf.getSecurityConfig();
+            synchronized (acProviders) {
                 provider = acProviderFactory.createProvider(systemSession, secConf);
                 acProviders.put(workspaceName, provider);
             }
-            return provider;
         }
+        return provider;
     }
 
     /**
@@ -496,13 +500,8 @@
          * {@inheritDoc}
          */
         public boolean grants(Set principals, String workspaceName) throws RepositoryException {
-            try {
-                AccessControlProvider prov = getAccessControlProvider(workspaceName);
-                return prov.canAccessRoot(principals);
-            } catch (NoSuchWorkspaceException e) {
-                // no such workspace -> return false.
-                return false;
-            }
+            AccessControlProvider prov = getAccessControlProvider(workspaceName);
+            return prov.canAccessRoot(principals);
         }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java Thu Jun 25 18:02:04 2009
@@ -132,6 +132,16 @@
         return new JackrabbitAccessControlPolicy[0];
     }
 
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getApplicablePolicies(java.security.Principal)
+     */
+    public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException {
+        checkInitialized();
+
+        log.debug("Implementation does not provide applicable policies -> returning empty array.");
+        return new JackrabbitAccessControlPolicy[0];
+    }
+    
     //--------------------------------------------------------------------------
     /**
      * Check if this manager has been properly initialized.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java Thu Jun 25 18:02:04 2009
@@ -385,6 +385,16 @@
         return editor.editAccessControlPolicies(principal);
     }
 
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getApplicablePolicies(Principal)
+     */
+    public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException {
+        checkInitialized();
+        if (editor == null) {
+            throw new UnsupportedRepositoryOperationException("Editing of access control policies is not supported.");
+        }
+        return editor.getPolicies(principal);
+    }
     //---------------------------------------< AbstractAccessControlManager >---
     /**
      * @see AbstractAccessControlManager#checkInitialized()

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java Thu Jun 25 18:02:04 2009
@@ -183,4 +183,11 @@
         checkInitialized();
         initialized = false;
     }
+
+    /**
+     * @see AccessControlProvider#isLive()
+     */
+    public boolean isLive() {
+        return initialized && session.isLive();
+    }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java Thu Jun 25 18:02:04 2009
@@ -57,6 +57,26 @@
     AccessControlPolicy[] getPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
 
     /**
+     * Retrieves the policies that have been applied before for the given
+     * <code>principal</code>. In contrast to {@link #editAccessControlPolicies}
+     * this method returns an empty array if no policy has been applied before
+     * by calling {@link #setPolicy}). Still the returned policies are detached from
+     * the <code>AccessControlProvider</code> and are only an external representation.
+     * Modification will therefore not take effect, until they are written back to
+     * the editor and persisted.
+     *
+     * @param principal  Principal for which the editable policies should be
+     * returned.
+     * @return the policies applied so far or an empty array if no
+     * policy has been applied before.
+     * @throws AccessControlException if the specified principal does not exist,
+     * if this implementation cannot provide policies for individual principals or
+     * if same other access control related exception occurs.
+     * @throws RepositoryException if an error occurs
+     */
+    JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessControlException, RepositoryException;
+
+    /**
      * Retrieves the editable policies for the Node identified by the given
      * <code>nodePath</code> that are applicable but have not yet have been set.<br>
      * The AccessControlPolicy objects returned are detached from the underlying

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java Thu Jun 25 18:02:04 2009
@@ -72,6 +72,15 @@
     void close();
 
     /**
+     * Returns <code>true</code>, if this provider is still alive and able to
+     * evaluate permissions; <code>false</code> otherwise.
+     *
+     * @return <code>true</code>, if this provider is still alive and able to
+     * evaluate permissions; <code>false</code> otherwise.
+     */
+    boolean isLive();
+
+    /**
      * Returns the effective policies for the node at the given absPath.
      *
      * @param absPath an absolute path.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java Thu Jun 25 18:02:04 2009
@@ -93,7 +93,6 @@
     //------------------------------------------------< AccessControlEditor >---
     /**
      * @see AccessControlEditor#getPolicies(String)
-     * @param nodePath
      */
     public AccessControlPolicy[] getPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException {
         checkProtectsNode(nodePath);
@@ -107,8 +106,20 @@
     }
 
     /**
+     * Always returns an empty array as no applicable policies are exposed.
+     * 
+     * @see AccessControlEditor#getPolicies(Principal)
+     */
+    public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessControlException, RepositoryException {
+        if (!session.getPrincipalManager().hasPrincipal(principal.getName())) {
+            throw new AccessControlException("Unknown principal.");
+        }
+        // TODO: impl. missing
+        return new JackrabbitAccessControlPolicy[0];
+    }
+
+    /**
      * @see AccessControlEditor#editAccessControlPolicies(String)
-     * @param nodePath
      */
     public AccessControlPolicy[] editAccessControlPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException {
         checkProtectsNode(nodePath);

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java Thu Jun 25 18:02:04 2009
@@ -166,9 +166,8 @@
         if (acls.isEmpty()) {
             // no access control information can be retrieved for the specified
             // node, since neither the node nor any of its parents is access
-            // controlled -> build a default policy.
+            // controlled.
             log.warn("No access controlled node present in item hierarchy starting from " + targetNode.getPath());
-            acls.add(new UnmodifiableAccessControlList(Collections.EMPTY_LIST));
         }
         return (AccessControlList[]) acls.toArray(new AccessControlList[acls.size()]);
     }
@@ -274,31 +273,34 @@
             log.debug("Install initial ACL:...");
             String rootPath = session.getRootNode().getPath();
             AccessControlPolicy[] acls = editor.editAccessControlPolicies(rootPath);
-            ACLTemplate acl = (ACLTemplate) acls[0];
+            if (acls.length > 0) {
+                ACLTemplate acl = (ACLTemplate) acls[0];
+                
+                PrincipalManager pMgr = session.getPrincipalManager();
+                AccessControlManager acMgr = session.getAccessControlManager();
+
+                log.debug("... Privilege.ALL for administrators.");
+                Principal administrators;
+                String pName = SecurityConstants.ADMINISTRATORS_NAME;
+                if (pMgr.hasPrincipal(pName)) {
+                    administrators = pMgr.getPrincipal(pName);
+                } else {
+                    log.warn("Administrators principal group is missing.");
+                    administrators = new PrincipalImpl(pName);
+                }
+                Privilege[] privs = new Privilege[]{acMgr.privilegeFromName(Privilege.JCR_ALL)};
+                acl.addAccessControlEntry(administrators, privs);
 
-            PrincipalManager pMgr = session.getPrincipalManager();
-            AccessControlManager acMgr = session.getAccessControlManager();
+                Principal everyone = pMgr.getEveryone();
+                log.debug("... Privilege.READ for everyone.");
+                privs = new Privilege[]{acMgr.privilegeFromName(Privilege.JCR_READ)};
+                acl.addAccessControlEntry(everyone, privs);
 
-            log.debug("... Privilege.ALL for administrators.");
-            Principal administrators;
-            String pName = SecurityConstants.ADMINISTRATORS_NAME;
-            if (pMgr.hasPrincipal(pName)) {
-                administrators = pMgr.getPrincipal(pName);
+                editor.setPolicy(rootPath, acl);
+                session.save();
             } else {
-                log.warn("Administrators principal group is missing.");
-                administrators = new PrincipalImpl(pName);
+                log.warn("No applicable ACL available for the root node -> skip initialization of the root node's ACL.");
             }
-            Privilege[] privs = new Privilege[]{acMgr.privilegeFromName(Privilege.JCR_ALL)};
-            acl.addAccessControlEntry(administrators, privs);
-
-            Principal everyone = pMgr.getEveryone();
-            log.debug("... Privilege.READ for everyone.");
-            privs = new Privilege[]{acMgr.privilegeFromName(Privilege.JCR_READ)};
-            acl.addAccessControlEntry(everyone, privs);
-
-            editor.setPolicy(rootPath, acl);
-            session.save();
-
         } catch (RepositoryException e) {
             log.error("Failed to set-up minimal access control for root node of workspace " + session.getWorkspace().getName());
             session.getRootNode().refresh(false);

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java Thu Jun 25 18:02:04 2009
@@ -48,21 +48,35 @@
      * @see AccessControlEditor#getPolicies(String)
      */
     public AccessControlPolicy[] getPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException {
-        List templates = new ArrayList(editors.length);
+        List<AccessControlPolicy> templates = new ArrayList<AccessControlPolicy>();
         for (int i = 0; i < editors.length; i++) {
             AccessControlPolicy[] ts = editors[i].getPolicies(nodePath);
-            if (ts.length > 0) {
+            if (ts != null && ts.length > 0) {
                 templates.addAll(Arrays.asList(ts));
             }
         }
-        return (AccessControlPolicy[]) templates.toArray(new AccessControlPolicy[templates.size()]);
+        return templates.toArray(new AccessControlPolicy[templates.size()]);
+    }
+
+    /**
+     * @see AccessControlEditor#getPolicies(Principal)
+     */
+    public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessControlException, RepositoryException {
+        List<JackrabbitAccessControlPolicy> templates = new ArrayList<JackrabbitAccessControlPolicy>();
+        for (int i = 0; i < editors.length; i++) {
+            JackrabbitAccessControlPolicy[] ts = editors[i].getPolicies(principal);
+            if (ts != null && ts.length > 0) {
+                templates.addAll(Arrays.asList(ts));
+            }
+        }
+        return templates.toArray(new JackrabbitAccessControlPolicy[templates.size()]);
     }
 
     /**
      * @see AccessControlEditor#editAccessControlPolicies(String)
      */
     public AccessControlPolicy[] editAccessControlPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException {
-        List templates = new ArrayList(editors.length);
+        List<AccessControlPolicy> templates = new ArrayList<AccessControlPolicy>();
         for (int i = 0; i < editors.length; i++) {
             try {
                 templates.addAll(Arrays.asList(editors[i].editAccessControlPolicies(nodePath)));
@@ -71,14 +85,14 @@
                 // ignore.
             }
         }
-        return (AccessControlPolicy[]) templates.toArray(new AccessControlPolicy[templates.size()]);
+        return templates.toArray(new AccessControlPolicy[templates.size()]);
     }
 
     /**
      * @see AccessControlEditor#editAccessControlPolicies(Principal)
      */
     public JackrabbitAccessControlPolicy[] editAccessControlPolicies(Principal principal) throws RepositoryException {
-        List templates = new ArrayList();
+        List<JackrabbitAccessControlPolicy> templates = new ArrayList<JackrabbitAccessControlPolicy>();
         for (int i = 0; i < editors.length; i++) {
             try {
                 templates.addAll(Arrays.asList(editors[i].editAccessControlPolicies(principal)));
@@ -87,7 +101,7 @@
                 // ignore.
             }
         }
-        return (JackrabbitAccessControlPolicy[]) templates.toArray(new JackrabbitAccessControlPolicy[templates.size()]);
+        return templates.toArray(new JackrabbitAccessControlPolicy[templates.size()]);
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java Thu Jun 25 18:02:04 2009
@@ -105,6 +105,21 @@
     }
 
     /**
+     * @see AccessControlEditor#getPolicies(Principal)
+     */
+    public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessControlException, RepositoryException {
+        if (!session.getPrincipalManager().hasPrincipal(principal.getName())) {
+            throw new AccessControlException("Cannot edit access control: " + principal.getName() +" isn't a known principal.");
+        }
+        JackrabbitAccessControlPolicy acl = getACL(principal);
+        if (acl == null) {
+            return new JackrabbitAccessControlPolicy[0];
+        } else {
+            return new JackrabbitAccessControlPolicy[] {acl};
+        }
+    }
+
+    /**
      * @see AccessControlEditor#editAccessControlPolicies(String)
      */
     public AccessControlPolicy[] editAccessControlPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException {
@@ -119,6 +134,9 @@
                     throw new AccessControlException("Access control modification not allowed at " + nodePath);
                 }
                 acNode = createAcNode(nodePath);
+            }
+
+            if (!isAccessControlled(acNode)) {
                 return new AccessControlPolicy[] {createTemplate(acNode)};
             } // else: acl has already been set before -> use getPolicies instead
         }
@@ -142,7 +160,15 @@
         } else {
             acNode = (NodeImpl) session.getNode(nPath);
         }
-        return new JackrabbitAccessControlPolicy[] {createTemplate(acNode)};
+        if (!isAccessControlled(acNode)) {
+            return new JackrabbitAccessControlPolicy[] {createTemplate(acNode)};
+        } else {
+            // policy child node has already been created -> set policy has
+            // been called before for this principal and getPolicy is used
+            // to retrieve the ACL template.
+            // no additional applicable policies present.
+            return new JackrabbitAccessControlPolicy[0];
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java Thu Jun 25 18:02:04 2009
@@ -23,9 +23,7 @@
 import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
-import org.apache.jackrabbit.core.security.authorization.UnmodifiableAccessControlList;
 import org.apache.jackrabbit.core.security.SecurityConstants;
-import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.ItemImpl;
@@ -37,6 +35,8 @@
 import javax.jcr.security.AccessControlEntry;
 import javax.jcr.security.Privilege;
 import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlException;
+
 import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -67,6 +67,7 @@
     private static Logger log = LoggerFactory.getLogger(ACLProvider.class);
 
     // TODO: add means to show effective-policy to a user.
+    private static final AccessControlPolicy effectivePolicy = EffectivePrincipalBasedPolicy.getInstance();
 
     private ACLEditor editor;
     private NodeImpl acRoot;
@@ -122,38 +123,23 @@
 
                 PrincipalManager pMgr = session.getPrincipalManager();
                 AccessControlManager acMgr = session.getAccessControlManager();
+
+                // initial default permissions for the administrators group                
                 Principal administrators;
                 String pName = SecurityConstants.ADMINISTRATORS_NAME;
                 if (pMgr.hasPrincipal(pName)) {
                     administrators = pMgr.getPrincipal(pName);
+                    installDefaultPermissions(administrators,
+                        new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_ALL)},
+                        restrictions, editor);
                 } else {
-                    log.warn("Administrators principal group is missing.");
-                    administrators = new PrincipalImpl(pName);
-                }
-                AccessControlPolicy[] acls = editor.editAccessControlPolicies(administrators);
-                ACLTemplate acl = (ACLTemplate) acls[0];
-                if (acl.isEmpty()) {
-                    log.debug("... Privilege.ALL for administrators principal.");
-                    acl.addEntry(administrators,
-                            new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_ALL)},
-                            true, restrictions);
-                    editor.setPolicy(acl.getPath(), acl);
-                } else {
-                    log.debug("... policy for administrators principal already present.");
+                    log.warn("Administrators principal group is missing -> Not adding default permissions.");
                 }
 
-                Principal everyone = pMgr.getEveryone();
-                acls = editor.editAccessControlPolicies(everyone);
-                acl = (ACLTemplate) acls[0];
-                if (acl.isEmpty()) {
-                    log.debug("... Privilege.READ for everyone principal.");
-                    acl.addEntry(everyone,
-                            new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_READ)},
-                            true, restrictions);
-                    editor.setPolicy(acl.getPath(), acl);
-                } else {
-                    log.debug("... policy for everyone principal already present.");
-                }
+                // initialize default permissions for the everyone group
+                installDefaultPermissions(pMgr.getEveryone(),
+                        new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_READ)},
+                        restrictions, editor);
 
                 session.save();
             } catch (RepositoryException e) {
@@ -163,26 +149,36 @@
         }
     }
 
+    private static void installDefaultPermissions(Principal principal, Privilege[] privs, Map restrictions, AccessControlEditor editor) throws RepositoryException, AccessControlException {
+        AccessControlPolicy[] acls = editor.editAccessControlPolicies(principal);
+        if (acls.length > 0) {
+            ACLTemplate acl = (ACLTemplate) acls[0];
+            if (acl.isEmpty()) {
+                acl.addEntry(principal, privs, true, restrictions);
+                editor.setPolicy(acl.getPath(), acl);
+            } else {
+                log.debug("... policy for principal '"+principal.getName()+"' already present.");
+            }
+        } else {
+            log.debug("... policy for principal  '"+principal.getName()+"'  already present.");
+        }
+    }
+
     /**
      * @see org.apache.jackrabbit.core.security.authorization.AccessControlProvider#getEffectivePolicies(Path)
      */
     public AccessControlPolicy[] getEffectivePolicies(Path absPath)
             throws ItemNotFoundException, RepositoryException {
         /*
-           TODO review
            since the per-node effect of the policies is defined by the
-           rep:nodePath restriction, returning the principal-based
-           policy at 'absPath' probably doesn't reveal what the caller expects.
-           Maybe it would be better not to return an empty array as
-           {@link AccessControlManager#getEffectivePolicies(String)
-           is defined to express a best-effor estimate only.
+           rep:nodePath restriction present with the individual access control
+           entries, returning the principal-based policy at 'absPath' (which for
+           most nodes in the repository isn't available anyway) doesn't
+           provide the desired information.
+           As tmp. solution some default policy is returned indicating.
+           TODO: add proper evalution and return a set of ACLs that take effect on the node at abspath
         */
-        AccessControlPolicy[] tmpls = editor.getPolicies(session.getJCRPath(absPath));
-        AccessControlPolicy[] effectives = new AccessControlPolicy[tmpls.length];
-        for (int i = 0; i < tmpls.length; i++) {
-            effectives[i] = new UnmodifiableAccessControlList((ACLTemplate) tmpls[i]);
-        }
-        return effectives;
+        return new AccessControlPolicy[] {effectivePolicy};
     }
 
     /**
@@ -447,4 +443,18 @@
             return new AbstractCompiledPermissions.Result(allows, denies, allowPrivileges, denyPrivileges);
         }
     }
+
+    /**
+     * Dummy effective policy 
+     */
+    private static final class EffectivePrincipalBasedPolicy implements AccessControlPolicy {
+
+        private static EffectivePrincipalBasedPolicy INSTANCE = new EffectivePrincipalBasedPolicy();
+        private EffectivePrincipalBasedPolicy() {
+        }
+
+        private static EffectivePrincipalBasedPolicy getInstance() {
+            return INSTANCE;
+        }
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java Thu Jun 25 18:02:04 2009
@@ -45,24 +45,7 @@
     }
 
     protected JackrabbitAccessControlList getPolicy(AccessControlManager acM, String path, Principal principal) throws RepositoryException, AccessDeniedException, NotExecutableException {
-        // first try if there is a new applicable policy
-        AccessControlPolicyIterator it = acM.getApplicablePolicies(path);
-        while (it.hasNext()) {
-            AccessControlPolicy acp = it.nextAccessControlPolicy();
-            if (acp instanceof ACLTemplate) {
-                return (ACLTemplate) acp;
-            }
-        }
-        // try if there is an acl that has been set before:
-        AccessControlPolicy[] pcls = acM.getPolicies(path);
-        for (int i = 0; i < pcls.length; i++) {
-            AccessControlPolicy policy = pcls[i];
-            if (policy instanceof ACLTemplate) {
-                return (ACLTemplate) policy;
-            }
-        }
-        // no applicable or existing ACLTemplate to edit -> not executable.
-        throw new NotExecutableException("ACLTemplate expected.");
+        return EvaluationUtil.getPolicy(acM, path, principal);
     }
 
     protected Map getRestrictions(Session s, String path) {

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java Thu Jun 25 18:02:04 2009
@@ -59,6 +59,7 @@
     static JackrabbitAccessControlList getPolicy(AccessControlManager acM, String path, Principal principal) throws RepositoryException,
             AccessDeniedException, NotExecutableException {
         if (acM instanceof JackrabbitAccessControlManager) {
+            // first try applicable policies
             AccessControlPolicy[] policies = ((JackrabbitAccessControlManager) acM).getApplicablePolicies(principal);
             for (int i = 0; i < policies.length; i++) {
                 if (policies[i] instanceof ACLTemplate) {
@@ -66,6 +67,15 @@
                     return acl;
                 }
             }
+
+            // second existing policies
+            policies = ((JackrabbitAccessControlManager) acM).getPolicies(principal);
+            for (int i = 0; i < policies.length; i++) {
+                if (policies[i] instanceof ACLTemplate) {
+                    ACLTemplate acl = (ACLTemplate) policies[i];
+                    return acl;
+                }
+            }
         }
         throw new NotExecutableException();
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java?rev=788450&r1=788449&r2=788450&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java Thu Jun 25 18:02:04 2009
@@ -18,6 +18,9 @@
 
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.security.authorization.AbstractWriteTest;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
@@ -30,7 +33,6 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
 import java.util.Map;
@@ -47,16 +49,7 @@
     }
 
     protected JackrabbitAccessControlList getPolicy(AccessControlManager acM, String path, Principal principal) throws RepositoryException, AccessDeniedException, NotExecutableException {
-        if (acM instanceof JackrabbitAccessControlManager) {
-            AccessControlPolicy[] policies = ((JackrabbitAccessControlManager) acM).getApplicablePolicies(principal);
-            for (int i = 0; i < policies.length; i++) {
-                if (policies[i] instanceof ACLTemplate) {
-                    ACLTemplate acl = (ACLTemplate) policies[i];
-                    return acl;
-                }
-            }
-        }
-        throw new NotExecutableException();
+        return EvaluationUtil.getPolicy(acM, path, principal);
     }
 
     protected Map getRestrictions(Session s, String path) throws RepositoryException, NotExecutableException {
@@ -78,5 +71,36 @@
 
         assertFalse(folder.hasProperty("jcr:created"));
     }
+
+    public void testEditor() throws NotExecutableException, RepositoryException {
+        UserManager uMgr = getUserManager(superuser);
+        User u = uMgr.createUser("t", "t");
+        Principal p = u.getPrincipal();
+        try {
+            JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) getAccessControlManager(superuser);
+            JackrabbitAccessControlPolicy[] acls = acMgr.getApplicablePolicies(p);
+
+            assertEquals(1, acls.length);
+            assertTrue(acls[0] instanceof ACLTemplate);
+
+            // access again
+            acls = acMgr.getApplicablePolicies(p);
+
+            assertEquals(1, acls.length);            
+            assertEquals(1, acMgr.getApplicablePolicies(acls[0].getPath()).getSize());
+
+            assertEquals(0, acMgr.getPolicies(p).length);
+            assertEquals(0, acMgr.getPolicies(acls[0].getPath()).length);
+
+            acMgr.setPolicy(acls[0].getPath(), acls[0]);
+
+            assertEquals(0, acMgr.getApplicablePolicies(p).length);
+            assertEquals(1, acMgr.getPolicies(p).length);
+            assertEquals(1, acMgr.getPolicies(acls[0].getPath()).length);
+        } finally {
+            u.remove();
+        }
+
+    }
     // TODO: add specific tests with other restrictions
 }