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 [8/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...

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalIterator.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalIterator.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalIterator.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,89 @@
+/*
+ * 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.principal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+
+import java.security.Principal;
+import java.util.NoSuchElementException;
+
+/**
+ * Lazy implementation of the <code>PrincipalIterator</code> that allows to
+ * avoid determing all elements of the iteration beforehand.
+ * NOTE: Subclasses must call {#link seekNext()}
+ * upon object construction and assign the value to the 'next' field.
+ */
+abstract class AbstractPrincipalIterator implements PrincipalIterator {
+
+    private static Logger log = LoggerFactory.getLogger(AbstractPrincipalIterator.class);
+
+    long size;
+    long position;
+    Principal next;
+
+    AbstractPrincipalIterator() {
+        size = -1;
+        position = 0;
+    }
+
+    /**
+     * Subclasses must call {#link seekNext()} upon object construction and
+     * assign the value to the 'next' field.
+     */
+    abstract Principal seekNext();
+
+    //--------------------------------------------------< PrincipalIterator >---
+    public Principal nextPrincipal() {
+        Principal p = next;
+        if (p == null) {
+            throw new NoSuchElementException();
+        }
+        next = seekNext();
+        position++;
+        return p;
+    }
+
+    //------------------------------------------------------< RangeIterator >---
+    public void skip(long skipNum) {
+        while (skipNum-- > 0) {
+            next();
+        }
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public long getPosition() {
+        return position;
+    }
+
+    //-----------------------------------------------------------< Iterator >---
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    public Object next() {
+        return nextPrincipal();
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,129 @@
+/*
+ * 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.principal;
+
+import org.apache.commons.collections.map.LRUMap;
+
+import java.security.Principal;
+import java.util.Properties;
+
+/**
+ * A base class of a principal provider implementing common tasks and a
+ * caching facility. Extending classes should only deal with the retrieval of
+ * {@link Principal}s from their source, the caching of the principials is done
+ * by this implementation.
+ * <p/>
+ * The {@link PrincipalProvider} mehtods that that involve searching like
+ * {@link PrincipalProvider#getGroupMembership(Principal)} are not cached.
+ */
+public abstract class AbstractPrincipalProvider implements PrincipalProvider {
+
+    /** Option name for the max size of the cache to use */
+    public static final String MAXSIZE_KEY = "cacheMaxSize";
+
+    /** flag indicating if the instance has not been {@link #close() closed} */
+    private boolean initialized;
+
+    /** the principal cache */
+    private LRUMap cache;
+
+    /**
+     * Create a new instance of <code>AbstractPrincipalProvider</code>.
+     * Initialization and cache are set up upon {@link #init(Properties)}
+     */
+    protected AbstractPrincipalProvider() {
+    }
+
+    /**
+     * Check if the instance has been closed {@link #close()}.
+     *
+     * @throws IllegalStateException if this instance was closed.
+     */
+    protected void checkInitialized() {
+        if (!initialized) {
+            throw new IllegalStateException("Not initialized.");
+        }
+    }
+
+    /**
+     * Clear the principal cache.
+     */
+    protected synchronized void clearCache() {
+        cache.clear();
+    }
+
+    /**
+     * Called if the cache does not contain the principal requested.<br>
+     * Implementations should return a {@link Principal} from their source,
+     * if it contains one for the given name or <code>null</code>.
+     *
+     * @param principalName
+     * @return Principal or null, if non provided for the given name
+     * @see #getPrincipal(String)
+     */
+    protected abstract Principal providePrincipal(String principalName);
+
+    //--------------------------------------------------< PrincipalProvider >---
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasPrincipal(String principalName) {
+        return getPrincipal(principalName) != null;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * {@link #providePrincipal(String)} is called, if no principal with the
+     * given name is present in the cache.
+     */
+    public synchronized Principal getPrincipal(String principalName) {
+        checkInitialized();
+        Principal principal = (Principal) cache.get(principalName);
+        if (principal == null) {
+            principal = providePrincipal(principalName);
+            if (principal != null) {
+                cache.put(principalName, principal);
+            }
+        }
+        return principal;
+    }
+
+    /**
+     * @see PrincipalProvider#init(java.util.Properties)
+     */
+    public synchronized void init(Properties options) {
+        if (initialized) {
+            throw new IllegalStateException("already initialized");
+        }
+
+        int maxSize = Integer.parseInt(options.getProperty(MAXSIZE_KEY, "1000"));
+        cache = new LRUMap(maxSize);
+
+        initialized = true;
+    }
+
+    /**
+     * Clears the cache and calls the implementation to close their resources
+     * @see PrincipalProvider#close()
+     */
+    public synchronized void close() {
+        checkInitialized();
+        cache.clear();
+        initialized = false;
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,46 @@
+/*
+ * 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.principal;
+
+/**
+ * This principal represents the admin user as a distinct principal having all
+ * the access rights and is being authenticated (in contrast to the
+ * {@link org.apache.jackrabbit.core.security.SystemPrincipal SystemPrincipal}).
+ */
+public final class AdminPrincipal implements JackrabbitPrincipal {
+
+    private final String adminId;
+
+    public AdminPrincipal(String adminId) {
+        if (adminId == null) {
+            throw new IllegalArgumentException("name can not be null");
+        }
+        this.adminId = adminId;
+    }
+
+    public String getName() {
+        return adminId;
+    }
+
+    public int hashCode() {
+        return adminId.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+        return obj == this || obj instanceof AdminPrincipal;
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,342 @@
+/*
+ * 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.principal;
+
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.commons.collections.set.ListOrderedSet;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+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.user.UserManagerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Provides principals for the users contained within the Repository.<p/>
+ * Each {@link Authorizable} accessible via {@link UserManager}
+ * is respected and the provider serves {@link Authorizable#getPrincipal()
+ * Principal}s retrieved from those <code>Authorizable</code> objects.
+ * <p/>
+ * In addition this provider exposes the <i>everyone</i> principal, which has no
+ * content (user/group) represention.
+ */
+public class DefaultPrincipalProvider extends AbstractPrincipalProvider implements EventListener {
+
+    /**
+     * the default logger
+     */
+    private static Logger log = LoggerFactory.getLogger(DefaultPrincipalProvider.class);
+
+    /**
+     * a cache for group memberships: maps principal-name to a set of principals
+     * representing the members.
+     */
+    private final LRUMap membershipCache;
+
+    /**
+     * Principal-Base of this Provider
+     */
+    private final UserManagerImpl userManager;
+
+    private final EveryonePrincipal everyonePrincipal;
+
+    /**
+     * Creates a new DefaultPrincipalProvider reading the principals from the
+     * storage below the given security root node.
+     *
+     * @param securitySession for Repository Access
+     * @throws RepositoryException if an error accessing the repository occurs.
+     */
+    public DefaultPrincipalProvider(Session securitySession,
+                             UserManagerImpl userManager) throws RepositoryException {
+
+        this.userManager = userManager;
+        everyonePrincipal = EveryonePrincipal.getInstance();
+        membershipCache = new LRUMap();
+
+        // listen to any modifications for users and groups
+        securitySession.getWorkspace().getObservationManager().addEventListener(this,
+                Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED,
+                UserManagerImpl.SECURITY_ROOT_PATH,
+                true,
+                null,
+                null,
+                false);
+    }
+
+    //------------------------------------------< AbstractPrincipalProvider >---
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * This implementation uses the user and node resolver to find the
+     * appropriate nodes.
+     */
+    protected Principal providePrincipal(String principalName) {
+        // check for 'everyone'
+        if (everyonePrincipal.getName().equals(principalName)) {
+            return everyonePrincipal;
+        }
+        try {
+            Principal principal = new PrincipalImpl(principalName);
+            Authorizable ath = userManager.getAuthorizable(principal);
+            if (ath != null) {
+                return ath.getPrincipal();
+            }
+        } catch (RepositoryException e) {
+            log.error("Failed to access Authorizable for Principal " + principalName, e);
+        }
+        return null;
+    }
+
+    //--------------------------------------------------< PrincipalProvider >---
+    /**
+     * @see PrincipalProvider#findPrincipals(String)
+     */
+    public PrincipalIterator findPrincipals(String simpleFilter) {
+        return findPrincipals(simpleFilter, PrincipalManager.SEARCH_TYPE_ALL);
+    }
+
+    /**
+     * @see PrincipalProvider#findPrincipals(String, int)
+     */
+    public PrincipalIterator findPrincipals(String simpleFilter, int searchType) {
+        checkInitialized();
+        switch (searchType) {
+            case PrincipalManager.SEARCH_TYPE_GROUP:
+                return findGroupPrincipals(simpleFilter);
+            case PrincipalManager.SEARCH_TYPE_NOT_GROUP:
+                return findUserPrincipals(simpleFilter);
+            case PrincipalManager.SEARCH_TYPE_ALL:
+                PrincipalIterator[] its = new PrincipalIterator[] {
+                        findUserPrincipals(simpleFilter),
+                        findGroupPrincipals(simpleFilter)
+                };
+                return new PrincipalIteratorAdapter(new IteratorChain(its));
+            default:
+                throw new IllegalArgumentException("Invalid searchType");
+        }
+    }
+
+    /**
+     * @see PrincipalProvider#getPrincipals(int)
+     * @param searchType
+     */
+    public PrincipalIterator getPrincipals(int searchType) {
+        return findPrincipals("", searchType);
+    }
+
+    /**
+     * @see PrincipalProvider#getGroupMembership(Principal)
+     */
+    public PrincipalIterator getGroupMembership(Principal userPrincipal) {
+        checkInitialized();
+        Set mship;
+        synchronized (membershipCache) {
+            mship = (Set) membershipCache.get(userPrincipal.getName());
+            if (mship == null) {
+                mship = new ListOrderedSet();
+                // recursively collect group membership
+                collectGroupMembership(userPrincipal, mship);
+
+                // make sure everyone-group is not missing
+                if (!mship.contains(everyonePrincipal) && everyonePrincipal.isMember(userPrincipal)) {
+                    mship.add(everyonePrincipal);
+                }
+                membershipCache.put(userPrincipal.getName(), mship);
+            }
+        }
+        return new PrincipalIteratorAdapter(mship);
+
+    }
+
+    /**
+     * @see PrincipalProvider#close()
+     */
+    public synchronized void close() {
+        super.close();
+        membershipCache.clear();
+    }
+
+    /**
+     * Always returns true.
+     *
+     * @see PrincipalProvider#canReadPrincipal(javax.jcr.Session,java.security.Principal)
+     */
+    public boolean canReadPrincipal(Session session, Principal principal) {
+        checkInitialized();
+        // by default (UserAccessControlProvider) READ-privilege is granted to
+        // everybody -> omit any (expensive) checks.
+        return true;
+        /*
+        // TODO: uncomment code if it turns out that the previous assumption is problematic.
+        // check if the session is granted read to the node.
+        if (session instanceof SessionImpl) {
+            SessionImpl sImpl = (SessionImpl) session;
+            Subject subject = sImpl.getSubject();
+            if (!subject.getPrincipals(SystemPrincipal.class).isEmpty()
+                    || !subject.getPrincipals(AdminPrincipal.class).isEmpty()) {
+                return true;
+            }
+            try {
+                UserManager umgr = ((SessionImpl)session).getUserManager();
+                return umgr.getAuthorizable(principal) != null;
+            } catch (RepositoryException e) {
+                // ignore and return false
+            }
+        }
+        return false;
+        */
+    }
+
+    //------------------------------------------------------< EventListener >---
+    /**
+     * @see EventListener#onEvent(EventIterator)
+     */
+    public void onEvent(EventIterator eventIterator) {
+        // simple rule: flush all cached
+        clearCache();
+        synchronized (membershipCache) {
+            membershipCache.clear();
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Recursively collect all Group-principals the specified principal is
+     * member of.
+     *
+     * @param princ
+     * @return all Group principals the specified <code>princ</code> is member of
+     * including inherited membership.
+     */
+    private Set collectGroupMembership(Principal princ, Set membership) {
+        String princName = princ.getName();
+        if (!hasPrincipal(princName)) {
+            return Collections.EMPTY_SET;
+        }
+        try {
+            Authorizable auth = userManager.getAuthorizable(princ);
+            if (auth != null) {
+                Iterator itr = auth.memberOf();
+                while (itr.hasNext()) {
+                    Group group = (Group) itr.next();
+                    Principal groupPrinc = group.getPrincipal();
+                    if (membership.add(groupPrinc)) {
+                        membership.addAll(collectGroupMembership(groupPrinc, membership));
+                    } else {
+                        String msg = "Cyclic group membership detected with Group " + groupPrinc.getName();
+                        log.error(msg);
+                    }
+                }
+            } else {
+                log.debug("Cannot find authorizable for principal " + princ.getName());
+            }
+        } catch (RepositoryException e) {
+            log.warn("Failed to determine membership for " + princName, e.getMessage());
+        }
+        return membership;
+    }
+
+    /**
+     * @param simpleFilter
+     * @return An iterator over the main principals of the authorizables found
+     * by the user manager.
+     */
+    private PrincipalIterator findUserPrincipals(String simpleFilter) {
+        synchronized (userManager) {
+            try {
+                Iterator itr = userManager.findUsers(simpleFilter);
+                return new PrincipalIteratorImpl(itr, false);
+            } catch (RepositoryException e) {
+                log.error("Error while searching user principals.", e);
+                return PrincipalIteratorAdapter.EMPTY;
+            }
+        }
+    }
+
+    /**
+     * @param simpleFilter
+     * @return An iterator over the main principals of the authorizables found
+     * by the user manager.
+     */
+    private PrincipalIterator findGroupPrincipals(final String simpleFilter) {
+        synchronized (userManager) {
+            try {
+                Iterator itr = userManager.findGroups(simpleFilter);
+
+                // everyone will not be found by the usermanager -> extra test
+                boolean addEveryone = everyonePrincipal.getName().matches(".*"+simpleFilter+".*");
+                return new PrincipalIteratorImpl(itr, addEveryone);
+
+            } catch (RepositoryException e) {
+                log.error("Error while searching group principals.", e);
+                return PrincipalIteratorAdapter.EMPTY;
+            }
+        }
+    }
+
+    //--------------------------------------------------------< inner class >---
+    /**
+     * Extension of AbstractPrincipalIterator that retrieves the next
+     * principal from the iterator over authorizables by calling
+     * {@link Authorizable#getPrincipal()}.
+     */
+    private class PrincipalIteratorImpl extends AbstractPrincipalIterator {
+
+        private final Iterator authorizableItr;
+        private boolean addEveryone;
+
+        private PrincipalIteratorImpl(Iterator authorizableItr, boolean addEveryone) {
+            this.authorizableItr = authorizableItr;
+            this.addEveryone = addEveryone;
+
+            next = seekNext();
+        }
+
+        protected Principal seekNext() {
+            while (authorizableItr.hasNext()) {
+                try {
+                    return ((Authorizable) authorizableItr.next()).getPrincipal();
+                } catch (RepositoryException e) {
+                    // should never get here
+                    log.warn("Error while retrieving principal from group -> skip.");
+                }
+            }
+
+            if (addEveryone) {
+                addEveryone = false; // make sure iteration stops
+                return everyonePrincipal;
+            } else {
+                // end of iteration reached
+                return null;
+            }
+        }
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/EveryonePrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/EveryonePrincipal.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/EveryonePrincipal.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/EveryonePrincipal.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,67 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * The EveryonePrincipal contains all principals (excluding itself).
+ */
+public final class EveryonePrincipal implements java.security.acl.Group {
+
+    private static final String NAME = "everyone";
+    private static final EveryonePrincipal INSTANCE = new EveryonePrincipal();
+
+    private EveryonePrincipal() {}
+
+    public static EveryonePrincipal getInstance() {
+        return INSTANCE;
+    }
+    
+    //----------------------------------------------------------< Principal >---
+    public String getName() {
+        return NAME;
+    }
+
+    //--------------------------------------------------------------< Group >---
+    public boolean addMember(Principal user) {
+        return false;
+    }
+
+    public boolean removeMember(Principal user) {
+        throw new UnsupportedOperationException("Cannot remove a member from the everyone group.");
+    }
+
+    public boolean isMember(Principal member) {
+        return !member.equals(this);
+    }
+
+    public Enumeration members() {
+        throw new UnsupportedOperationException("Not implemented.");
+    }
+
+    //-------------------------------------------------------------< Object >---
+
+    public int hashCode() {
+        return NAME.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+        return obj == this || obj instanceof EveryonePrincipal;
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ItemBasedPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ItemBasedPrincipal.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ItemBasedPrincipal.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ItemBasedPrincipal.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,37 @@
+/*
+ * 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.principal;
+
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+
+/**
+ * <code>ItemBasedPrincipal</code> is a <code>Principal</code> that is
+ * persisted as item within the repository. In addition to the methods
+ * inherited from the {@link Principal} interface it therefore provides
+ * a {@link #getPath()} method.
+ */
+public interface ItemBasedPrincipal extends JackrabbitPrincipal {
+
+    /**
+     * @return the path of the {@link javax.jcr.Item} that represents this
+     * <code>Principal</code>.
+     * @throws RepositoryException If an error occurs while retrieving the
+     *                             <code>Item</code> path.
+     */
+    String getPath() throws RepositoryException;
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/JackrabbitPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/JackrabbitPrincipal.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/JackrabbitPrincipal.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/JackrabbitPrincipal.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,27 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+
+/**
+ * <code>JackrabbitPrincipal</code>
+ * Marks the principal to be the result of authentication against the repository.
+ */
+public interface JackrabbitPrincipal extends Principal {
+
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,87 @@
+/*
+ * 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.principal;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * Base class for implementations of <code>JackrabbitPrincipal</code>.
+ */
+public class PrincipalImpl implements JackrabbitPrincipal, Serializable {
+
+    /** the serial number */
+    private static final long serialVersionUID = 384040549033267804L;
+
+    /**
+     * the name of this principal
+     */
+    private final String name;
+
+
+    /**
+     * Creates a new principal with the given name.
+     *
+     * @param name the name of this principal
+     */
+    public PrincipalImpl(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name can not be null");
+        }
+        this.name = name;
+    }
+
+    //----------------------------------------------------------< Principal >---
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return name;
+    }
+
+    //-------------------------------------------------------------< Object >---
+    /**
+     * Two principals are equal, if their names are.
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof JackrabbitPrincipal) {
+            // TODO: check if correct
+            return name.equals(((Principal) obj).getName());
+        }
+        return false;
+    }
+
+    /**
+     * @return the hash code of the principals name.
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString() {
+        return getClass().getName() + ":" + name;
+    }
+}
+

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalIteratorAdapter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalIteratorAdapter.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalIteratorAdapter.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalIteratorAdapter.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,68 @@
+/*
+ * 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.principal;
+
+import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
+import org.apache.jackrabbit.commons.iterator.RangeIteratorDecorator;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * <code>PrincipalIteratorAdapter</code>...
+ */
+public class PrincipalIteratorAdapter extends RangeIteratorDecorator
+        implements PrincipalIterator {
+
+    /**
+     * Static instance of an empty {@link PrincipalIterator}.
+     */
+    public static final PrincipalIteratorAdapter EMPTY = new PrincipalIteratorAdapter(RangeIteratorAdapter.EMPTY);
+
+
+    /**
+     * Creates an adapter for the given {@link Iterator} of principals.
+     *
+     * @param iterator iterator of {@link Principal}s
+     */
+    public PrincipalIteratorAdapter(Iterator iterator) {
+        super(new RangeIteratorAdapter(iterator));
+    }
+
+    /**
+     * Creates an iterator for the given collection of <code>Principal</code>s.
+     *
+     * @param collection collection of {@link Principal} objects.
+     */
+    public PrincipalIteratorAdapter(Collection collection) {
+        super(new RangeIteratorAdapter(collection));
+    }
+
+    //----------------------------------------< AccessControlPolicyIterator >---
+    /**
+     * Returns the next policy.
+     *
+     * @return next policy.
+     * @throws NoSuchElementException if there is no next policy.
+     */
+    public Principal nextPrincipal() throws NoSuchElementException {
+        return (Principal) next();
+    }
+}
\ No newline at end of file

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,340 @@
+/*
+ * 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.principal;
+
+import org.apache.jackrabbit.api.security.principal.NoSuchPrincipalException;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This principal manager implementation uses the {@link DefaultPrincipalProvider}
+ * in order to dispatch the respective requests and assemble the required
+ * data. It is bound to a session and therefore obliges the access restrictions
+ * of the respective subject.
+ */
+public class PrincipalManagerImpl implements PrincipalManager {
+
+    /** the Session this manager has been created for*/
+    private final Session session;
+
+    /** the principalProviders */
+    private final PrincipalProvider[] providers;
+
+    private boolean closed;
+
+    /**
+     * Creates a new default principal manager implementation.
+     *
+     * @param session
+     * @param providers
+     */
+    public PrincipalManagerImpl(Session session, PrincipalProvider[] providers) {
+        this.session = session;
+        this.providers = providers;
+        closed = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasPrincipal(String principalName) {
+        return internalGetPrincipal(principalName) != null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Principal getPrincipal(String principalName) throws NoSuchPrincipalException {
+        Principal p = internalGetPrincipal(principalName);
+        if (p == null) {
+            // not found (or access denied)
+            throw new NoSuchPrincipalException("Unknown principal " + principalName);
+        } else {
+            return p;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PrincipalIterator findPrincipals(String simpleFilter) {
+        checkIsValid();
+        List entries = new ArrayList(providers.length);
+        for (int i = 0; i < providers.length; i++) {
+            PrincipalProvider pp = providers[i];
+            PrincipalIterator it = pp.findPrincipals(simpleFilter);
+            if (it.hasNext()) {
+                entries.add(new CheckedIteratorEntry(it, pp));
+            }
+        }
+        return new CheckedPrincipalIterator(entries);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PrincipalIterator findPrincipals(String simpleFilter, int searchType) {
+        checkIsValid();
+        List entries = new ArrayList(providers.length);
+        for (int i = 0; i < providers.length; i++) {
+            PrincipalProvider pp = providers[i];
+            PrincipalIterator it = pp.findPrincipals(simpleFilter, searchType);
+            if (it.hasNext()) {
+                entries.add(new CheckedIteratorEntry(it, pp));
+            }
+        }
+        return new CheckedPrincipalIterator(entries);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param searchType
+     */
+    public PrincipalIterator getPrincipals(int searchType) {
+        checkIsValid();
+        List entries = new ArrayList(providers.length);
+        for (int i = 0; i < providers.length; i++) {
+            PrincipalProvider pp = providers[i];
+            PrincipalIterator it = pp.getPrincipals(searchType);
+            if (it.hasNext()) {
+                entries.add(new CheckedIteratorEntry(it, pp));
+            }
+        }
+        return new CheckedPrincipalIterator(entries);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PrincipalIterator getGroupMembership(Principal principal) {
+        checkIsValid();
+        List entries =  new ArrayList(providers.length + 1);
+        for (int i = 0; i < providers.length; i++) {
+            PrincipalProvider pp = providers[i];
+            PrincipalIterator groups = pp.getGroupMembership(principal);
+            if (groups.hasNext()) {
+                entries.add(new CheckedIteratorEntry(groups, pp));
+            }
+        }
+        // additional entry for the 'everyone' group
+        if (!(principal instanceof EveryonePrincipal)) {
+            Iterator it = Collections.singletonList(getEveryone()).iterator();
+            entries.add(new CheckedIteratorEntry(it, null));
+        }
+        return new CheckedPrincipalIterator(entries);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Principal getEveryone() {
+        checkIsValid();
+        return EveryonePrincipal.getInstance();
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Check if the instance has been closed.
+     *
+     * @throws IllegalStateException if this instance was closed.
+     */
+    private void checkIsValid() {
+        if (closed) {
+            throw new IllegalStateException("PrincipalManagerImpl instance has been closed.");
+        }
+    }
+
+    /**
+     * @param principalName
+     * @return The principal with the given name or <code>null</code> if none
+     * of the providers knows that principal of if the Session is not allowed
+     * to see it.
+     */
+    private Principal internalGetPrincipal(String principalName) {
+        checkIsValid();
+        for (int i = 0; i < providers.length; i++) {
+            Principal principal = providers[i].getPrincipal(principalName);
+            if (principal != null && providers[i].canReadPrincipal(session, principal)) {
+                return disguise(principal, providers[i]);
+            }
+        }
+        // nothing found or not allowed to see it.
+        return null;
+    }
+
+    /**
+     * @param principal
+     * @return A group that only reveals those members that are visible to the
+     * current session or the specified principal if its not a group or the
+     * everyone principal.
+     */
+    private Principal disguise(Principal principal, PrincipalProvider provider) {
+        if (!(principal instanceof Group) || principal instanceof EveryonePrincipal) {
+            // nothing to do.
+            return principal;
+        }
+        Group gr = (Group) principal;
+        // make sure all groups except for the 'everyone' group expose only
+        // principals visible to the session.
+        if (principal instanceof ItemBasedPrincipal) {
+            return new ItemBasedCheckedGroup(gr, provider);
+        } else {
+            return new CheckedGroup(gr, provider);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * An implementation of the <code>Group</code> interface that wrapps another
+     * Group and makes sure, that all exposed members are visible to the Session
+     * the <code>PrincipalManager</code> has been built for. This is required
+     * due to the fact, that the principal provider is not bound to a particular
+     * Session object.
+     */
+    private class CheckedGroup implements Group {
+
+        final Group delegatee;
+        private final PrincipalProvider provider;
+
+        private CheckedGroup(Group delegatee, PrincipalProvider provider) {
+            this.delegatee = delegatee;
+            this.provider = provider;
+        }
+
+        public boolean addMember(Principal user) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public boolean removeMember(Principal user) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public boolean isMember(Principal member) {
+            // TODO: check if access-restrictions should be checked
+            return delegatee.isMember(member);
+        }
+
+        public Enumeration members() {
+            Iterator it = Collections.list(delegatee.members()).iterator();
+            final Iterator members = new CheckedPrincipalIterator(it, provider);
+            return new Enumeration() {
+                public boolean hasMoreElements() {
+                    return members.hasNext();
+                }
+                public Object nextElement() {
+                    return members.next();
+                }
+            };
+        }
+
+        public String getName() {
+            return delegatee.getName();
+        }
+
+        //---------------------------------------------------------< Object >---
+        public int hashCode() {
+            return delegatee.hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            return delegatee.equals(obj);
+        }
+    }
+
+    /**
+     * Same as {@link CheckedGroup} but wrapping an ItemBasePrincipal.
+     */
+    private class ItemBasedCheckedGroup extends CheckedGroup implements ItemBasedPrincipal {
+
+        private ItemBasedCheckedGroup(Group delegatee, PrincipalProvider provider) {
+            super(delegatee, provider);
+            if (!(delegatee instanceof ItemBasedPrincipal)) {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        public String getPath() throws RepositoryException {
+            return ((ItemBasedPrincipal) delegatee).getPath();
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * A PrincipalIterator implementation that tests for each principal
+     * in the passed base iterators whether it is visible to the Session
+     * the PrincipalManager has been built for. A principal that is not
+     * accessible is skipped during the iteration.
+     */
+    private class CheckedPrincipalIterator extends AbstractPrincipalIterator {
+
+        private final List entries;
+
+        private CheckedPrincipalIterator(Iterator it, PrincipalProvider provider) {
+            entries = new ArrayList(1);
+            entries.add(new CheckedIteratorEntry(it, provider));
+            next = seekNext();
+        }
+
+        private CheckedPrincipalIterator(List entries) {
+            this.entries = new ArrayList(entries);
+            next = seekNext();
+        }
+
+        protected final Principal seekNext() {
+            while (!entries.isEmpty()) {
+                // first test if current-itr has more elements
+                CheckedIteratorEntry current = (CheckedIteratorEntry) entries.get(0);
+                Iterator iterator = current.iterator;
+                while (iterator.hasNext()) {
+                    Principal chk = (Principal) iterator.next();
+                    if (current.provider == null ||
+                        current.provider.canReadPrincipal(session, chk)) {
+                        return disguise(chk, current.provider);
+                    }
+                }
+                // ino more elements in current-itr -> move to next iterator.
+                entries.remove(0);
+            }
+            return null;
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     *
+     */
+    private static class CheckedIteratorEntry {
+
+        private final PrincipalProvider provider;
+        private final Iterator iterator;
+
+        private CheckedIteratorEntry(Iterator iterator, PrincipalProvider provider) {
+            this.iterator = iterator;
+            this.provider = provider;
+        }
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,136 @@
+/*
+ * 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.principal;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+
+import javax.jcr.Session;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Properties;
+
+/**
+ * This interface defines methods to provide access to sources of
+ * {@link Principal}s. This allows the security framework share any external
+ * sources for authorization and authentication, as may be used by a custom
+ * {@link javax.security.auth.spi.LoginModule} for example.
+ *
+ * @see PrincipalManager for more details about principals, users and groups.
+ */
+public interface PrincipalProvider {
+
+    /**
+     * Checks if the principal with the given name is known to this provider.
+     *
+     * @param principalName the name of the principal to check
+     * @return return <code>true</code> if the principal with this name is known
+     *         to this provider; <code>false</code> otherwise.
+     */
+    boolean hasPrincipal(String principalName);
+
+    /**
+     * Returns the principal with the given name if is known to this provider
+     *
+     * @param principalName the name of the principal to retrieve
+     * @return return the requested principal or <code>null</code>
+     */
+    Principal getPrincipal(String principalName);
+
+    /**
+     * Searches for <code>Principal</code>s that match the given String.
+     * NOTE: <code>Group</code>s are included in the search result.
+     *
+     * @param simpleFilter
+     * @return
+     * @see #findPrincipals(String,int)
+     */
+    PrincipalIterator findPrincipals(String simpleFilter);
+
+    /**
+     * Searches for <code>Principal</code>s that match the given String.
+     *
+     * @param simpleFilter
+     * @param searchType searchType Any of the following constants:
+     * <ul>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_ALL}</li>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_GROUP}</li>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_NOT_GROUP}</li>
+     * </ul>
+     * @return
+     * @see #findPrincipals(String)
+     */
+    PrincipalIterator findPrincipals(String simpleFilter, int searchType);
+
+    /**
+     * Returns an iterator over all principals that match the given search type.
+     *
+     * @return an iterator over all principals that match the given search type.
+     * @param searchType searchType Any of the following constants:
+     * <ul>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_ALL}</li>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_GROUP}</li>
+     * <li>{@link PrincipalManager#SEARCH_TYPE_NOT_GROUP}</li>
+     * </ul>
+     */
+    PrincipalIterator getPrincipals(int searchType);
+
+    /**
+     * Returns an iterator over all group principals for which the given
+     * principal is either direct or indirect member of. If a principal is
+     * a direct member of a group, then <code>{@link Group#isMember(Principal)}</code>
+     * evaluates to <code>true</code>. A principal is an indirect member of a
+     * group if any of its groups (to any degree of separation) is direct memeber
+     * of the group.
+     * <p/>
+     * Example:<br>
+     * If Principal is member of Group A, and Group A is member of
+     * Group B, this method will return Group A and Group B.
+     *
+     * @param principal the principal to return it's membership from.
+     * @return an iterator returning all groups the given principal is member of.
+     */
+    PrincipalIterator getGroupMembership(Principal principal);
+
+    /**
+     * Initialize this provider.
+     *
+     * @param options the options that are set
+     */
+    void init(Properties options);
+
+    /**
+     * This is called when a provider is not longer used by the repository.
+     * An implementation can then release any resources bound to this
+     * provider, eg. disconnect from a backend system.
+     */
+    void close();
+
+    /**
+     * // TODO: review again.
+     * Tests if the provided session is allowed to read the given principal.
+     * Since the principal providers do not restrict the access
+     * on the prinicipals they provide, this method is used by the PrincipalManger
+     * to ensure proper access rights for the client requesting the principals.
+     *
+     * @param session
+     * @param principalToRead The principal to be accessed by the specified subject.
+     * @return <code>true</code> if the subject is allowed to read the principal;
+     * <code>false</code> otherwise.
+     */
+    boolean canReadPrincipal(Session session, Principal principalToRead);
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProviderRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProviderRegistry.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProviderRegistry.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProviderRegistry.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.security.principal;
+
+import javax.jcr.RepositoryException;
+import java.util.Properties;
+
+/**
+ * Registry used to store and retrieve <code>PrincipalProvider</code>s.
+ *
+ * @see PrincipalProvider
+ */
+public interface PrincipalProviderRegistry {
+
+    /**
+     * Registers a new provider by means of a configuration. The
+     * registry expects the properties to contain a
+     * {@link org.apache.jackrabbit.core.config.LoginModuleConfig#PARAM_PRINCIPAL_PROVIDER_CLASS}
+     * to be able to create a instance of PrincipalProvider.
+     * <p/>
+     * The Properties will be passed to the instanciated Provider via
+     * {@link PrincipalProvider#init(Properties)}
+     *
+     * @param configuration Properties for the Provider
+     * @return the newly added Provider or <code>null</code> if the configuration
+     * was incomplete.
+     * @throws RepositoryException if an error occurs while creating the
+     * provider instance.
+     */
+    PrincipalProvider registerProvider(Properties configuration) throws RepositoryException;
+
+    /**
+     * @return the default principal provider
+     */
+    PrincipalProvider getDefault();
+
+    /**
+     * @param className
+     * @return PrincipalProvider or <code>null</code> if no provider with
+     * the given class name was registered.
+     */
+    PrincipalProvider getProvider(String className);
+
+    /**
+     * Returns all registered providers.
+     *
+     * @return all registered providers.
+     */
+    PrincipalProvider[] getProviders();
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ProviderRegistryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ProviderRegistryImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ProviderRegistryImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/ProviderRegistryImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,132 @@
+/*
+ * 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.principal;
+
+import org.apache.jackrabbit.core.config.BeanConfig;
+import org.apache.jackrabbit.core.config.LoginModuleConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * This is the default implementation of the {@link PrincipalProviderRegistry}
+ * interface.
+ */
+public class ProviderRegistryImpl implements PrincipalProviderRegistry {
+
+    /** the default logger */
+    private static final Logger log = LoggerFactory.getLogger(ProviderRegistryImpl.class);
+
+    private final PrincipalProvider defaultPrincipalProvider;
+    private final Map providers = new HashMap();
+
+    /**
+     * Create an instance of <code>ProviderRegistryImpl</code> with the given
+     * default principal provider.
+     * NOTE that the provider must be initialized by the caller.
+     *
+     * @param defaultPrincipalProvider
+     */
+    public ProviderRegistryImpl(PrincipalProvider defaultPrincipalProvider) {
+        this.defaultPrincipalProvider = defaultPrincipalProvider;
+        providers.put(defaultPrincipalProvider.getClass().getName(), defaultPrincipalProvider);
+    }
+
+
+    //------------------------------------------< PrincipalProviderRegistry >---
+    /**
+     * @see PrincipalProviderRegistry#registerProvider(Properties)
+     */
+    public PrincipalProvider registerProvider(Properties config) throws RepositoryException {
+        PrincipalProvider provider = createProvider(config);
+        if (provider != null) {
+            synchronized(providers) {
+                providers.put(provider.getClass().getName(), provider);
+            }
+        } else {
+            log.debug("Could not register principal provider: " +
+                    LoginModuleConfig.PARAM_PRINCIPAL_PROVIDER_CLASS +
+                    " configuration entry missing.");
+        }
+        return provider;
+    }
+
+    /**
+     * @see PrincipalProviderRegistry#getDefault()
+     */
+    public PrincipalProvider getDefault() {
+        return defaultPrincipalProvider;
+    }
+
+    /**
+     * @see PrincipalProviderRegistry#getProviders()
+     */
+    public PrincipalProvider getProvider(String className) {
+        synchronized (providers) {
+            return (PrincipalProvider) providers.get(className);
+        }
+    }
+
+    /**
+     * @see PrincipalProviderRegistry#getProviders()
+     */
+    public PrincipalProvider[] getProviders() {
+        synchronized (providers) {
+            Collection pps = providers.values();
+            return (PrincipalProvider[]) pps.toArray(new PrincipalProvider[pps.size()]);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Read the map and instanciate the class indicated by the
+     * {@link LoginModuleConfig#PARAM_PRINCIPAL_PROVIDER_CLASS} key.<br>
+     * The class gets set the properties of the given map, via a Bean mechanism
+     *
+     * @param config
+     * @return the new provider instance or <code>null</code> if the
+     * configuration does not contain the required entry.
+     */
+    private PrincipalProvider createProvider(Properties config)
+            throws RepositoryException {
+
+        String className = config.getProperty(LoginModuleConfig.PARAM_PRINCIPAL_PROVIDER_CLASS);
+        if (className == null) {
+            return null;
+        }
+
+        try {
+            Class pc = Class.forName(className, true, BeanConfig.getDefaultClassLoader());
+            PrincipalProvider pp = (PrincipalProvider) pc.newInstance();
+            pp.init(config);
+            return pp;
+        } catch (ClassNotFoundException e) {
+            throw new RepositoryException("Unable to create new principal provider.", e);
+        } catch (IllegalAccessException e) {
+            throw new RepositoryException("Unable to create new principal provider.", e);
+        } catch (InstantiationException e) {
+            throw new RepositoryException("Unable to create new principal provider.", e);
+        } catch (ClassCastException e) {
+            throw new RepositoryException("Unable to create new principal provider.", e);
+        }
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,286 @@
+/*
+ * 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.simple;
+
+import org.apache.jackrabbit.core.security.AbstractAccessControlManager;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.AMContext;
+import org.apache.jackrabbit.core.security.AnonymousPrincipal;
+import org.apache.jackrabbit.core.security.SystemPrincipal;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Name;
+
+import javax.security.auth.Subject;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.PathNotFoundException;
+
+/**
+ * <code>SimpleAccessManager</code> ...
+ */
+public class SimpleAccessManager extends AbstractAccessControlManager implements AccessManager {
+
+    /**
+     * Subject whose access rights this AccessManager should reflect
+     */
+    private Subject subject;
+
+    /**
+     * hierarchy manager used for ACL-based access control model
+     */
+    private HierarchyManager hierMgr;
+
+    private NamePathResolver resolver;
+    private WorkspaceAccessManager wspAccessMgr;
+
+    private boolean initialized;
+
+    private boolean system;
+    private boolean anonymous;
+
+    /**
+     * Empty constructor
+     */
+    public SimpleAccessManager() {
+        initialized = false;
+        anonymous = false;
+        system = false;
+    }
+
+    //--------------------------------------------------------< AccessManager >
+    /**
+     * {@inheritDoc}
+     */
+    public void init(AMContext context)
+            throws AccessDeniedException, Exception {
+        init(context, null, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void init(AMContext context, AccessControlProvider acProvider, WorkspaceAccessManager wspAccessManager) throws AccessDeniedException, Exception {
+        if (initialized) {
+            throw new IllegalStateException("already initialized");
+        }
+
+        subject = context.getSubject();
+        hierMgr = context.getHierarchyManager();
+        resolver = context.getNamePathResolver();
+        wspAccessMgr = wspAccessManager;
+        anonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty();
+        system = !subject.getPrincipals(SystemPrincipal.class).isEmpty();
+
+        // @todo check permission to access given workspace based on principals
+        initialized = true;
+
+        if (!canAccess(context.getWorkspaceName())) {
+            throw new AccessDeniedException("Not allowed to access Workspace " + context.getWorkspaceName());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void close() throws Exception {
+        checkInitialized();
+        initialized = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkPermission(ItemId id, int permissions)
+            throws AccessDeniedException, ItemNotFoundException,
+            RepositoryException {
+        if (!isGranted(id, permissions)) {
+            throw new AccessDeniedException("Access denied");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isGranted(ItemId id, int permissions)
+            throws ItemNotFoundException, RepositoryException {
+        checkInitialized();
+        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 boolean isGranted(Path absPath, int permissions) throws RepositoryException {
+        return internalIsGranted(absPath, permissions);
+    }
+
+    public boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException {
+        return internalIsGranted(parentPath, permissions);
+    }
+
+    private boolean internalIsGranted(Path absPath, int permissions) throws ItemNotFoundException, RepositoryException {
+        if (!absPath.isAbsolute()) {
+            throw new RepositoryException("Absolute path expected");
+        }
+        checkInitialized();
+        if (system) {
+            // system has always all permissions
+            return true;
+        } else if (anonymous) {
+            // anonymous is only granted READ premissions
+            return permissions == Permission.READ;
+        }
+
+        // @todo check permission based on principals
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean canAccess(String workspaceName) throws NoSuchWorkspaceException, RepositoryException {
+        if (system || wspAccessMgr == null) {
+            return true;
+        }
+        return wspAccessMgr.grants(subject.getPrincipals(), workspaceName);
+    }
+
+    //-----------------------------------------------< AccessControlManager >---
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasPrivileges(String absPath, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        // make sure absPath points to an existing node
+        getValidNodePath(absPath);
+
+        if (privileges == null || privileges.length == 0) {
+            // null or empty privilege array -> return true
+            return true;
+        } else {
+            int bits = PrivilegeRegistry.getBits(privileges);
+            if (system) {
+                // system has always all permissions
+                return true;
+            } else if (anonymous) {
+                if (bits != PrivilegeRegistry.READ) {
+                    // anonymous is only granted READ premissions
+                    return false;
+                }
+            }
+
+            // @todo check permission based on principals
+            return true;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Privilege[] getPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        getValidNodePath(absPath);
+
+        if (anonymous) {
+            return new Privilege[] {PrivilegeRegistry.READ_PRIVILEGE};
+        } else if (system) {
+            return new Privilege[] {PrivilegeRegistry.ALL_PRIVILEGE};
+        } else {
+            // @todo check permission based on principals
+            return new Privilege[] {PrivilegeRegistry.ALL_PRIVILEGE};
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public AccessControlPolicy getEffectivePolicy(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path p = getValidNodePath(absPath);
+        checkPrivileges(p, PrivilegeRegistry.READ_AC);
+
+        return new AccessControlPolicy() {
+            public String getName() throws RepositoryException {
+                return "Simple AccessControlPolicy";
+            }
+            public String getDescription() throws RepositoryException {
+                return null;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public AccessControlEntry[] getEffectiveAccessControlEntries(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        checkInitialized();
+        Path p = getValidNodePath(absPath);
+        checkPrivileges(p, PrivilegeRegistry.READ_AC);
+
+        return new AccessControlEntry[0];
+    }
+    
+    //---------------------------------------< AbstractAccessControlManager >---
+    /**
+     * {@inheritDoc}
+     */
+    protected void checkInitialized() throws IllegalStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+    }
+
+    protected void checkPrivileges(Path absPath, int privileges) throws AccessDeniedException, PathNotFoundException, RepositoryException {
+        if (anonymous && privileges != PrivilegeRegistry.READ) {
+            throw new AccessDeniedException("Anonymous may only READ.");
+        }
+    }
+
+    protected Path getValidNodePath(String absPath) throws PathNotFoundException, RepositoryException {
+        Path path = resolver.getQPath(absPath);
+        if (!path.isAbsolute()) {
+            throw new RepositoryException("Absolute path expected. Found: " + absPath);
+        }
+
+        if (hierMgr.resolveNodePath(path) == null) {
+            throw new PathNotFoundException(absPath);
+        } else {
+            return path;
+        }
+    }
+}

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,67 @@
+/*
+ * 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.simple;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.security.authentication.Authentication;
+import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.Subject;
+import javax.jcr.Session;
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import java.util.Map;
+import java.security.Principal;
+import java.security.acl.Group;
+
+/**
+ * <code>SimpleLoginModule</code>...
+ */
+public class SimpleLoginModule extends AbstractLoginModule {
+
+    private static Logger log = LoggerFactory.getLogger(SimpleLoginModule.class);
+
+    protected void doInit(CallbackHandler callbackHandler, Session session, Map options) throws LoginException {
+        // nothing to do
+        log.debug("init: SimpleLoginModule. Done.");
+    }
+
+    protected boolean impersonate(Principal principal, Credentials credentials) throws RepositoryException, LoginException {
+        if (principal instanceof Group) {
+            return false;
+        }
+        Subject impersSubject = getImpersonatorSubject(credentials);
+        return impersSubject != null;
+    }
+
+    protected Authentication getAuthentication(Principal principal, Credentials creds) throws RepositoryException {
+        if (principal instanceof Group) {
+            return null;
+        }
+        return new Authentication() {
+            public boolean canHandle(Credentials credentials) {
+                return true;
+            }
+            public boolean authenticate(Credentials credentials) throws RepositoryException {
+                return true;
+            }
+        };
+    }
+}
\ No newline at end of file

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

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