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 2008/03/19 14:57:11 UTC

svn commit: r638834 [3/14] - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/ jackr...

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java Wed Mar 19 06:56:13 2008
@@ -23,7 +23,7 @@
  * The contained configuration information are: the home directory and name of
  * the workspace, the file system, the persistence manager, the search index and
  * the item state manager locking configuration. The search index and the item
- * state manager locking are optional parts.
+ * state manager locking and the security config are optional parts.
  */
 public class WorkspaceConfig {
 
@@ -63,6 +63,11 @@
     private ISMLockingConfig ismLockingConfig;
 
     /**
+     * Workspace security configuration. Can be <code>null</code>.
+     */
+    private final WorkspaceSecurityConfig workspaceSecurityConfig;
+
+    /**
      * Creates a workspace configuration object.
      *
      * @param home home directory
@@ -72,10 +77,12 @@
      * @param sc search index configuration
      * @param ismLockingConfig the item state manager locking configuration. If
      * <code>null</code> is passed, a default configuration is taken.
+     * @param workspaceSecurityConfig the workspace specific security configuration.
      */
     public WorkspaceConfig(String home, String name, boolean clustered,
                            FileSystemConfig fsc, PersistenceManagerConfig pmc,
-                           SearchConfig sc, ISMLockingConfig ismLockingConfig) {
+                           SearchConfig sc, ISMLockingConfig ismLockingConfig,
+                           WorkspaceSecurityConfig workspaceSecurityConfig) {
         this.home = home;
         this.name = name;
         this.clustered = clustered;
@@ -87,6 +94,7 @@
         } else {
             this.ismLockingConfig = ISMLockingConfig.createDefaultConfig();
         }
+        this.workspaceSecurityConfig = workspaceSecurityConfig;
     }
 
     /**
@@ -150,5 +158,12 @@
      */
     public SearchConfig getSearchConfig() {
         return sc;
+    }
+    /**
+     * @return workspace-specific security settings.
+     * @see WorkspaceSecurityConfig
+     */
+    public WorkspaceSecurityConfig getSecurityConfig() {
+        return workspaceSecurityConfig;
     }
 }

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,41 @@
+/*
+ * 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.core.config;
+
+/**
+ * Respresentation of workspace specific security settings.
+ */
+public class WorkspaceSecurityConfig {
+
+    /** configuration for AccessControlProvider */
+    private final BeanConfig accessControlProviderConfig;
+
+    /**
+     * @param accessControlProviderConfig
+     */
+    public WorkspaceSecurityConfig(BeanConfig accessControlProviderConfig) {
+        this.accessControlProviderConfig = accessControlProviderConfig;
+    }
+
+    /**
+     * @return Configuration for the AccessControlProvider or
+     * <code>null</code>, if this optional config entry is missing
+     */
+    public BeanConfig getAccessControlProviderConfig() {
+        return accessControlProviderConfig;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceSecurityConfig.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AMContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AMContext.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AMContext.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AMContext.java Wed Mar 19 06:56:13 2008
@@ -17,17 +17,21 @@
 package org.apache.jackrabbit.core.security;
 
 import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
 import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 
 import javax.security.auth.Subject;
+import javax.jcr.Session;
 import java.io.File;
 
 /**
- * An <code>AMContext</code> is used to provide context information for an
- * <code>AccessManager</code>.
+ * An <code>AMContext</code> is used to provide <code>Session</code> specific
+ * context information for an <code>AccessManager</code>.
  *
  * @see AccessManager#init(AMContext)
+ * @see AccessManager#init(AMContext, AccessControlProvider, WorkspaceAccessManager)
  */
 public class AMContext {
 
@@ -46,15 +50,17 @@
      */
     private final Subject subject;
 
+    private final Session session;
+
     /**
      * hierarchy manager for resolving ItemId-to-Path mapping
      */
     private final HierarchyManager hierMgr;
 
     /**
-     * namespace resolver for resolving namespaces in qualified paths
+     * name and path resolver for resolving namespaces in qualified paths
      */
-    private final NamespaceResolver nsResolver;
+    private final NamePathResolver resolver;
 
     /**
      * name of the workspace
@@ -68,20 +74,22 @@
      * @param fs              the virtual jackrabbit filesystem
      * @param subject         subject whose access rights should be reflected
      * @param hierMgr         hierarchy manager
-     * @param nsResolver      namespace resolver
+     * @param resolver        name and path resolver
      * @param workspaceName   workspace name
      */
     public AMContext(File physicalHomeDir,
                      FileSystem fs,
+                     Session session,
                      Subject subject,
                      HierarchyManager hierMgr,
-                     NamespaceResolver nsResolver,
+                     NamePathResolver resolver,
                      String workspaceName) {
         this.physicalHomeDir = physicalHomeDir;
         this.fs = fs;
+        this.session = session;
         this.subject = subject;
         this.hierMgr = hierMgr;
-        this.nsResolver = nsResolver;
+        this.resolver = resolver;
         this.workspaceName = workspaceName;
     }
 
@@ -105,6 +113,15 @@
     }
 
     /**
+     * Returns the session
+     *
+     * @return the session
+     */
+    public Session getSession() {
+        return session;
+    }
+
+    /**
      * Returns the subject
      *
      * @return the subject
@@ -127,8 +144,8 @@
      *
      * @return the namespace resolver
      */
-    public NamespaceResolver getNamespaceResolver() {
-        return nsResolver;
+    public NamePathResolver getNamePathResolver() {
+        return resolver;
     }
 
     /**

Added: 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=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,183 @@
+/*
+ * 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.core.security;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicyIterator;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
+import org.apache.jackrabbit.spi.Path;
+
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import java.security.Principal;
+
+/**
+ * <code>AbstractAccessControlManager</code>...
+ */
+public abstract class AbstractAccessControlManager implements AccessControlManager {
+
+    private static Logger log = LoggerFactory.getLogger(AbstractAccessControlManager.class);
+
+    /**
+     * Always returns all registered <code>Privilege</code>s.
+     *
+     * @param absPath
+     * @return Always returns all registered <code>Privilege</code>s.
+     * @see AccessControlManager#getSupportedPrivileges(String)
+     */
+    public Privilege[] getSupportedPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        getValidNodePath(absPath);
+
+        // return all known privileges everywhere.
+        return PrivilegeRegistry.getRegisteredPrivileges();
+    }
+
+    /**
+     * Returns <code>null</code>.
+     *
+     * @param absPath
+     * @return always returns <code>null</code>.
+     * @see AccessControlManager#getApplicablePolicies(String)
+     */
+    public AccessControlPolicy getPolicy(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.READ_AC);
+
+        log.debug("Implementation does not provide applicable policies -> getPolicy() always returns null.");
+        return null;
+    }
+
+    /**
+     * Returns an empty iterator.
+     *
+     * @param absPath
+     * @return always returns an empty iterator.
+     * @see AccessControlManager#getApplicablePolicies(String)
+     */
+    public AccessControlPolicyIterator getApplicablePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.READ_AC);
+
+        log.debug("Implementation does not provide applicable policies -> returning empty iterator.");
+        return AccessControlPolicyIteratorAdapter.EMPTY;
+    }
+    
+    /**
+     * Always throws <code>AccessControlException</code>
+     *
+     * @see AccessControlManager#setPolicy(String, AccessControlPolicy)
+     */
+    public void setPolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.MODIFY_AC);
+
+        throw new AccessControlException("AccessControlPolicy " + policy.getName() + " cannot be applied.");
+    }
+
+    /**
+     * Always throws <code>AccessControlException</code>
+     *
+     * @see AccessControlManager#removePolicy(String)
+     */
+    public AccessControlPolicy removePolicy(String absPath) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.MODIFY_AC);
+
+        throw new AccessControlException("No AccessControlPolicy has been set through this API -> Cannot be removed.");
+    }
+
+    /**
+     * Returns an empty array.
+     *
+     * @return always returns an empty array.
+     * @see AccessControlManager#getAccessControlEntries(String)
+     */
+    public AccessControlEntry[] getAccessControlEntries(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.READ_AC);
+
+        return new AccessControlEntry[0];
+    }
+
+    /**
+     * Always throws <code>UnsupportedRepositoryOperationException</code>
+     *
+     * @see AccessControlManager#addAccessControlEntry(String, Principal, Privilege[])
+     */
+    public AccessControlEntry addAccessControlEntry(String absPath, Principal principal, Privilege[] privileges) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.MODIFY_AC);
+
+        throw new UnsupportedRepositoryOperationException("Adding access control entry is not supported by this AccessControlManager (" + getClass().getName()+ ").");
+    }
+
+    /**
+     * Always throws <code>AccessControlException</code>
+     * 
+     * @see AccessControlManager#removeAccessControlEntry(String, AccessControlEntry)
+     */
+    public void removeAccessControlEntry(String absPath, AccessControlEntry ace) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        checkPrivileges(getValidNodePath(absPath), PrivilegeRegistry.MODIFY_AC);
+
+        throw new AccessControlException("Invalid access control entry, that has not been applied through this API.");
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Check if this manager has been properly initialized.
+     *
+     * @throws IllegalStateException If this manager has not been properly initialized.
+     */
+    protected abstract void checkInitialized() throws IllegalStateException;
+
+    /**
+     * Check if the specified privileges are granted at <code>absPath</code>.
+     *
+     * @param absPath
+     * @param privileges
+     * @throws AccessDeniedException if the session does not have the
+     * specified privileges.
+     * @throws PathNotFoundException if no node exists at <code>absPath</code>
+     * of if the session does not have the privilege to READ it.
+     * @throws RepositoryException
+     */
+    protected abstract void checkPrivileges(Path absPath, int privileges) throws AccessDeniedException, PathNotFoundException, RepositoryException;
+
+    /**
+     * Build a qualified path from the specified <code>absPath</code> and test
+     * if it is really absolute and points to an existing node.
+     *
+     * @param absPath
+     * @throws PathNotFoundException if no node at <code>absPath</code> exists
+     * or the session does not have privilege to retrieve the node.
+     * @throws RepositoryException If the given <code>absPath</code> is not
+     * absolute or if some other error occurs.
+     */
+    protected abstract Path getValidNodePath(String absPath) throws PathNotFoundException, RepositoryException;
+
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java Wed Mar 19 06:56:13 2008
@@ -17,30 +17,36 @@
 package org.apache.jackrabbit.core.security;
 
 import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.ItemNotFoundException;
-import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.RepositoryException;
 
 /**
- * The <code>AccessManager</code> can be queried to determines whether permission
- * is granted to perform a specific action on a specific item.
+ * The <code>AccessManager</code> can be queried to determines whether privileges
+ * are granted on a specific item.
  */
 public interface AccessManager {
 
     /**
      * READ permission constant
+     * @deprecated
      */
     int READ = 1;
 
     /**
      * WRITE permission constant
+     * @deprecated
      */
     int WRITE = 2;
 
     /**
      * REMOVE permission constant
+     * @deprecated 
      */
     int REMOVE = 4;
 
@@ -57,6 +63,21 @@
     void init(AMContext context) throws AccessDeniedException, Exception;
 
     /**
+     * Initialize this access manager. An <code>AccessDeniedException</code> will
+     * be thrown if the subject of the given <code>context</code> is not
+     * granted access to the specified workspace.
+     *
+     * @param context access manager context
+     * @param acProvider
+     * @param wspAccessMgr
+     * @throws AccessDeniedException if the subject is not granted access
+     *                               to the specified workspace.
+     * @throws Exception             if another error occurs
+     */
+    void init(AMContext context, AccessControlProvider acProvider,
+              WorkspaceAccessManager wspAccessMgr) throws AccessDeniedException, Exception;
+
+    /**
      * Close this access manager. After having closed an access manager,
      * further operations on this object are treated as illegal and throw
      *
@@ -79,6 +100,7 @@
      * @throws AccessDeniedException if permission is denied
      * @throws ItemNotFoundException if the target item does not exist
      * @throws RepositoryException   it an error occurs
+     * @deprecated 
      */
     void checkPermission(ItemId id, int permissions)
             throws AccessDeniedException, ItemNotFoundException, RepositoryException;
@@ -98,21 +120,66 @@
      * @return <code>true</code> if permission is granted; otherwise <code>false</code>
      * @throws ItemNotFoundException if the target item does not exist
      * @throws RepositoryException   if another error occurs
+     * @deprecated
      */
     boolean isGranted(ItemId id, int permissions)
             throws ItemNotFoundException, RepositoryException;
 
     /**
+     * Determines whether the specified <code>permissions</code> are granted
+     * on the item with the specified <code>absPath</code> (i.e. the <i>target</i>
+     * item, that may or may not yet exist).
+     *
+     * @param absPath     the absolute path to test
+     * @param permissions A combination of one or more of the following constants
+     *                    encoded as a bitmask value:
+     * <ul>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#READ READ}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#ADD_NODE ADD_NODE}</code></li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#REMOVE_NODE REMOVE_NODE}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#SET_PROPERTY SET_PROPERTY}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#REMOVE_PROPERTY REMOVE_PROPERTY}</li>
+     * </ul>
+     * @return <code>true</code> if the specified permissions are granted;
+     * otherwise <code>false</code>.
+     */
+    boolean isGranted(Path absPath, int permissions) throws RepositoryException;
+
+    /**
+     * Determines whether the specified <code>permissions</code> are granted
+     * on an item represented by the combination of the given
+     * <code>parentPath</code> and <code>childName</code> (i.e. the <i>target</i>
+     * item, that may or may not yet exist).
+     *
+     * @param parentPath  Path to an existing parent node.
+     * @param childName   Name of the child item that may or may not exist yet.
+     * @param permissions A combination of one or more of the following constants
+     *                    encoded as a bitmask value:
+     * <ul>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#READ READ}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#ADD_NODE ADD_NODE}</code></li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#REMOVE_NODE REMOVE_NODE}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#SET_PROPERTY SET_PROPERTY}</li>
+     * <li>{@link org.apache.jackrabbit.core.security.authorization.Permission#REMOVE_PROPERTY REMOVE_PROPERTY}</li>
+     * </ul>
+     * @return <code>true</code> if the specified permissions are granted;
+     * otherwise <code>false</code>.
+     * @throws ItemNotFoundException
+     * @throws RepositoryException
+     */
+    boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException;
+
+    /**
      * Determines whether the subject of the current context is granted access
-     * to the given workspace.
+     * to the given workspace. Note that an implementation is free to test for
+     * the existance of a workspace with the specified name. In this case
+     * the expected return value is <code>false</code>, if no such workspace
+     * exists.
      *
      * @param workspaceName name of workspace
      * @return <code>true</code> if the subject of the current context is
      *         granted access to the given workspace; otherwise <code>false</code>.
-     * @throws NoSuchWorkspaceException if a workspace with the given name
-     *                                  does not exist.
-     * @throws RepositoryException      if another error occurs
+     * @throws RepositoryException if another error occurs.
      */
-    boolean canAccess(String workspaceName)
-            throws NoSuchWorkspaceException, RepositoryException;
+    boolean canAccess(String workspaceName) throws RepositoryException;
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AnonymousPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AnonymousPrincipal.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AnonymousPrincipal.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AnonymousPrincipal.java Wed Mar 19 06:56:13 2008
@@ -22,9 +22,9 @@
 /**
  * A <code>AnonymousPrincipal</code> ...
  */
-public class AnonymousPrincipal implements Principal, Serializable {
+public final class AnonymousPrincipal implements Principal, Serializable {
 
-    private static final String ANONYMOUS_USER = "anonymous";
+    private static final String ANONYMOUS_NAME = "anonymous";
 
     /**
      * Creates an <code>AnonymousPrincipal</code>.
@@ -47,7 +47,7 @@
     }
 
     public int hashCode() {
-        return ANONYMOUS_USER.hashCode();
+        return ANONYMOUS_NAME.hashCode();
     }
 
     //------------------------------------------------------------< Principal >
@@ -55,6 +55,6 @@
      * {@inheritDoc}
      */
     public String getName() {
-        return ANONYMOUS_USER;
+        return ANONYMOUS_NAME;
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AuthContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AuthContext.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AuthContext.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AuthContext.java Wed Mar 19 06:56:13 2008
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.core.security;
 
+import org.apache.jackrabbit.core.security.authentication.JAASAuthContext;
+import org.apache.jackrabbit.core.security.authentication.LocalAuthContext;
+
 import javax.jcr.Credentials;
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
@@ -30,13 +33,14 @@
  * <p>
  * This class is abstract and has two implementations:
  * <ul>
- *   <li>{@link AuthContext.JAAS} which delegates to a regular JAAS <code>LoginContext</code></li>
- *   <li>{@link AuthContext.Local} which implements authentication using a locally-defined
+ *   <li>{@link JAASAuthContext} which delegates to a regular JAAS <code>LoginContext</code></li>
+ *   <li>{@link LocalAuthContext} which implements authentication using a locally-defined
  *       JAAS <code>LoginModule</code></li>
  * </ul>
  *
+ * @deprecated Use {@link org.apache.jackrabbit.core.security.authentication.AuthContext} instead.
  */
-public abstract class AuthContext {
+public abstract class AuthContext implements org.apache.jackrabbit.core.security.authentication.AuthContext {
 
     /**
      * Perform the authentication and, if successful, associate Principals and Credentials
@@ -65,6 +69,8 @@
 
     /**
      * An {@link AuthContext} implemented using a regular JAAS <code>LoginContext</code>.
+     *
+     * @deprecated Use {@link org.apache.jackrabbit.core.security.authentication.JAASAuthContext} instead
      */
     public static class JAAS extends AuthContext {
 
@@ -106,6 +112,8 @@
 
     /**
      * An {@link AuthContext} implemented using a particular <code>LoginModule</code>.
+     *
+     * @deprecated Use {@link org.apache.jackrabbit.core.security.authentication.LocalAuthContext} instead.
      */
     public static class Local extends AuthContext {
         private final LoginModule module;
@@ -118,7 +126,6 @@
          *
          * @param module the login module
          * @param options login module options
-         * @param config the login module configuration
          * @param creds the credentials
          */
         public Local(LoginModule module, Map options, Credentials creds) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallback.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallback.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallback.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallback.java Wed Mar 19 06:56:13 2008
@@ -16,38 +16,11 @@
  */
 package org.apache.jackrabbit.core.security;
 
-import javax.jcr.Credentials;
-import javax.security.auth.callback.Callback;
-import java.io.Serializable;
-
 /**
  * A <code>CredentialsCallback</code> ...
+ *
+ * @deprecated Use {@link org.apache.jackrabbit.core.security.authentication.CredentialsCallback } instead.
  */
-public class CredentialsCallback implements Callback, Serializable {
-
-    private Credentials credentials;
-
-    /**
-     * Constructor
-     */
-    public CredentialsCallback() {
-    }
-
-    /**
-     * Get the retrieved credentials.
-     *
-     * @return the retrieved credentials (which may be null)
-     */
-    public Credentials getCredentials() {
-        return credentials;
-    }
+public class CredentialsCallback extends org.apache.jackrabbit.core.security.authentication.CredentialsCallback {
 
-    /**
-     * Set the retrieved credentials.
-     *
-     * @param credentials the retrieved credentials (which may be null)
-     */
-    public void setCredentials(Credentials credentials) {
-        this.credentials = credentials;
-    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallbackHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallbackHandler.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallbackHandler.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/CredentialsCallbackHandler.java Wed Mar 19 06:56:13 2008
@@ -16,57 +16,25 @@
  */
 package org.apache.jackrabbit.core.security;
 
+import org.apache.jackrabbit.core.security.principal.PrincipalProviderRegistry;
+
 import javax.jcr.Credentials;
-import javax.jcr.SimpleCredentials;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import java.io.IOException;
+import javax.jcr.Session;
 
 /**
- * A <code>CredentialsCallbackHandler</code> ...
+ * A <code>CallbackHandlerImpl</code> ...
+ *
+ * @deprecated Use {@link org.apache.jackrabbit.core.security.authentication.CallbackHandlerImpl} instead.
  */
-public class CredentialsCallbackHandler implements CallbackHandler {
-
-    protected final Credentials credentials;
+public class CredentialsCallbackHandler extends org.apache.jackrabbit.core.security.authentication.CallbackHandlerImpl {
 
-    /**
-     * Constructor
-     *
-     * @param credentials
-     */
     public CredentialsCallbackHandler(Credentials credentials) {
-        this.credentials = credentials;
+        super(credentials, null, null);
     }
 
-    //------------------------------------------------------< CallbackHandler >
-    /**
-     * {@inheritDoc}
-     */
-    public void handle(Callback[] callbacks) throws IOException,
-            UnsupportedCallbackException {
-        for (int i = 0; i < callbacks.length; i++) {
-            if (callbacks[i] instanceof CredentialsCallback) {
-                CredentialsCallback ccb = (CredentialsCallback) callbacks[i];
-                // supply credentials
-                ccb.setCredentials(credentials);
-            } else if (callbacks[i] instanceof NameCallback
-                    && credentials instanceof SimpleCredentials) {
-                NameCallback ncb = (NameCallback) callbacks[i];
-                SimpleCredentials sc = (SimpleCredentials) credentials;
-                // supply name
-                ncb.setName(sc.getUserID());
-            } else if (callbacks[i] instanceof PasswordCallback
-                    && credentials instanceof SimpleCredentials) {
-                PasswordCallback pcb = (PasswordCallback) callbacks[i];
-                SimpleCredentials sc = (SimpleCredentials) credentials;
-                // supply password
-                pcb.setPassword(sc.getPassword());
-            } else {
-                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
-            }
-        }
+    public CredentialsCallbackHandler(Credentials credentials,
+                                      Session session,
+                                      PrincipalProviderRegistry principalProviderRegistry) {
+        super(credentials, session, principalProviderRegistry);
     }
 }

Added: 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=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,500 @@
+/*
+ * 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.core.security;
+
+import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
+import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicyIterator;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * The <code>DefaultAccessManager</code> controls access by evaluating access
+ * control policies for the <code>Subject</code> attached to the
+ * <code>Session</code> this manager has been built for.<p>
+ * Please note the following exceptional situations:<br>
+ * This manager allows all privileges for a particular item if
+ * <ul>
+ * <li>the Session's Subject contains a {@link SystemPrincipal} <i>or</i>
+ * an {@link AdminPrincipal}</li>
+ * </ul>
+ * <p/>
+ * It allows to access all available workspaces if
+ * <ul>
+ * <li>no <code>WorkspaceAccessManager</code> is defined.</li>
+ * </ul>
+ * <p/>
+ * How access control policies are matched to a particular item is defined by
+ * the <code>AccessControlProvider</code> set to this AccessManager.
+ *
+ * @version $Rev$, $Date$
+ * @see AccessManager
+ * @see AccessControlManager
+ */
+public class DefaultAccessManager extends AbstractAccessControlManager implements AccessManager {
+
+    private static final Logger log = LoggerFactory.getLogger(DefaultAccessManager.class);
+
+    private boolean initialized;
+
+    private NamePathResolver resolver;
+
+    private Set principals;
+
+    private AccessControlProvider acProvider;
+
+    private AccessControlEditor editor;
+
+    /**
+     * the workspace access
+     */
+    private WorkspaceAccess wspAccess;
+
+    /**
+     * access items for resolution of last persisted item in hierarchy
+     */
+    private HierarchyManager hierMgr;
+
+    /**
+     * The permissions that apply for the principals, that are present with
+     * the session subject this manager has been created for.
+     */
+    private CompiledPermissions compiledPermissions;
+
+    //------------------------------------------------------< AccessManager >---
+    /**
+     * @see AccessManager#init(AMContext)
+     */
+    public void init(AMContext amContext) throws AccessDeniedException, Exception {
+        init(amContext, null, null);
+    }
+
+    /**
+     * @see AccessManager#init(AMContext, AccessControlProvider, WorkspaceAccessManager)
+     */
+    public void init(AMContext amContext, AccessControlProvider acProvider,
+                     WorkspaceAccessManager wspAccessManager) throws AccessDeniedException, Exception {
+        if (initialized) {
+            throw new IllegalStateException("Already initialized.");
+        }
+
+        this.acProvider = acProvider;
+
+        resolver = amContext.getNamePathResolver();
+        hierMgr = amContext.getHierarchyManager();
+
+        Subject subject = amContext.getSubject();
+        principals = (subject == null) ? Collections.EMPTY_SET : subject.getPrincipals();
+
+        wspAccess = new WorkspaceAccess(wspAccessManager, isSystemOrAdmin(subject));
+
+        if (acProvider != null) {
+            editor = acProvider.getEditor(amContext.getSession());
+            compiledPermissions = acProvider.compilePermissions(principals);
+        } else {
+            // TODO: review expected default-permissions here.
+            log.warn("No AccessControlProvider defined -> no access is granted.");
+            editor = null;
+            compiledPermissions = new CompiledPermissions() {
+                public void close() {
+                    //nop
+                }
+                public boolean grants(Path absPath, int permissions) throws RepositoryException {
+                    // deny everything
+                    return false;
+                }
+                public int getPrivileges(Path absPath) throws RepositoryException {
+                    return 0;
+                }
+            };
+        }
+
+        initialized = true;
+
+        if (!canAccess(amContext.getWorkspaceName())) {
+            throw new AccessDeniedException("Not allowed to access Workspace " + amContext.getWorkspaceName());
+        }
+    }
+
+    /**
+     * @see AccessManager#close()
+     */
+    public void close() throws Exception {
+        if (!initialized) {
+            throw new IllegalStateException("Manager is not initialized.");
+        }
+        initialized = false;
+        compiledPermissions.close();
+
+        hierMgr = null;
+        acProvider = null;
+        editor = null;
+        wspAccess = null;
+    }
+
+    /**
+     * @see AccessManager#checkPermission(ItemId, int)
+     */
+    public void checkPermission(ItemId id, int permissions) throws AccessDeniedException, ItemNotFoundException, RepositoryException {
+        if (!isGranted(id, permissions)) {
+            throw new AccessDeniedException("Not sufficient privileges for permissions : " + permissions + " on " + hierMgr.getPath(id));
+        }
+    }
+
+    /**
+     * @see AccessManager#isGranted(ItemId, int)
+     */
+    public boolean isGranted(ItemId id, int actions)
+            throws ItemNotFoundException, RepositoryException {
+        checkInitialized();
+        int perm = 0;
+        if ((actions & READ) == READ) {
+            perm |= Permission.READ;
+        }
+        if ((actions & WRITE) == WRITE) {
+            if (id.denotesNode()) {
+                // TODO: check again if correct
+                perm |= Permission.SET_PROPERTY;
+                perm |= Permission.ADD_NODE;
+            } else {
+                perm |= Permission.SET_PROPERTY;
+            }
+        }
+        if ((actions & REMOVE) == REMOVE) {
+            perm |= (id.denotesNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
+        }
+        Path path = hierMgr.getPath(id);
+        return isGranted(path, perm);
+    }
+
+    public boolean isGranted(Path absPath, int permissions) throws RepositoryException {
+        checkInitialized();
+        if (!absPath.isAbsolute()) {
+            throw new RepositoryException("Absolute path expected");
+        }
+        return compiledPermissions.grants(absPath, permissions);
+    }
+
+    public boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException {
+        Path p = PathFactoryImpl.getInstance().create(parentPath, childName, true);
+        return isGranted(p, permissions);
+    }
+
+    /**
+     * @see AccessManager#canAccess(String)
+     */
+    public boolean canAccess(String workspaceName) throws NoSuchWorkspaceException, RepositoryException {
+        checkInitialized();
+        return wspAccess.canAccess(workspaceName);
+    }
+
+    //-----------------------------------------------< AccessControlManager >---
+    /**
+     * @see AccessControlManager#hasPrivileges(String, Privilege[])
+     */
+    public boolean hasPrivileges(String absPath, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        if (privileges == null || privileges.length == 0) {
+            // null or empty privilege array -> return true
+            log.debug("No privileges defined for hasPrivilege test.");
+            return true;
+        } else {
+            int privs = PrivilegeRegistry.getBits(privileges);
+            return internalHasPrivileges(path, privs);
+        }
+    }
+
+    /**
+     * @see AccessControlManager#getPrivileges(String)
+     */
+    public Privilege[] getPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        int privs = compiledPermissions.getPrivileges(path);
+        return (privs == 0) ? new Privilege[0] : PrivilegeRegistry.getPrivileges(privs);
+    }
+
+    /**
+     * @see AccessControlManager#getPolicy(String)
+     */
+    public AccessControlPolicy getPolicy(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.READ_AC);
+
+        AccessControlPolicy policy = null;
+        if (editor != null) {
+            policy = editor.getPolicyTemplate(getNodeId(path));
+        }
+        return policy;
+    }
+
+    /**
+     * @see AccessControlManager#getEffectivePolicy(String)
+     */
+    public AccessControlPolicy getEffectivePolicy(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.READ_AC);
+
+        // TODO: acProvider may not retrieve the correct policy in case of transient modifications
+        return acProvider.getPolicy(getNodeId(path));
+    }
+
+    /**
+     * @see AccessControlManager#getApplicablePolicies(String)
+     */
+    public AccessControlPolicyIterator getApplicablePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.READ_AC);
+
+        if (editor != null) {
+            PolicyTemplate applicable = editor.editPolicyTemplate(getNodeId(path));
+            if (applicable != null) {
+                return new AccessControlPolicyIteratorAdapter(Collections.singletonList(applicable));
+            }
+        }
+        // no applicable policies -> return empty iterator.
+        return AccessControlPolicyIteratorAdapter.EMPTY;
+    }
+
+    /**
+     * @see AccessControlManager#setPolicy(String, AccessControlPolicy)
+     */
+    public void setPolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        if (policy instanceof PolicyTemplate) {
+            Path path = getValidNodePath(absPath);
+            checkPrivileges(path, PrivilegeRegistry.MODIFY_AC);
+            if (editor == null) {
+                throw new UnsupportedRepositoryOperationException("Modification of AccessControlPolicies is not supported. ");
+            }
+            editor.setPolicyTemplate(getNodeId(path), (PolicyTemplate) policy);
+        } else {
+            throw new AccessControlException("Access control policy '" + policy + "' not applicable");
+        }
+    }
+
+    /**
+     * @see AccessControlManager#removePolicy(String)
+     */
+    public AccessControlPolicy removePolicy(String absPath) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.MODIFY_AC);
+        if (editor == null) {
+            throw new UnsupportedRepositoryOperationException("Removal of AccessControlPolicies is not supported.");
+        }
+        return editor.removePolicyTemplate(getNodeId(path));
+    }
+
+    /**
+     * @see AccessControlManager#getAccessControlEntries(String)
+     */
+    public AccessControlEntry[] getAccessControlEntries(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.READ_AC);
+
+        AccessControlEntry[] entries = new AccessControlEntry[0];
+        if (editor != null) {
+            entries = editor.getAccessControlEntries(getNodeId(path));
+        }
+        return entries;
+    }
+
+    /**
+     * @see AccessControlManager#getEffectiveAccessControlEntries(String)
+     */
+    public AccessControlEntry[] getEffectiveAccessControlEntries(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.READ_AC);
+
+        return acProvider.getAccessControlEntries(getNodeId(path));
+    }
+
+    /**
+     * @see AccessControlManager#addAccessControlEntry(String, Principal, Privilege[])
+     */
+    public AccessControlEntry addAccessControlEntry(String absPath, Principal principal, Privilege[] privileges) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.MODIFY_AC);
+
+        if (editor == null) {
+            throw new UnsupportedRepositoryOperationException("Adding access control entries is not supported.");
+        } else {
+            NodeId id = getNodeId(path);
+            return editor.addAccessControlEntry(id, principal, privileges);
+        }
+    }
+
+    /**
+     * @see AccessControlManager#removeAccessControlEntry(String, AccessControlEntry)
+     */
+    public void removeAccessControlEntry(String absPath, AccessControlEntry ace) throws PathNotFoundException, AccessControlException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path path = getValidNodePath(absPath);
+        checkPrivileges(path, PrivilegeRegistry.MODIFY_AC);
+        if (editor == null) {
+            throw new UnsupportedRepositoryOperationException("Removal of access control entries is not supported.");
+        }
+        NodeId id = getNodeId(path);
+        if (!editor.removeAccessControlEntry(id, ace)) {
+            throw new AccessControlException("AccessControlEntry " + ace + " has not been assigned though this API.");
+        }
+    }
+
+    //---------------------------------------< AbstractAccessControlManager >---
+    /**
+     * @see AbstractAccessControlManager#checkInitialized()
+     */
+    protected void checkInitialized() {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+    }
+
+    /**
+     * @see AbstractAccessControlManager#getValidNodePath(String)
+     */
+    protected Path getValidNodePath(String absPath) throws PathNotFoundException, RepositoryException {
+        Path p = resolver.getQPath(absPath);
+        if (!p.isAbsolute()) {
+            throw new RepositoryException("Absolute path expected.");
+        }
+        if (hierMgr.resolveNodePath(p) != null) {
+            return p;
+        } else {
+            throw new PathNotFoundException("No such node " + absPath);
+        }
+    }
+
+    /**
+     * @see AbstractAccessControlManager#checkPrivileges(Path, int)
+     */
+    protected void checkPrivileges(Path absPath, int privileges) throws AccessDeniedException, RepositoryException {
+        if (!internalHasPrivileges(absPath, privileges)) {
+            throw new AccessDeniedException("No privilege " + privileges + " at " + resolver.getJCRPath(absPath));
+        }
+    }
+
+    //------------------------------------------------------------< private >---
+    private boolean internalHasPrivileges(Path path, int privileges) throws RepositoryException {
+        return (compiledPermissions.getPrivileges(path) | ~privileges) == -1;
+    }
+
+    private NodeId getNodeId(Path absPath) throws RepositoryException {
+        NodeId id = hierMgr.resolveNodePath(absPath);
+        if (id == null) {
+            throw new PathNotFoundException(resolver.getJCRPath(absPath));
+        }
+        return id;
+    }
+
+    /**
+     * @return if created with system-privileges
+     */
+    private static boolean isSystemOrAdmin(Subject subject) {
+        if (subject == null) {
+            return false;
+        } else {
+            return !(subject.getPrincipals(SystemPrincipal.class).isEmpty() &&
+                     subject.getPrincipals(AdminPrincipal.class).isEmpty());
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Simple wrapper around the repository's <code>WorkspaceAccessManager</code>
+     * that remembers for which workspaces the access has already been
+     * evaluated.
+     */
+    private class WorkspaceAccess {
+
+        private final WorkspaceAccessManager wspAccessManager;
+
+        private final boolean isAdmin;
+        // TODO: entries must be cleared if access permission to wsp change.
+        private final List allowed;
+        private final List denied;
+
+        private WorkspaceAccess(WorkspaceAccessManager wspAccessManager,
+                                boolean isAdmin) {
+            this.wspAccessManager = wspAccessManager;
+            this.isAdmin = isAdmin;
+            if (!isAdmin) {
+                allowed = new ArrayList(5);
+                denied = new ArrayList(5);
+            } else {
+                allowed = denied = null;
+            }
+        }
+
+        private boolean canAccess(String workspaceName) throws RepositoryException {
+            if (isAdmin || wspAccessManager == null || allowed.contains(workspaceName)) {
+                return true;
+            } else if (denied.contains(workspaceName)) {
+                return false;
+            }
+
+            // not yet tested -> ask the workspace-accessmanager.
+            boolean canAccess = wspAccessManager.grants(principals, workspaceName);
+            if (canAccess) {
+                allowed.add(workspaceName);
+            } else {
+                denied.add(workspaceName);
+            }
+            return canAccess;
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,103 @@
+/*
+ * 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.core.security;
+
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.config.SecurityConfig;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Repository;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.security.auth.Subject;
+
+/**
+ * <code>JackrabbitSecurityManager</code>...
+ */
+public interface JackrabbitSecurityManager {
+
+    public void init(Repository repository, Session systemSession) throws RepositoryException;
+
+    /**
+     * Disposes those parts of this security manager that are related to the
+     * workspace indicated by the given <code>workspaceName</code>.
+     *
+     * @param workspaceName Name of the workspace that is being disposed.
+     */
+    public void dispose(String workspaceName);
+
+    /**
+     * Disposes this security manager instance and cleans all internal caches.
+     */
+    public void close();
+
+    /**
+     * Returns the configuration that applies to this manager.
+     *
+     * @return security config
+     * @throws RepositoryException
+     */
+    public SecurityConfig getSecurityConfig() throws RepositoryException;
+
+    /**
+     * Returns a new <code>AuthContext</code> for the specified credentials and
+     * subject.
+     *
+     * @param creds
+     * @param subject
+     * @return A new <code>AuthContext</code> for the given <code>creds</code>
+     * and <code>subject</code>.
+     * @throws RepositoryException
+     */
+    public AuthContext getAuthContext(Credentials creds, Subject subject) throws RepositoryException;
+
+    /**
+     * Retrieve the <code>AccessManager</code> for the given <code>session</code>.
+     *
+     * @param session
+     * @param amContext
+     * @return <code>AccessManager</code> for the specified <code>session</code>.
+     * @throws RepositoryException
+     */
+    public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException;
+
+    /**
+     * Retrieve the principal manager for the given <code>session</code>.
+     *
+     * @param session
+     * @return PrincipalManager for the given <code>session</code>.
+     * @throws UnsupportedRepositoryOperationException If principal management
+     * is not supported.
+     * @throws RepositoryException if an error occurs
+     */
+    public PrincipalManager getPrincipalManager(Session session) throws RepositoryException;
+
+    /**
+     * Returns the user manager for the specified <code>session</code>.
+     *
+     * @param session
+     * @return UserManager for the given <code>session</code>.
+     * @throws UnsupportedRepositoryOperationException If user management is
+     * not supported.
+     * @throws RepositoryException
+     */
+    public UserManager getUserManager(Session session) throws RepositoryException;
+
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SecurityConstants.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SecurityConstants.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SecurityConstants.java Wed Mar 19 06:56:13 2008
@@ -28,6 +28,26 @@
      *
      * @see javax.jcr.Session#impersonate(javax.jcr.Credentials)
      */
-    String IMPERSONATOR_ATTRIBUTE =
-            "org.apache.jackrabbit.core.security.impersonator";
+    String IMPERSONATOR_ATTRIBUTE = "org.apache.jackrabbit.core.security.impersonator";
+
+    /**
+     * The default principal name of the administrators group
+     */
+    String ADMINISTRATORS_NAME = "administrators";
+
+    /**
+     * The default userID of the administrator.
+     */
+    String ADMIN_ID = "admin";
+
+    /**
+     * The default userID for anonymous login
+     */
+    String ANONYMOUS_ID = "anonymous";
+
+    /**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()}  SimpleCredentials} 
+     */
+    String DEFAULT_DIGEST = "sha1";
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleAccessManager.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleAccessManager.java Wed Mar 19 06:56:13 2008
@@ -16,127 +16,11 @@
  */
 package org.apache.jackrabbit.core.security;
 
-import org.apache.jackrabbit.core.HierarchyManager;
-import org.apache.jackrabbit.core.ItemId;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.RepositoryException;
-import javax.security.auth.Subject;
-
 /**
  * <code>SimpleAccessManager</code> ...
+ *
+ * @deprecated Use {@link org.apache.jackrabbit.core.security.simple.SimpleAccessManager} instead.
  */
-public class SimpleAccessManager implements AccessManager {
-
-    /**
-     * Subject whose access rights this AccessManager should reflect
-     */
-    protected Subject subject;
-
-    /**
-     * hierarchy manager used for ACL-based access control model
-     */
-    protected HierarchyManager hierMgr;
-
-    private boolean initialized;
-
-    protected boolean system;
-    protected boolean anonymous;
-
-    /**
-     * Empty constructor
-     */
-    public SimpleAccessManager() {
-        initialized = false;
-        anonymous = false;
-        system = false;
-    }
-
-    //--------------------------------------------------------< AccessManager >
-    /**
-     * {@inheritDoc}
-     */
-    public void init(AMContext context)
-            throws AccessDeniedException, Exception {
-        if (initialized) {
-            throw new IllegalStateException("already initialized");
-        }
-
-        subject = context.getSubject();
-        hierMgr = context.getHierarchyManager();
-        anonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty();
-        system = !subject.getPrincipals(SystemPrincipal.class).isEmpty();
-
-        // @todo check permission to access given workspace based on principals
-        initialized = true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public synchronized void close() throws Exception {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        initialized = false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void checkPermission(ItemId id, int permissions)
-            throws AccessDeniedException, ItemNotFoundException,
-            RepositoryException {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        if (system) {
-            // system has always all permissions
-            return;
-        } else if (anonymous) {
-            // anonymous is always denied WRITE & REMOVE permissions
-            if ((permissions & WRITE) == WRITE
-                    || (permissions & REMOVE) == REMOVE) {
-                throw new AccessDeniedException();
-            }
-        }
-        // @todo check permission based on principals
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isGranted(ItemId id, int permissions)
-            throws ItemNotFoundException, RepositoryException {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        if (system) {
-            // system has always all permissions
-            return true;
-        } else if (anonymous) {
-            // anonymous is always denied WRITE & REMOVE premissions
-            if ((permissions & WRITE) == WRITE
-                    || (permissions & REMOVE) == REMOVE) {
-                return false;
-            }
-        }
-
-        // @todo check permission based on principals
-        return true;
-    }
+public class SimpleAccessManager extends org.apache.jackrabbit.core.security.simple.SimpleAccessManager {
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean canAccess(String workspaceName)
-            throws NoSuchWorkspaceException, RepositoryException {
-        // @todo check permission to access given workspace based on principals
-        return true;
-    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java Wed Mar 19 06:56:13 2008
@@ -16,6 +16,18 @@
  */
 package org.apache.jackrabbit.core.security;
 
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Name;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ItemNotFoundException;
 import java.io.File;
 import java.io.FileInputStream;
 import java.security.Principal;
@@ -24,12 +36,6 @@
 import java.util.Iterator;
 import java.util.Properties;
 
-import javax.jcr.AccessDeniedException;
-
-import org.apache.jackrabbit.core.ItemId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * The simple JBoss access manager is a specialized Access Manager to
  * handle Authorization of individuals authenticated through JBoss
@@ -56,6 +62,10 @@
 
     public void init(AMContext context)
             throws AccessDeniedException, Exception {
+        init(context, null, null);
+    }
+
+    public void init(AMContext context, AccessControlProvider acProvider, WorkspaceAccessManager wspAccessMgr) throws AccessDeniedException, Exception {
         Properties rolemaps = new Properties();
         File rolemap = new File(context.getHomeDir(), "rolemapping.properties");
         log.info("Loading jbossgroup role mappings from {}", rolemap.getPath());
@@ -97,12 +107,25 @@
 
     public boolean isGranted(ItemId id, int permissions) {
         // system has always all permissions
-        // anonymous has all but WRITE & REMOVE premissions
+        // anonymous has only READ premissions
         return system || (anonymous && ((permissions & (WRITE | REMOVE)) == 0));
     }
 
+    public boolean isGranted(Path absPath, int permissions) throws RepositoryException {
+        return internalIsGranted(permissions);
+    }
+
+    public boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException {
+        return internalIsGranted(permissions);
+    }
+
     public boolean canAccess(String workspaceName) {
         return system || anonymous;
     }
 
+    private boolean internalIsGranted(int permissions) {
+        /* system has always all permissions,
+           anonymous has only READ premissions */
+        return system || (anonymous && Permission.READ == permissions);
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleLoginModule.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleLoginModule.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleLoginModule.java Wed Mar 19 06:56:13 2008
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.core.security;
 
+import org.apache.jackrabbit.core.security.authentication.CredentialsCallback;
+import org.apache.jackrabbit.core.config.LoginModuleConfig;
+
 import javax.jcr.Credentials;
 import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
@@ -25,30 +28,22 @@
 import javax.security.auth.login.FailedLoginException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
-import java.util.HashSet;
 import java.util.Map;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
  * A <code>SimpleLoginModule</code> ...
+ *
+ * @deprecated Use {@link org.apache.jackrabbit.core.security.simple.SimpleLoginModule} instead.
  */
 public class SimpleLoginModule implements LoginModule {
 
     /**
-     * Name of the anonymous user id option in the LoginModule configuration
-     */
-    private static final String OPT_ANONYMOUS = "anonymousId";
-
-    /**
      * Name of the default user id option in the LoginModule configuration
      */
     private static final String OPT_DEFAULT = "defaultUserId";
 
-    /**
-     * The default user id for anonymous login
-     */
-    private static final String DEFAULT_ANONYMOUS_ID = "anonymous";
-
     // initial state
     private Subject subject;
     private CallbackHandler callbackHandler;
@@ -58,22 +53,23 @@
 
     // local authentication state:
     // the principals, i.e. the authenticated identities
-    private final Set principals = new HashSet();
+    private final Set principals;
 
     /**
      * Id of an anonymous user login
      */
-    private String anonymousUserId = DEFAULT_ANONYMOUS_ID;
+    private String anonymousUserId = SecurityConstants.ANONYMOUS_ID;
 
     /**
      * The default user id. Only used when not <code>null</code>.
      */
-    private String defaultUserId = null;
+    private String defaultUserId;
 
     /**
      * Constructor
      */
     public SimpleLoginModule() {
+        principals = new HashSet();
     }
 
     /**
@@ -124,7 +120,7 @@
 
         // initialize any configured options
         //someOpt = "true".equalsIgnoreCase((String)options.get("someOpt"));
-        String userId = (String) options.get(OPT_ANONYMOUS);
+        String userId = (String) options.get(LoginModuleConfig.PARAM_ANONYMOUS_ID);
         if (userId != null) {
             anonymousUserId = userId;
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SystemPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SystemPrincipal.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SystemPrincipal.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SystemPrincipal.java Wed Mar 19 06:56:13 2008
@@ -22,7 +22,7 @@
 /**
  * A <code>SystemPrincipal</code> ...
  */
-public class SystemPrincipal implements Principal, Serializable {
+public final class SystemPrincipal implements Principal, Serializable {
 
     private static final String SYSTEM_USER = "system";