jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r638834 [2/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...
Date Wed, 19 Mar 2008 13:57:11 GMT
Added: 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=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,479 @@
+/*
+ * 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;
+
+import org.apache.jackrabbit.core.config.AccessManagerConfig;
+import org.apache.jackrabbit.core.config.BeanConfig;
+import org.apache.jackrabbit.core.config.LoginModuleConfig;
+import org.apache.jackrabbit.core.config.SecurityConfig;
+import org.apache.jackrabbit.core.config.WorkspaceConfig;
+import org.apache.jackrabbit.core.config.WorkspaceSecurityConfig;
+import org.apache.jackrabbit.core.security.AMContext;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
+import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
+import org.apache.jackrabbit.core.security.authentication.AuthContextProvider;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactory;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactoryImpl;
+import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.principal.DefaultPrincipalProvider;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.core.security.principal.PrincipalManagerImpl;
+import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.core.security.principal.PrincipalProviderRegistry;
+import org.apache.jackrabbit.core.security.principal.ProviderRegistryImpl;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * The security manager acts as central managing class for all security related
+ * operations on a low-level non-protected level. It manages the
+ * <ul>
+ * <li> {@link PrincipalProvider}s
+ * <li> {@link AccessControlProvider}s
+ * <li> {@link WorkspaceAccessManager}
+ * <li> {@link UserManager}
+ * </ul>
+ */
+public class DefaultSecurityManager implements JackrabbitSecurityManager {
+
+    // TODO: should rather be placed in the core.security package. However protected access to SystemSession required to move here.
+    /**
+     * the default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(DefaultSecurityManager.class);
+
+    /**
+     *
+     */
+    private boolean initialized;
+
+    /**
+     * the repository implementation
+     */
+    private RepositoryImpl repository;
+
+    /**
+     * session on the system workspace.
+     */
+    private SystemSession securitySession;
+
+    /**
+     * System user manager. Implementation needed here for the DefaultPrincipalProvider.
+     */
+    private UserManager systemUserManager;
+
+    /**
+     * System Sessions PrincipalMangager used for internal access to Principals
+     */
+    private PrincipalManager systemPrincipalManager;
+
+    /**
+     * The user id of the administrator. The value is retrieved from
+     * configuration. If the config entry is missing a default id is used (see
+     * {@link SecurityConstants#ADMIN_ID}).
+     *
+     */
+    private String adminId;
+
+    /**
+     * Contains the access control providers per workspace.
+     * key = name of the workspace,
+     * value = {@link AccessControlProvider}
+     */
+    private final Map acProviders = new HashMap();
+
+    /**
+     * the AccessControlProviderFactory
+     */
+    private AccessControlProviderFactory acProviderFactory;
+
+    /**
+     * the configured WorkspaceAccessManager
+     */
+    private WorkspaceAccessManager workspaceAccessManager;
+
+    /**
+     * the principal provider registry
+     */
+    private PrincipalProviderRegistry principalProviderRegistry;
+
+    /**
+     * factory for login-context {@see Repository#login())
+     */
+    private AuthContextProvider authContextProvider;
+
+    //------------------------------------------< JackrabbitSecurityManager >---
+    /**
+     * @see JackrabbitSecurityManager#init(Repository, Session)
+     */
+    public synchronized void init(Repository repository, Session systemSession) throws RepositoryException {
+        if (initialized) {
+            throw new IllegalStateException("already initialized");
+        }
+        if (!(repository instanceof RepositoryImpl)) {
+            throw new RepositoryException("RepositoryImpl expected");
+        }
+        if (!(systemSession instanceof SystemSession)) {
+            throw new RepositoryException("SystemSession expected");
+        }
+
+        securitySession = (SystemSession) systemSession;
+        this.repository = (RepositoryImpl) repository;
+
+        SecurityConfig config = this.repository.getConfig().getSecurityConfig();
+        LoginModuleConfig loginModConf = config.getLoginModuleConfig();
+
+        // build AuthContextProvider based on appName + optional LoginModuleConfig
+        authContextProvider = new AuthContextProvider(config.getAppName(), loginModConf);
+        if (authContextProvider.isJAAS()) {
+            log.info("init: use JAAS login-configuration for " + config.getAppName());
+        } else if (authContextProvider.isLocal()) {
+            log.info("init: use Repository Login-Configuration for " + config.getAppName());
+        } else {
+            String msg = "Neither JAAS nor RepositoryConfig contained a valid Configuriation for " + config.getAppName();
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+
+        Properties[] moduleConfig = authContextProvider.getModuleConfig();
+
+        // retrieve default-ids (admin and anomymous) from login-module-configuration.
+        String anonymousId = null;
+        for (int i = 0; i < moduleConfig.length; i++) {
+            if (moduleConfig[i].containsKey(LoginModuleConfig.PARAM_ADMIN_ID)) {
+                adminId = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ADMIN_ID);
+            }
+            if (moduleConfig[i].containsKey(LoginModuleConfig.PARAM_ANONYMOUS_ID)) {
+                anonymousId = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ANONYMOUS_ID, null);
+            }
+        }
+        // fallback:
+        if (adminId == null) {
+            log.debug("No adminID defined in LoginModule/JAAS config -> using default.");
+            adminId = SecurityConstants.ADMIN_ID;
+        }
+        if (anonymousId == null) {
+            log.debug("No anonymousID defined in LoginModule/JAAS config -> anonymous not defined..");
+        }
+
+        // create the system userManager and make sure the system-users exist.
+        systemUserManager = new UserManagerImpl(securitySession, adminId);
+        createSystemUsers(adminId, anonymousId);
+
+        // init default ac-provider-factory
+        acProviderFactory = new AccessControlProviderFactoryImpl();
+        acProviderFactory.init(this);
+
+        // create the evalutor for workspace access
+        workspaceAccessManager = createWorkspaceAccessManager();
+
+        // initialize principa-provider registry
+        // 1) create default
+        PrincipalProvider defaultPP = new DefaultPrincipalProvider(securitySession, (UserManagerImpl) systemUserManager);
+        defaultPP.init(new Properties());
+        // 2) create registry instance
+        principalProviderRegistry = new ProviderRegistryImpl(defaultPP);
+        // 3) register all configured principal providers.
+        for (int i = 0; i < moduleConfig.length; i++) {
+            principalProviderRegistry.registerProvider(moduleConfig[i]);
+        }
+
+        // create the principal manager for the security workspace
+        systemPrincipalManager = new PrincipalManagerImpl(securitySession, principalProviderRegistry.getProviders());
+
+        initialized = true;
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#dispose(String)
+     */
+    public void dispose(String workspaceName) {
+        checkInitialized();
+        synchronized (acProviders) {
+            AccessControlProvider prov = (AccessControlProvider) acProviders.remove(workspaceName);
+            if (prov != null) {
+                prov.close();
+            }
+        }
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#close()
+     */
+    public void close() {
+        checkInitialized();
+        synchronized (acProviders) {
+            Iterator itr = acProviders.values().iterator();
+            while (itr.hasNext()) {
+                ((AccessControlProvider) itr.next()).close();
+            }
+            acProviders.clear();
+        }
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#getSecurityConfig()
+     */
+    public SecurityConfig getSecurityConfig() throws RepositoryException {
+        return repository.getConfig().getSecurityConfig();
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#getAccessManager(Session,AMContext)
+     */
+    public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException {
+        checkInitialized();
+        AccessManagerConfig amConfig = getSecurityConfig().getAccessManagerConfig();
+        try {
+            String wspName = session.getWorkspace().getName();
+            AccessControlProvider pp = getAccessControlProvider(wspName);
+
+            AccessManager accessMgr = (AccessManager) amConfig.newInstance();
+            accessMgr.init(amContext, pp, workspaceAccessManager);
+            return accessMgr;
+        } catch (AccessDeniedException ade) {
+            // re-throw
+            throw ade;
+        } catch (Exception e) {
+            // wrap in RepositoryException
+            String msg = "Failed to instantiate AccessManager (" + amConfig.getClassName() + ")";
+            e.printStackTrace();
+            log.error(msg, e);
+            throw new RepositoryException(msg, e);
+        }
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#getPrincipalManager(Session)
+     */
+    public synchronized PrincipalManager getPrincipalManager(Session session)
+            throws RepositoryException {
+        checkInitialized();
+        if (session == securitySession) {
+            return systemPrincipalManager;
+        } else if (session instanceof SessionImpl) {
+            SessionImpl sImpl = (SessionImpl) session;
+            return new PrincipalManagerImpl(sImpl, principalProviderRegistry.getProviders());
+        } else {
+            throw new RepositoryException("Internal error: SessionImpl expected.");
+        }
+    }
+
+    /**
+     * @see JackrabbitSecurityManager#getUserManager(Session)
+     */
+    public UserManager getUserManager(Session session) throws RepositoryException {
+        checkInitialized();
+        if (session == securitySession) {
+            return systemUserManager;
+        } else if (session instanceof SessionImpl) {
+            String workspaceName = securitySession.getWorkspace().getName();
+            try {
+                SessionImpl sImpl = (SessionImpl) session;
+                SessionImpl s = (SessionImpl) sImpl.createSession(workspaceName);
+                return new UserManagerImpl(s, adminId);
+            } catch (NoSuchWorkspaceException e) {
+                throw new AccessControlException("Cannot build UserManager for " + session.getUserID(), e);
+            }
+        } else {
+            throw new RepositoryException("Internal error: SessionImpl expected.");
+        }
+    }
+
+    /**
+     * Creates an AuthContext for the given {@link Credentials} and
+     * {@link Subject}.<br>
+     * This includes selection of applicatoin specific LoginModules and
+     * initalization with credentials and Session to System-Workspace
+     *
+     * @return an {@link AuthContext} for the given Credentials, Subject
+     * @throws RepositoryException in other exceptional repository states
+     */
+    public AuthContext getAuthContext(Credentials creds, Subject subject)
+            throws RepositoryException {
+        checkInitialized();
+        return authContextProvider.getAuthContext(creds, subject, securitySession, principalProviderRegistry);
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * @param wspName
+     * @return The <code>WorkspaceSecurityConfig</code> for the given workspace
+     * name or <code>null</code>.
+     */
+    private WorkspaceSecurityConfig getWorkspaceSecurityConfig(String wspName) {
+        WorkspaceConfig conf = repository.getConfig().getWorkspaceConfig(wspName);
+        if (conf == null) {
+            return null;
+        } else {
+            return conf.getSecurityConfig();
+        }
+    }
+
+    /**
+     * Returns the access control provider for the specified
+     * <code>workspaceName</code>.
+     *
+     * @param workspaceName
+     * @return access control provider
+     * @throws NoSuchWorkspaceException If no workspace with 'workspaceName' exists.
+     * @throws RepositoryException
+     */
+    private AccessControlProvider getAccessControlProvider(String workspaceName)
+            throws NoSuchWorkspaceException, RepositoryException {
+
+        synchronized (acProviders) {
+            AccessControlProvider provider = (AccessControlProvider) acProviders.get(workspaceName);
+            if (provider == null) {
+                SystemSession systemSession = repository.getSystemSession(workspaceName);
+                provider = acProviderFactory.createProvider(systemSession, getWorkspaceSecurityConfig(workspaceName));
+                acProviders.put(workspaceName, provider);
+            }
+            return provider;
+        }
+    }
+
+    /**
+     * @return the WorkspaceAccessManager responsible for the repository.
+     */
+    private WorkspaceAccessManager createWorkspaceAccessManager() throws RepositoryException {
+        WorkspaceAccessManager wspAccess;
+        BeanConfig config = repository.getConfig().getSecurityConfig().getSecurityManagerConfig().getWorkspaceAccessConfig();
+        if (config != null) {
+            wspAccess = (WorkspaceAccessManager) config.newInstance();
+        } else {
+            // fallback -> the default implementation
+            log.debug("No WorkspaceAccessManager configured; using default.");
+            wspAccess = new WorkspaceAccessManagerImpl();
+        }
+        wspAccess.init(this);
+        return wspAccess;
+    }
+
+    /**
+     * Make sure the 'administrators' group exists and the user with the
+     * configured (or default) adminID is member of this user-group.
+     *
+     * @param adminId
+     * @param anonymousId
+     * @throws RepositoryException
+     */
+    private void createSystemUsers(String adminId,
+                                   String anonymousId) throws RepositoryException {
+        Principal pr = new PrincipalImpl(SecurityConstants.ADMINISTRATORS_NAME);
+        Group admins = (Group) systemUserManager.getAuthorizable(pr);
+        if (admins == null) {
+            admins = systemUserManager.createGroup(new PrincipalImpl(SecurityConstants.ADMINISTRATORS_NAME));
+            log.debug("...created administrators group with name '"+SecurityConstants.ADMINISTRATORS_NAME+"'");
+        }
+
+        if (adminId != null) {
+            Authorizable admin = systemUserManager.getAuthorizable(adminId);
+            if (admin == null) {
+                Credentials creds = new SimpleCredentials(adminId, adminId.toCharArray());
+                admin = systemUserManager.createUser(adminId, creds, new PrincipalImpl(adminId));
+                log.info("...created admin-user with id \'" + adminId + "\' ...");
+                admins.addMember(admin);
+                log.info("...added admin \'" + adminId + "\' as member of the administrators group.");
+            }
+        }
+
+        if (anonymousId != null) {
+            Authorizable anonymous = systemUserManager.getAuthorizable(anonymousId);
+            if (anonymous == null) {
+                Credentials creds = new SimpleCredentials(anonymousId, new char[0]);
+                systemUserManager.createUser(anonymousId, creds, new PrincipalImpl(anonymousId));
+                log.info("...created anonymous-user with id \'" + anonymousId + "\' ...");
+            }
+        }
+    }
+
+    private void checkInitialized() {
+        if (!initialized) {
+            throw new IllegalStateException("Not initialized");
+        }
+    }
+
+    //------------------------------------------------------< inner classes >---
+    /**
+     * <code>WorkspaceAccessManager</code> that upon {@link #grants(Set principals, String)}
+     * evaluates if access to the root node of a workspace with the specified
+     * name is granted.
+     */
+    private class WorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager {
+
+        private final Path rootPath = PathFactoryImpl.getInstance().getRootPath();
+
+        //-----------------------------------------< WorkspaceAccessManager >---
+        /**
+         * {@inheritDoc}
+         */
+        public void init(JackrabbitSecurityManager securityManager) throws RepositoryException {
+            // nothing to do here.
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void close() throws RepositoryException {
+            // nothing to do here.
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean grants(Set principals, String workspaceName) throws RepositoryException {
+            try {
+                // TODO: improve
+                AccessControlProvider prov = getAccessControlProvider(workspaceName);
+                CompiledPermissions cp = prov.compilePermissions(principals);
+                return cp.grants(rootPath, Permission.READ);
+            } catch (NoSuchWorkspaceException e) {
+                // no such workspace -> return false.
+                return false;
+            }
+        }
+    }
+}

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

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

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Wed Mar 19 06:56:13 2008
@@ -25,9 +25,9 @@
 import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
 import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.ItemStateListener;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.SessionItemStateManager;
@@ -465,13 +465,34 @@
             ItemState itemState = (ItemState) dirtyIter.next();
 
             if (itemState.getStatus() != ItemState.STATUS_NEW) {
-                // transient item is not 'new', therefore it has to be 'modified'
-
+                /* transient item is not 'new', therefore it has to be 'modified'
+                   detect the effective set of modification:
+                   - child additions -> add_node perm on the child
+                   - property additions, modifications or removals -> set_property permission
+                   note: removed items are checked later on.
+                */
                 // check WRITE permission
-                ItemId id = itemState.getId();
-                if (!accessMgr.isGranted(id, AccessManager.WRITE)) {
-                    String msg = itemMgr.safeGetJCRPath(id)
-                            + ": not allowed to modify item";
+                Path path = stateMgr.getHierarchyMgr().getPath(itemState.getId());
+                boolean isGranted = true;
+                if (itemState.isNode()) {
+                    // modified node state -> check possible modifications
+                    NodeState nState = (NodeState) itemState;
+                    for (Iterator it = nState.getAddedChildNodeEntries().iterator();
+                         it.hasNext() && isGranted;) {
+                        Name nodeName = ((NodeState.ChildNodeEntry) it.next()).getName();
+                        isGranted = accessMgr.isGranted(path, nodeName, Permission.ADD_NODE);
+                    }
+                    for (Iterator it = nState.getAddedPropertyNames().iterator();
+                         it.hasNext() && isGranted;) {
+                        Name propName = (Name) it.next();
+                        isGranted = accessMgr.isGranted(path, propName, Permission.SET_PROPERTY);
+                    }
+                } else {
+                    isGranted = accessMgr.isGranted(path, Permission.SET_PROPERTY);
+                }
+
+                if (!isGranted) {
+                    String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to modify item";
                     log.debug(msg);
                     throw new AccessDeniedException(msg);
                 }
@@ -640,10 +661,11 @@
         // walk through list of removed transient items and check REMOVE permission
         while (removedIter.hasNext()) {
             ItemState itemState = (ItemState) removedIter.next();
-            ItemId id = itemState.getId();
+            Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
             // check REMOVE permission
-            if (!accessMgr.isGranted(id, AccessManager.REMOVE)) {
-                String msg = itemMgr.safeGetJCRPath(id)
+            int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
+            if (!accessMgr.isGranted(path, permission)) {
+                String msg = itemMgr.safeGetJCRPath(path)
                         + ": not allowed to remove item";
                 log.debug(msg);
                 throw new AccessDeniedException(msg);

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Wed Mar 19 06:56:13 2008
@@ -195,7 +195,7 @@
             throws ItemNotFoundException, AccessDeniedException,
             RepositoryException {
         // check privileges
-        if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+        if (!canRead(id)) {
             // clear cache
             ItemImpl item = retrieveItem(id);
             if (item != null) {
@@ -217,6 +217,10 @@
         }
     }
 
+    private boolean canRead(ItemId id) throws RepositoryException {
+        return session.getAccessManager().isGranted(id, AccessManager.READ);
+    }
+
     //--------------------------------------------------< item access methods >
     /**
      * Checks whether an item exists at the specified path.
@@ -293,7 +297,7 @@
             }
 
             // check privileges
-            if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+            if (!canRead(id)) {
                 // clear cache
                 evictItem(id);
                 // item exists but the session has not been granted read access
@@ -397,7 +401,7 @@
         if (item == null) {
             // not yet in cache, need to create instance:
             // check privileges
-            if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+            if (!canRead(id)) {
                 throw new AccessDeniedException("cannot read item " + id);
             }
             // create instance of item
@@ -448,8 +452,7 @@
         if (item == null) {
             // not yet in cache, need to create instance:
             // only check privileges if state is not new
-            if (state.getStatus() != ItemState.STATUS_NEW
-                    && !session.getAccessManager().isGranted(id, AccessManager.READ)) {
+            if (state.getStatus() != ItemState.STATUS_NEW && !canRead(id)) {
                 throw new AccessDeniedException("cannot read item " + id);
             }
             // create instance of item
@@ -482,7 +485,7 @@
         while (iter.hasNext()) {
             NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
             // check read access
-            if (session.getAccessManager().isGranted(entry.getId(), AccessManager.READ)) {
+            if (canRead(entry.getId())) {
                 return true;
             }
         }
@@ -514,7 +517,7 @@
         while (iter.hasNext()) {
             NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
             // check read access
-            if (session.getAccessManager().isGranted(entry.getId(), AccessManager.READ)) {
+            if (canRead(entry.getId())) {
                 childIds.add(entry.getId());
             }
         }
@@ -546,7 +549,7 @@
         while (iter.hasNext()) {
             Name propName = (Name) iter.next();
             // check read access
-            if (session.getAccessManager().isGranted(new PropertyId(parentId, propName), AccessManager.READ)) {
+            if (canRead(new PropertyId(parentId, propName))) {
                 return true;
             }
         }
@@ -580,7 +583,7 @@
             Name propName = (Name) iter.next();
             PropertyId id = new PropertyId(parentId, propName);
             // check read access
-            if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+            if (canRead(id)) {
                 childIds.add(id);
             }
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed Mar 19 06:56:13 2008
@@ -33,9 +33,9 @@
 import org.apache.jackrabbit.core.config.ClusterConfig;
 import org.apache.jackrabbit.core.config.DataStoreConfig;
 import org.apache.jackrabbit.core.config.FileSystemConfig;
-import org.apache.jackrabbit.core.config.LoginModuleConfig;
 import org.apache.jackrabbit.core.config.PersistenceManagerConfig;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.SecurityManagerConfig;
 import org.apache.jackrabbit.core.config.VersioningConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
 import org.apache.jackrabbit.core.data.DataStore;
@@ -52,24 +52,37 @@
 import org.apache.jackrabbit.core.observation.ObservationDispatcher;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
-import org.apache.jackrabbit.core.security.AuthContext;
+import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
 import org.apache.jackrabbit.core.state.CacheManager;
 import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ISMLocking;
 import org.apache.jackrabbit.core.state.ItemStateCacheFactory;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.ManagedMLRUItemStateCacheFactory;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
-import org.apache.jackrabbit.core.state.ISMLocking;
 import org.apache.jackrabbit.core.util.RepositoryLock;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
 
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+import javax.security.auth.Subject;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -86,19 +99,6 @@
 import java.util.Properties;
 import java.util.Set;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
-import javax.jcr.observation.ObservationManager;
-import javax.security.auth.Subject;
-
 /**
  * A <code>RepositoryImpl</code> ...
  */
@@ -150,6 +150,11 @@
     private final VirtualNodeTypeStateManager virtNTMgr;
 
     /**
+     * Security manager
+     */
+    private JackrabbitSecurityManager securityMgr;
+
+    /**
      * Search manager for the jcr:system tree. May be <code>null</code> if
      * none is configured.
      */
@@ -376,6 +381,36 @@
     }
 
     /**
+     * Returns the {@link org.apache.jackrabbit.core.security.JackrabbitSecurityManager SecurityManager}
+     * of this <code>Repository</code>
+     *
+     * @return the security manager
+     * @throws RepositoryException if an error occurs.
+     */
+    protected synchronized JackrabbitSecurityManager getSecurityManager()
+            throws RepositoryException {
+
+        if (securityMgr == null) {
+            SecurityManagerConfig smc = getConfig().getSecurityConfig().getSecurityManagerConfig();
+
+            String workspaceName = smc.getWorkspaceName();
+            if (workspaceName == null) {
+                workspaceName = getConfig().getDefaultWorkspaceName();
+            }
+            SystemSession securitySession = getSystemSession(workspaceName);
+            // mark system session as 'active' for that the system workspace does
+            // not get disposed by workspace-janitor
+            onSessionCreated(securitySession);
+
+            securityMgr = (JackrabbitSecurityManager) smc.newInstance();
+            securityMgr.init(this, securitySession);
+
+            log.info("SecurityManager = " + securityMgr.getClass());
+        }
+        return securityMgr;
+    }
+
+    /**
      * Creates the version manager.
      *
      * @param vConfig the versioning config
@@ -412,8 +447,13 @@
      */
     protected void initStartupWorkspaces() throws RepositoryException {
         String wspName = repConfig.getDefaultWorkspaceName();
+        String secWspName = repConfig.getSecurityConfig().getSecurityManagerConfig().getWorkspaceName();
         try {
             initWorkspace((WorkspaceInfo) wspInfos.get(wspName));
+            if(secWspName != null && !wspInfos.containsKey(secWspName)) {
+                createWorkspace(secWspName);
+                log.info("created system workspace: {}", secWspName);
+            }
         } catch (RepositoryException e) {
             // if default workspace failed to initialize, shutdown again
             log.error("Failed to initialize workspace '" + wspName + "'", e);
@@ -578,7 +618,7 @@
         /**
          * todo implement 'System' workspace
          * FIXME
-         * - the should be one 'System' workspace per repository
+         * - there should be one 'System' workspace per repository
          * - the 'System' workspace should have the /jcr:system node
          * - versions, version history and node types should be reflected in
          *   this system workspace as content under /jcr:system
@@ -939,6 +979,57 @@
         }
     }
 
+    /**
+     * Tries to add Principals to a given subject:
+     * First Access the Subject from the current AccessControlContext,
+     * If Subject is found the LoginContext is evoked for it, in order
+     * to possibly allow for extension of preauthenticated Subject.<br>
+     * In contrast to a login with Credentials, a Session is created, even if the
+     * Authentication failed.<br>
+     * If the {@link Subject} is marked to be unmodificable or if the
+     * authentication of the the Subject failed Session is build for unchanged
+     * Subject.
+     *
+     * @param workspaceName must not be null
+     * @return if a Subject is exsting null else
+     * @throws RepositoryException
+     * @throws AccessDeniedException
+     */
+    private Session extendAuthentication(String workspaceName)
+            throws RepositoryException, AccessDeniedException {
+
+        Subject subject = null;
+        try {
+            AccessControlContext acc = AccessController.getContext();
+            subject = Subject.getSubject(acc);
+        } catch (SecurityException e) {
+            log.warn("Can't check for preauthentication. Reason:", e.getMessage());
+        }
+        if (subject == null) {
+            log.debug("No preauthenticated subject found -> return null.");
+            return null;
+        }
+
+        Session s;
+        if (subject.isReadOnly()) {
+            log.debug("Preauthenticated Subject is read-only -> create Session");
+            s = createSession(subject, workspaceName);
+        } else {
+            log.debug("Found preauthenticated Subject, try to extend authentication");
+            // login either using JAAS or custom LoginModule
+            AuthContext authCtx = getSecurityManager().getAuthContext(null, subject);
+            try {
+                authCtx.login();
+                s = createSession(authCtx, workspaceName);
+            } catch (javax.security.auth.login.LoginException e) {
+                // subject could not be extended
+                log.debug("Preauthentication could not be extended");
+                s = createSession(subject, workspaceName);
+            }
+        }
+        return s;
+    }
+
     //-------------------------------------------------< JackrabbitRepository >
 
     /**
@@ -975,6 +1066,10 @@
             clusterNode.stop();
         }
 
+        if (securityMgr != null) {
+            securityMgr.close();
+        }
+
         // close active user sessions
         // (copy sessions to array to avoid ConcurrentModificationException;
         // manually copy entries rather than calling ReferenceMap#toArray() in
@@ -1236,30 +1331,24 @@
             getWorkspaceInfo(workspaceName);
 
             if (credentials == null) {
-                // null credentials, obtain the identity of the already-authenticated
+                // try to obtain the identity of the already authenticated
                 // subject from access control context
-                AccessControlContext acc = AccessController.getContext();
-                Subject subject = Subject.getSubject(acc);
-                if (subject != null) {
-                    return createSession(subject, workspaceName);
+                Session session = extendAuthentication(workspaceName);
+                if (session != null) {
+                    // sucessful extended authentication
+                    return session;
+                } else {
+                    log.debug("Attempt to login without Credentials and Subject -> try login with null credentials.");
                 }
             }
-            // login either using JAAS or our own LoginModule
-            AuthContext authCtx;
-            LoginModuleConfig lmc = repConfig.getLoginModuleConfig();
-            if (lmc == null) {
-                authCtx = new AuthContext.JAAS(repConfig.getAppName(), credentials);
-            } else {
-                authCtx = new AuthContext.Local(
-                        lmc.getLoginModule(), lmc.getParameters(), credentials);
-            }
+            // not preauthenticated -> try login with credentials
+            AuthContext authCtx = getSecurityManager().getAuthContext(credentials, new Subject());
             authCtx.login();
-
             // create session
             return createSession(authCtx, workspaceName);
+
         } catch (SecurityException se) {
-            throw new LoginException(
-                    "Unable to access authentication information", se);
+            throw new LoginException("Unable to access authentication information", se);
         } catch (javax.security.auth.login.LoginException le) {
             throw new LoginException(le.getMessage(), le);
         } catch (AccessDeniedException ade) {
@@ -1873,6 +1962,12 @@
                 searchMgr.close();
                 searchMgr = null;
             }
+
+            // deregister
+            if (securityMgr != null) {
+                securityMgr.dispose(getName());
+            }
+
 
             // close system session
             if (systemSession != null) {

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,120 @@
+/*
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
+import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
+
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.Property;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.version.VersionException;
+import javax.jcr.lock.LockException;
+
+/**
+ * <code>SecurityItemModifier</code>: An abstract helper class to allow classes
+ * of the security API residing outside of the core package to modify and remove
+ * protected items for security. The protected item definitions are required in
+ * order not to have security relevant content being changed through common
+ * item operations but forcing the usage of the security API. The latter asserts
+ * that implementation specific constraints are not violated.
+ */
+public abstract class SecurityItemModifier {
+
+    private static Logger log = LoggerFactory.getLogger(SecurityItemModifier.class);
+
+    protected SecurityItemModifier() {
+        Class cl = getClass();
+        if (!(cl.equals(UserManagerImpl.class) ||
+              cl.equals(ACLEditor.class) ||
+              cl.getSuperclass().equals(ACLEditor.class))) {
+            throw new IllegalArgumentException("Only UserManagerImpl and ACLEditor may extend from the SecurityItemModifier");
+        }
+    }
+
+    protected NodeImpl addSecurityNode(NodeImpl parentImpl, Name name, Name ntName) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+        synchronized (parentImpl) {
+            // validation: make sure Node is not locked or checked-in.
+            parentImpl.checkSetProperty();
+
+            NodeTypeImpl nodeType = parentImpl.session.getNodeTypeManager().getNodeType(ntName);
+            NodeDefinitionImpl def = parentImpl.getApplicableChildNodeDefinition(name, ntName);
+
+            // check for name collisions
+            // TODO: improve. copied from NodeImpl
+            NodeState thisState = (NodeState) parentImpl.getItemState();
+            NodeState.ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1);
+            if (cne != null) {
+                // there's already a child node entry with that name;
+                // check same-name sibling setting of new node
+                if (!def.allowsSameNameSiblings()) {
+                    throw new ItemExistsException();
+                }
+                // check same-name sibling setting of existing node
+                NodeId newId = cne.getId();
+                NodeImpl n = (NodeImpl) parentImpl.session.getItemManager().getItem(newId);
+                if (!n.getDefinition().allowsSameNameSiblings()) {
+                    throw new ItemExistsException();
+                }
+            }
+
+            return parentImpl.createChildNode(name, def, nodeType, null);
+        }
+    }
+
+    protected Property setSecurityProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+        synchronized (parentImpl) {
+            // validation: make sure Node is not locked or checked-in.
+            parentImpl.checkSetProperty();
+            InternalValue intVs = InternalValue.create(value, parentImpl.session.getNamePathResolver());
+            return parentImpl.internalSetProperty(name, intVs);
+        }
+    }
+
+    protected Property setSecurityProperty(NodeImpl parentImpl, Name name, Value[] values) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+        synchronized (parentImpl) {
+            // validation: make sure Node is not locked or checked-in.
+            parentImpl.checkSetProperty();
+            InternalValue[] intVs = new InternalValue[values.length];
+            for (int i = 0; i < values.length; i++) {
+                intVs[i] = InternalValue.create(values[i], parentImpl.session.getNamePathResolver());
+            }
+            return parentImpl.internalSetProperty(name, intVs);
+        }
+    }
+
+    protected void removeSecurityItem(ItemImpl itemImpl) throws LockException, VersionException, AccessDeniedException, ItemNotFoundException, RepositoryException {
+        NodeImpl n = (itemImpl.isNode()) ? (NodeImpl) itemImpl : (NodeImpl) itemImpl.getParent();
+        synchronized (n) {
+            // validation: make sure Node is not locked or checked-in.
+            n.checkSetProperty();
+            itemImpl.internalRemove(true);
+        }
+    }
+}
\ No newline at end of file

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

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

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Wed Mar 19 06:56:13 2008
@@ -20,7 +20,6 @@
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.commons.AbstractSession;
 import org.apache.jackrabbit.core.RepositoryImpl.WorkspaceInfo;
-import org.apache.jackrabbit.core.config.AccessManagerConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
 import org.apache.jackrabbit.core.data.GarbageCollector;
 import org.apache.jackrabbit.core.lock.LockManager;
@@ -31,8 +30,13 @@
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
 import org.apache.jackrabbit.core.security.AMContext;
 import org.apache.jackrabbit.core.security.AccessManager;
-import org.apache.jackrabbit.core.security.AuthContext;
 import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
 import org.apache.jackrabbit.core.state.NodeState;
@@ -80,8 +84,8 @@
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.ValueFactory;
 import javax.jcr.Workspace;
-import javax.jcr.lock.Lock;
 import javax.jcr.lock.LockException;
+import javax.jcr.lock.Lock;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.observation.EventListener;
@@ -91,7 +95,6 @@
 import java.io.File;
 import java.io.PrintStream;
 import java.security.AccessControlException;
-import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -99,21 +102,34 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.Arrays;
 
 /**
  * A <code>SessionImpl</code> ...
  */
 public class SessionImpl extends AbstractSession
-        implements NamePathResolver, Dumpable {
+        implements JackrabbitSession, NamePathResolver, Dumpable {
 
     private static Logger log = LoggerFactory.getLogger(SessionImpl.class);
 
     /**
-     * prededfined action constants in checkPermission
+     * TODO deprecate as soon as present with Session interface (JSR 283)
      */
     public static final String READ_ACTION = "read";
+
+    /**
+     * TODO deprecate as soon as present with Session interface (JSR 283)
+     */
     public static final String REMOVE_ACTION = "remove";
+
+    /**
+     * TODO deprecate as soon as present with Session interface (JSR 283)
+     */
     public static final String ADD_NODE_ACTION = "add_node";
+
+    /**
+     * TODO deprecate as soon as present with Session interface (JSR 283)
+     */
     public static final String SET_PROPERTY_ACTION = "set_property";
 
     /**
@@ -208,6 +224,16 @@
     protected ValueFactory valueFactory;
 
     /**
+     * Principal Manager
+     */
+    private PrincipalManager principalManager;
+
+    /**
+     * User Manager
+     */
+    private UserManager userManager;
+
+    /**
      * Protected constructor.
      *
      * @param rep
@@ -240,17 +266,26 @@
             throws AccessDeniedException, RepositoryException {
         alive = true;
         this.rep = rep;
-        Set principals = subject.getPrincipals();
-        if (principals.isEmpty()) {
-            String msg = "unable to instantiate Session: no principals found";
-            log.error(msg);
-            throw new RepositoryException(msg);
-        } else {
-            // use 1st principal in case there are more that one
-            Principal principal = (Principal) principals.iterator().next();
-            userId = principal.getName();
-        }
         this.subject = subject;
+
+        /*
+         Retrieve userID from the subject.
+         Since the subject may contain multiple principals and the principal
+         name must not be equals to the UserID by definition, the proper way
+         is to check for known credentials the provide the correct userID.
+         The specification explicitely defines the UserID to be related to
+         the credentials and allows 'null' values in case the credentials do
+         not reveal a userID.
+         TODO: eval alternative approach via UserManager
+        */
+        String uid = null;
+        Iterator creds = subject.getPublicCredentials(SimpleCredentials.class).iterator();
+        if (creds.hasNext()) {
+            SimpleCredentials sc = (SimpleCredentials) creds.next();
+            uid = sc.getUserID();
+        }
+        userId = uid;
+
         nsMappings = new LocalNamespaceMappings(rep.getNamespaceRegistry());
         namePathResolver = new DefaultNamePathResolver(nsMappings, true);
         ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), rep.getNamespaceRegistry(), getNamespaceResolver(), getNamePathResolver(), rep.getDataStore());
@@ -323,27 +358,15 @@
     protected AccessManager createAccessManager(Subject subject,
                                                 HierarchyManager hierMgr)
             throws AccessDeniedException, RepositoryException {
-        AccessManagerConfig amConfig = rep.getConfig().getAccessManagerConfig();
-        try {
-
-            AMContext ctx = new AMContext(new File(rep.getConfig().getHomeDir()),
-                    rep.getFileSystem(),
-                    subject,
-                    hierMgr,
-                    rep.getNamespaceRegistry(),
-                    wsp.getName());
-            AccessManager accessMgr = (AccessManager) amConfig.newInstance();
-            accessMgr.init(ctx);
-            return accessMgr;
-        } catch (AccessDeniedException ade) {
-            // re-throw
-            throw ade;
-        } catch (Exception e) {
-            // wrap in RepositoryException
-            String msg = "failed to instantiate AccessManager implementation: " + amConfig.getClassName();
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
-        }
+        String wspName = getWorkspace().getName();
+        AMContext ctx = new AMContext(new File(rep.getConfig().getHomeDir()),
+                rep.getFileSystem(),
+                this,
+                getSubject(),
+                getItemStateManager().getAtticAwareHierarchyMgr(),
+                getNamePathResolver(),
+                wspName);
+        return rep.getSecurityManager().getAccessManager(this, ctx);
     }
 
     /**
@@ -365,11 +388,39 @@
      *
      * @return the <code>Subject</code> associated with this session
      */
-    protected Subject getSubject() {
+    public Subject getSubject() {
         return subject;
     }
 
     /**
+      * Creates a new session with the same subject as this sessions but to a
+      * different workspace. The returned session is a newly logged in session,
+      * with the same subject but a different workspace. Even if the given
+      * workspace is the same as this sessions one, the implementation must
+      * return a new session object.
+      *
+      * @param workspaceName name of the workspace to acquire a session for.
+      * @return A session to the requested workspace for the same authenticated
+      *         subject.
+      * @throws AccessDeniedException in case the current Subject is not allowed
+      *         to access the requested Workspace
+      * @throws NoSuchWorkspaceException If the named workspace does not exist.
+      * @throws RepositoryException in any other exceptional state
+      */
+    public Session createSession(String workspaceName)
+            throws AccessDeniedException, NoSuchWorkspaceException, RepositoryException {
+
+        if (workspaceName == null) {
+            workspaceName = rep.getConfig().getDefaultWorkspaceName();
+        }
+        if (loginContext!=null) {
+            return rep.createSession(loginContext, workspaceName);
+        } else {
+            return rep.createSession(getSubject(), workspaceName);
+        }
+    }
+
+    /**
      * Returns the <code>AccessManager</code> associated with this session.
      *
      * @return the <code>AccessManager</code> associated with this session
@@ -649,134 +700,35 @@
         return namePathResolver.getQPath(path);
     }
 
-    //--------------------------------------------------------------< Session >
+    //----------------------------------------------------< JackrabbitSession >
     /**
-     * {@inheritDoc}
+     * @see JackrabbitSession#getPrincipalManager()
      */
-    public void checkPermission(String absPath, String actions)
-            throws AccessControlException, RepositoryException {
-        // check sanity of this session
-        sanityCheck();
-
-        // build the set of actions to be checked
-        String[] strings = actions.split(",");
-        HashSet set = new HashSet();
-        for (int i = 0; i < strings.length; i++) {
-            set.add(strings[i]);
-        }
-
-        Path targetPath;
-        try {
-            targetPath = getQPath(absPath).getNormalizedPath();
-        } catch (NameException e) {
-            String msg = "invalid path: " + absPath;
-            log.debug(msg, e);
-            throw new RepositoryException(msg, e);
-        }
-        if (!targetPath.isAbsolute()) {
-            throw new RepositoryException("not an absolute path: " + absPath);
-        }
-
-        ItemId targetId = null;
-
-        /**
-         * "read" action:
-         * requires READ permission on target item
-         */
-        if (set.contains(READ_ACTION)) {
-            try {
-                targetId = hierMgr.resolvePath(targetPath);
-                if (targetId == null) {
-                    // target does not exist, throw exception
-                    throw new AccessControlException(READ_ACTION);
-                }
-                accessMgr.checkPermission(targetId, AccessManager.READ);
-            } catch (AccessDeniedException re) {
-                // otherwise the RepositoryException catch clause will
-                // log a warn message, which is not appropriate in this case.
-                throw new AccessControlException(READ_ACTION);
-            }
-        }
-
-        Path parentPath = null;
-        ItemId parentId = null;
-
-        /**
-         * "add_node" action:
-         * requires WRITE permission on parent item
-         */
-        if (set.contains(ADD_NODE_ACTION)) {
-            try {
-                parentPath = targetPath.getAncestor(1);
-                parentId = hierMgr.resolveNodePath(parentPath);
-                if (parentId == null) {
-                    // parent does not exist (i.e. / was specified), throw exception
-                    throw new AccessControlException(ADD_NODE_ACTION);
-                }
-                accessMgr.checkPermission(parentId, AccessManager.WRITE);
-            } catch (AccessDeniedException re) {
-                // otherwise the RepositoryException catch clause will
-                // log a warn message, which is not appropriate in this case.
-                throw new AccessControlException(ADD_NODE_ACTION);
-            }
+    public PrincipalManager getPrincipalManager() throws RepositoryException, AccessDeniedException {
+        if (principalManager == null) {
+            principalManager = rep.getSecurityManager().getPrincipalManager(this);
         }
+        return principalManager;
+    }
 
-        /**
-         * "remove" action:
-         * requires REMOVE permission on target item
-         */
-        if (set.contains(REMOVE_ACTION)) {
-            try {
-                if (targetId == null) {
-                    targetId = hierMgr.resolvePath(targetPath);
-                    if (targetId == null) {
-                        // parent does not exist, throw exception
-                        throw new AccessControlException(REMOVE_ACTION);
-                    }
-                }
-                accessMgr.checkPermission(targetId, AccessManager.REMOVE);
-            } catch (AccessDeniedException re) {
-                // otherwise the RepositoryException catch clause will
-                // log a warn message, which is not appropriate in this case.
-                throw new AccessControlException(REMOVE_ACTION);
-            }
+    /**
+     * @see JackrabbitSession#getUserManager()
+     */
+    public UserManager getUserManager() throws AccessDeniedException, RepositoryException {
+        if (userManager == null) {
+            userManager = rep.getSecurityManager().getUserManager(this);
         }
+        return userManager;
+    }
 
-        /**
-         * "set_property" action:
-         * requires WRITE permission on parent item if property is going to be
-         * added or WRITE permission on target item if property is going to be
-         * modified
-         */
-        if (set.contains(SET_PROPERTY_ACTION)) {
-            try {
-                if (targetId == null) {
-                    targetId = hierMgr.resolvePath(targetPath);
-                    if (targetId == null) {
-                        // property does not exist yet,
-                        // check WRITE permission on parent
-                        if (parentPath == null) {
-                            parentPath = targetPath.getAncestor(1);
-                        }
-                        if (parentId == null) {
-                            parentId = hierMgr.resolveNodePath(parentPath);
-                            if (parentId == null) {
-                                // parent does not exist, throw exception
-                                throw new AccessControlException(SET_PROPERTY_ACTION);
-                            }
-                        }
-                        accessMgr.checkPermission(parentId, AccessManager.WRITE);
-                    } else {
-                        // property does already exist,
-                        // check WRITE permission on target
-                        accessMgr.checkPermission(targetId, AccessManager.WRITE);
-                    }
-                }
-            } catch (AccessDeniedException re) {
-                // otherwise the RepositoryException catch clause will
-                // log a warn message, which is not appropriate in this case.
-                throw new AccessControlException(SET_PROPERTY_ACTION);
-            }
+    //--------------------------------------------------------------< Session >
+    /**
+     * {@inheritDoc}
+     */
+    public void checkPermission(String absPath, String actions)
+            throws AccessControlException, RepositoryException {
+        if (!hasPermission(absPath, actions)) {
+            throw new AccessControlException(actions);
         }
     }
 
@@ -1391,7 +1343,7 @@
      *         absolute path.
      * @since JCR 2.0
      */
-    boolean propertyExists(String absPath) throws RepositoryException {
+    public boolean propertyExists(String absPath) throws RepositoryException {
         // check sanity of this session
         sanityCheck();
 
@@ -1405,6 +1357,69 @@
             String msg = "invalid path:" + absPath;
             log.debug(msg);
             throw new RepositoryException(msg, e);
+        }
+    }
+
+    /**
+     * @see Session#hasPermission(String, String)
+     * @since 2.0
+     */
+    public boolean hasPermission(String absPath, String actions) throws RepositoryException {
+        // check sanity of this session
+        sanityCheck();
+        Path path = getQPath(absPath).getNormalizedPath();
+        // test if path is absolute
+        if (!path.isAbsolute()) {
+            throw new RepositoryException("Absolute path expected. Was:" + absPath);
+        }
+
+        Set s = new HashSet(Arrays.asList(actions.split(",")));
+        int permissions = 0;
+        if (s.remove(SessionImpl.READ_ACTION)) {
+            permissions |= Permission.READ;
+        }
+        if (s.remove(SessionImpl.ADD_NODE_ACTION)) {
+            permissions |= Permission.ADD_NODE;
+        }
+        if (s.remove(SessionImpl.SET_PROPERTY_ACTION)) {
+            permissions |= Permission.SET_PROPERTY;
+        }
+        if (s.remove(SessionImpl.REMOVE_ACTION)) {
+            if (nodeExists(absPath)) {
+                permissions |= (propertyExists(absPath)) ?
+                        (Permission.REMOVE_NODE | Permission.REMOVE_PROPERTY) :
+                        Permission.REMOVE_NODE;
+            } else if (propertyExists(absPath)) {
+                permissions |= Permission.REMOVE_PROPERTY;
+            } else {
+                // item does exist -> check both permissions
+                permissions = Permission.REMOVE_NODE | Permission.REMOVE_PROPERTY;
+            }
+        }
+        if (!s.isEmpty()) {
+            StringBuffer sb = new StringBuffer();
+            for (Iterator it = s.iterator(); it.hasNext();) {
+                sb.append(it.next());
+            }
+            throw new IllegalArgumentException("Unknown actions: " + sb.toString());
+        }
+        try {
+            return getAccessManager().isGranted(path, permissions);
+        } catch (AccessDeniedException e) {
+            return false;
+        }
+    }
+
+    /**
+     * @see Session#getAccessControlManager()
+     * @since 2.0
+     */
+    public AccessControlManager getAccessControlManager()
+            throws UnsupportedRepositoryOperationException, RepositoryException {
+        if (accessMgr instanceof AccessControlManager) {
+            return (AccessControlManager) accessMgr;
+        } else {
+            throw new UnsupportedRepositoryOperationException("Access control discovery is not supported.");
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Wed Mar 19 06:56:13 2008
@@ -20,6 +20,10 @@
 import org.apache.jackrabbit.core.security.AMContext;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.SystemPrincipal;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Name;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.ItemNotFoundException;
@@ -84,7 +88,6 @@
          * correctly
          */
         return new SystemAccessManager();
-        //return super.createAccessManager(subject, hierMgr);
     }
 
     //--------------------------------------------------------< inner classes >
@@ -105,6 +108,10 @@
             // nop
         }
 
+        public void init(AMContext context, AccessControlProvider acProvider, WorkspaceAccessManager wspAccessMgr) throws AccessDeniedException, Exception {
+            // nop
+        }
+
         /**
          * {@inheritDoc}
          */
@@ -134,6 +141,26 @@
          */
         public boolean isGranted(ItemId id, int permissions)
                 throws ItemNotFoundException, RepositoryException {
+            // allow everything
+            return true;
+        }
+
+        /**
+         * Always returns true.
+         *
+         * @see AccessManager#isGranted(Path, int)
+         */
+        public boolean isGranted(Path absPath, int permissions) throws RepositoryException {
+            // allow everything
+            return true;
+        }
+
+        /**
+         * Always returns true.
+         *
+         * @see AccessManager#isGranted(Path, Name, int) 
+         */
+        public boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException {
             // allow everything
             return true;
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Wed Mar 19 06:56:13 2008
@@ -20,7 +20,7 @@
 import org.apache.jackrabbit.core.lock.LockManager;
 import org.apache.jackrabbit.core.lock.LockManagerImpl;
 import org.apache.jackrabbit.core.lock.XALockManager;
-import org.apache.jackrabbit.core.security.AuthContext;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.state.XAItemStateManager;
 import org.apache.jackrabbit.core.version.VersionManager;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java Wed Mar 19 06:56:13 2008
@@ -23,7 +23,7 @@
  * This class is currently only used to assign a static type to
  * more generic bean configuration information.
  *
- * @see RepositoryConfig#getAccessManagerConfig()
+ * @see SecurityConfig#getAccessManagerConfig()
  */
 public class AccessManagerConfig extends BeanConfig {
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java Wed Mar 19 06:56:13 2008
@@ -29,6 +29,23 @@
  */
 public class LoginModuleConfig extends BeanConfig {
 
+    public static final String PARAM_ANONYMOUS_ID = "anonymousId";
+    public static final String PARAM_ADMIN_ID = "adminId";
+
+    /**
+     * Name of the default user id to be used upon Repository.login with
+     * <code>null</code> credentials. Optional parameter in the LoginModule
+     * configuration.
+     */
+    public static final String PARAM_DEFAULT_USERID = "defaultUserId";
+
+    /**
+     * Property-Key for the fully qualified class name of the implementation of
+     * {@link org.apache.jackrabbit.core.security.principal.PrincipalProvider}
+     * to be used with the LoginModule.
+     */
+    public static final String PARAM_PRINCIPAL_PROVIDER_CLASS = "principalprovider";
+
     /**
      * Creates an access manager configuration object from the
      * given bean configuration.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java Wed Mar 19 06:56:13 2008
@@ -634,6 +634,7 @@
      * JAAS app-entry configuration.
      *
      * @return repository name
+     * @deprecated Use {@link SecurityConfig#getAppName()} instead.
      */
     public String getAppName() {
         return sec.getAppName();
@@ -643,6 +644,7 @@
      * Returns the repository access manager configuration.
      *
      * @return access manager configuration
+     * @deprecated Use {@link SecurityConfig#getAccessManagerConfig()} instead.
      */
     public AccessManagerConfig getAccessManagerConfig() {
         return sec.getAccessManagerConfig();
@@ -653,6 +655,7 @@
      *
      * @return login module configuration, or <code>null</code> if standard
      *         JAAS mechanism should be used.
+     * @deprecated Use {@link SecurityConfig#getLoginModuleConfig()} instead.
      */
     public LoginModuleConfig getLoginModuleConfig() {
         return sec.getLoginModuleConfig();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java Wed Mar 19 06:56:13 2008
@@ -16,14 +16,14 @@
  */
 package org.apache.jackrabbit.core.config;
 
-import java.io.File;
-import java.util.Properties;
-
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
+import java.io.File;
+import java.util.Properties;
+
 /**
  * Configuration parser. This class is used to parse the repository and
  * workspace configuration files.
@@ -55,12 +55,21 @@
     /** Name of the security configuration element. */
     public static final String SECURITY_ELEMENT = "Security";
 
+    /** Name of the security manager configuration element. */
+    public static final String SECURITY_MANAGER_ELEMENT = "SecurityManager";
+
     /** Name of the access manager configuration element. */
     public static final String ACCESS_MANAGER_ELEMENT = "AccessManager";
 
     /** Name of the login module configuration element. */
     public static final String LOGIN_MODULE_ELEMENT = "LoginModule";
 
+    /**
+     * Name of the optional WorkspaceAccessManager element defining which
+     * implementation of WorkspaceAccessManager to be used.
+     */
+    private static final String WORKSPACE_ACCESS_ELEMENT = "WorkspaceAccessManager";
+
     /** Name of the general workspace configuration element. */
     public static final String WORKSPACES_ELEMENT = "Workspaces";
 
@@ -95,6 +104,9 @@
     /** Name of the application name configuration attribute. */
     public static final String APP_NAME_ATTRIBUTE = "appName";
 
+    /** Name of the workspace conaining security data. */
+    public static final String WSP_NAME_ATTRIBUTE = "workspaceName";
+
     /** Name of the root path configuration attribute. */
     public static final String ROOT_PATH_ATTRIBUTE = "rootPath";
 
@@ -124,6 +136,15 @@
     /** Default synchronization delay, in milliseconds. */
     public static final String DEFAULT_SYNC_DELAY = "5000";
 
+    /** Name of the workspace specific security configuration element */
+    private static final String WSP_SECURITY_ELEMENT = "WorkspaceSecurity";
+
+    /**
+     * Name of the optional AccessControlProvider element defining which
+     * implementation of AccessControlProvider should be used.
+     */
+    private static final String AC_PROVIDER_ELEMENT = "AccessControlProvider";
+
     /**
      * Creates a new configuration parser with the given parser variables.
      *
@@ -140,6 +161,7 @@
      *   &lt;Repository&gt;
      *     &lt;FileSystem ...&gt;
      *     &lt;Security appName="..."&gt;
+     *       &lt;SecurityManager ...&gt;
      *       &lt;AccessManager ...&gt;
      *       &lt;LoginModule ... (optional)&gt;
      *     &lt;/Security&gt;
@@ -236,13 +258,15 @@
      * uses the following format:
      * <pre>
      *   &lt;Security appName="..."&gt;
+     *     &lt;SecurityManager ...&gt;
      *     &lt;AccessManager ...&gt;
      *     &lt;LoginModule ... (optional)&gt;
      *   &lt;/Security&gt;
      * </pre>
      * <p/>
-     * Both the <code>AccessManager</code> and <code>LoginModule</code>
-     * elements are {@link #parseBeanConfig(Element,String) bean configuration}
+     * The <code>SecurityManager</code>, the <code>AccessManager</code>
+     * and <code>LoginModule</code> are all
+     * {@link #parseBeanConfig(Element,String) bean configuration}
      * elements.
      * <p/>
      * The login module is an optional feature of repository configuration.
@@ -254,9 +278,35 @@
     public SecurityConfig parseSecurityConfig(Element security)
             throws ConfigurationException {
         String appName = getAttribute(security, APP_NAME_ATTRIBUTE);
+
+        SecurityManagerConfig smc = parseSecurityManagerConfig(security);
         AccessManagerConfig amc = parseAccessManagerConfig(security);
         LoginModuleConfig lmc = parseLoginModuleConfig(security);
-        return new SecurityConfig(appName, amc, lmc);
+
+        return new SecurityConfig(appName, smc, amc, lmc);
+    }
+
+    /**
+     * Parses the security manager configuration.
+     *
+     * @param security the &lt;security> element.
+     * @return the security manager configuration.
+     * @throws ConfigurationException if the configuration is broken
+     */
+    public SecurityManagerConfig parseSecurityManagerConfig(Element security)
+            throws ConfigurationException {
+
+        BeanConfig bc = parseBeanConfig(security, SECURITY_MANAGER_ELEMENT);
+
+        Element smElement = getElement(security, SECURITY_MANAGER_ELEMENT);
+        String wspAttr = getAttribute(smElement, WSP_NAME_ATTRIBUTE, null);
+
+        BeanConfig wac = null;
+        Element element = getElement(smElement, WORKSPACE_ACCESS_ELEMENT, false);
+        if (element != null) {
+            wac = parseBeanConfig(smElement, WORKSPACE_ACCESS_ELEMENT);
+        }
+        return new SecurityManagerConfig(bc, wspAttr, wac);
     }
 
     /**
@@ -300,6 +350,8 @@
      *     &lt;PersistenceManager ...&gt;
      *     &lt;SearchIndex ...&gt;
      *     &lt;ISMLocking ...&gt;
+     *     &lt;WorkspaceSecurity ...&gt;
+     *     &lt;ISMLocking ...&gt;
      *   &lt;/Workspace&gt;
      * </pre>
      * <p>
@@ -337,6 +389,7 @@
      * @throws ConfigurationException if the configuration is broken
      * @see #parseBeanConfig(Element, String)
      * @see #parseSearchConfig(Element)
+     * @see #parseWorkspaceSecurityConfig(Element)
      */
     public WorkspaceConfig parseWorkspaceConfig(InputSource xml)
             throws ConfigurationException {
@@ -371,7 +424,10 @@
         // Item state manager locking configuration (optional)
         ISMLockingConfig ismLockingConfig = tmpParser.parseISMLockingConfig(root);
 
-        return new WorkspaceConfig(home, name, clustered, fsc, pmc, sc, ismLockingConfig);
+        // workspace specific security configuration
+        WorkspaceSecurityConfig workspaceSecurityConfig = tmpParser.parseWorkspaceSecurityConfig(root);
+
+        return new WorkspaceConfig(home, name, clustered, fsc, pmc, sc, ismLockingConfig, workspaceSecurityConfig);
     }
 
     /**
@@ -430,6 +486,34 @@
         return null;
     }
 
+
+    /**
+     * Read the WorkspaceSecurity Element of Workspace's configuration. It uses
+     * the following format:
+     * <pre>
+     *   &lt;WorkspaceSecurity&gt;
+     *     &lt;AccessControlProvider class="..." (optional)&gt;
+     *   &lt;/WorkspaceSecurity&gt;
+     * </pre>
+     *
+     * @param parent Workspace-Root-Element
+     * @return
+     * @throws ConfigurationException
+     */
+    public WorkspaceSecurityConfig parseWorkspaceSecurityConfig(Element parent)
+        throws ConfigurationException {
+
+        BeanConfig factConf = null;
+        Element element = getElement(parent, WSP_SECURITY_ELEMENT, false);
+        if (element != null) {
+            Element provFact = getElement(element, AC_PROVIDER_ELEMENT, false);
+            if (provFact !=null ) {
+                factConf = parseBeanConfig(element, AC_PROVIDER_ELEMENT);
+            }
+        }
+        return new WorkspaceSecurityConfig(factConf);
+    }
+
     /**
      * Parses ism locking configuration. ism locking configuration  uses the
      * following format:
@@ -587,7 +671,7 @@
      * <code>DataStore</code> is a {@link #parseBeanConfig(Element,String) bean configuration}
      * element.
      *
-     * @param cluster parent cluster element
+     * @param parent cluster element
      * @return journal configuration, or <code>null</code>
      * @throws ConfigurationException if the configuration is broken
      */

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java Wed Mar 19 06:56:13 2008
@@ -28,6 +28,11 @@
     private final String name;
 
     /**
+     * Repository security manager configuration;
+     */
+    private final SecurityManagerConfig smc;
+
+    /**
      * Repository access manager configuration;
      */
     private final AccessManagerConfig amc;
@@ -41,12 +46,16 @@
      * Creates a new security configuration.
      *
      * @param name repository name for a JAAS app-entry configuration
+     * @param smc security manager configuration
      * @param amc access manager configuration
      * @param lmc login module configuration (can be <code>null</code>)
      */
     public SecurityConfig(
-            String name, AccessManagerConfig amc, LoginModuleConfig lmc) {
+            String name,
+            SecurityManagerConfig smc,
+            AccessManagerConfig amc, LoginModuleConfig lmc) {
         this.name = name;
+        this.smc = smc;
         this.amc = amc;
         this.lmc = lmc;
     }
@@ -59,6 +68,15 @@
      */
     public String getAppName() {
         return name;
+    }
+
+    /**
+     * Returns the repository security manager configuration.
+     *
+     * @return access manager configuration
+     */
+    public SecurityManagerConfig getSecurityManagerConfig() {
+        return smc;
     }
 
     /**

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+/**
+ * Security manager configuration. This bean configuration class
+ * is used to create configured security manager objects.
+ * <p>
+ * This class is currently only used to assign a static type to
+ * more generic bean configuration information.
+ *
+ * @see SecurityConfig#getSecurityManagerConfig()
+ */
+public class SecurityManagerConfig extends BeanConfig {
+
+    private final String workspaceName;
+    private final BeanConfig workspaceAccessConfig; 
+
+    /**
+     * Creates an security manager configuration object from the
+     * given bean configuration.
+     *
+     * @param config bean configuration
+     */
+    public SecurityManagerConfig(BeanConfig config, String workspaceName,
+                                 BeanConfig workspaceAccessConfig) {
+        super(config);
+        this.workspaceName = workspaceName;
+        this.workspaceAccessConfig = workspaceAccessConfig;
+    }
+
+    /**
+     * Returns the name of the 'workspaceName' attribute or <code>null</code>
+     * if the SecurityManager does not require an extra workspace.
+     *
+     * @return
+     */
+    public String getWorkspaceName() {
+        return workspaceName;
+    }
+
+    /**
+     * @return the configuration for the <code>WorkspaceAccessManager</code>.
+     * May be <code>null</code> if the configuration entry is missing (i.e.
+     * the system default should be used).
+     */
+    public BeanConfig getWorkspaceAccessConfig() {
+        return workspaceAccessConfig;
+    }
+}

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

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



Mime
View raw message