You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by ad...@apache.org on 2009/03/11 06:40:54 UTC

svn commit: r752380 [5/9] - in /incubator/jsecurity/trunk: ./ core/src/org/apache/ki/ core/src/org/apache/ki/aop/ core/src/org/apache/ki/authc/ core/src/org/apache/ki/authc/credential/ core/src/org/apache/ki/authc/pam/ core/src/org/apache/ki/authz/ cor...

Copied: incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SessionsSecurityManager.java (from r752240, incubator/jsecurity/trunk/core/src/org/ki/mgt/SessionsSecurityManager.java)
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SessionsSecurityManager.java?p2=incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SessionsSecurityManager.java&p1=incubator/jsecurity/trunk/core/src/org/ki/mgt/SessionsSecurityManager.java&r1=752240&r2=752380&rev=752380&view=diff
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/ki/mgt/SessionsSecurityManager.java (original)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SessionsSecurityManager.java Wed Mar 11 05:40:38 2009
@@ -16,28 +16,29 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.ki.mgt;
-
-import org.ki.authz.HostUnauthorizedException;
-import org.ki.cache.CacheManagerAware;
-import org.ki.session.InvalidSessionException;
-import org.ki.session.Session;
-import org.ki.session.SessionListener;
-import org.ki.session.SessionListenerRegistrar;
-import org.ki.session.mgt.AbstractSessionManager;
-import org.ki.session.mgt.AbstractValidatingSessionManager;
-import org.ki.session.mgt.DefaultSessionManager;
-import org.ki.session.mgt.SessionManager;
-import org.ki.util.LifecycleUtils;
+package org.apache.ki.mgt;
 
 import java.io.Serializable;
 import java.net.InetAddress;
 import java.util.Collection;
 import java.util.Date;
 
+import org.apache.ki.authz.HostUnauthorizedException;
+import org.apache.ki.cache.CacheManagerAware;
+import org.apache.ki.session.InvalidSessionException;
+import org.apache.ki.session.Session;
+import org.apache.ki.session.SessionListener;
+import org.apache.ki.session.SessionListenerRegistrar;
+import org.apache.ki.session.mgt.AbstractSessionManager;
+import org.apache.ki.session.mgt.AbstractValidatingSessionManager;
+import org.apache.ki.session.mgt.DefaultSessionManager;
+import org.apache.ki.session.mgt.SessionManager;
+import org.apache.ki.util.LifecycleUtils;
+
+
 /**
  * JSecurity support of a {@link SecurityManager} class hierarchy that delegates all
- * {@link org.ki.session.Session session} operations to a wrapped {@link SessionManager SessionManager}
+ * {@link org.apache.ki.session.Session session} operations to a wrapped {@link org.apache.ki.session.mgt.SessionManager SessionManager}
  * instance.  That is, this class implements the methods in the
  * {@link SessionManager SessionManager} interface, but in reality, those methods are merely passthrough calls to
  * the underlying 'real' {@code SessionManager} instance.
@@ -95,14 +96,14 @@
      * Returns this security manager's internal delegate {@link SessionManager SessionManager}.
      *
      * @return this security manager's internal delegate {@link SessionManager SessionManager}.
-     * @see #setSessionManager(org.ki.session.mgt.SessionManager) setSessionManager
+     * @see #setSessionManager(org.apache.ki.session.mgt.SessionManager) setSessionManager
      */
     public SessionManager getSessionManager() {
         return this.sessionManager;
     }
 
     /**
-     * Calls {@link AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
+     * Calls {@link org.apache.ki.mgt.AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
      * {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()} to ensure the
      * <code>CacheManager</code> is applied to the SessionManager as necessary.
      */
@@ -165,13 +166,13 @@
     /**
      * Passthrough configuration property to the underlying {@link AbstractSessionManager AbstractSessionManager}
      * instance.  Please read the
-     * {@link org.ki.session.mgt.AbstractSessionManager#getGlobalSessionTimeout() AbstractSessionManager.getGlobalSessionTimeout()}
+     * {@link org.apache.ki.session.mgt.AbstractSessionManager#getGlobalSessionTimeout() AbstractSessionManager.getGlobalSessionTimeout()}
      * for more.
      *
      * @return the time in milliseconds that any {@link Session Session} may remain idle before expiring.
      * @throws IllegalStateException if the underlying {@code SessionManager} instance is not a subclass of
      *                               {@link AbstractSessionManager AbstractSessionManager}.
-     * @see org.ki.session.mgt.AbstractSessionManager#getGlobalSessionTimeout()
+     * @see org.apache.ki.session.mgt.AbstractSessionManager#getGlobalSessionTimeout()
      */
     public long getGlobalSessionTimeout() {
         assertSessionManager(AbstractSessionManager.class);
@@ -181,13 +182,13 @@
     /**
      * Passthrough configuration property to the underlying {@link AbstractSessionManager AbstractSessionManager}
      * instance.  Please read the
-     * {@link org.ki.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long) AbstractSessionManager.setGlobalSessionTimeout(long)}
+     * {@link org.apache.ki.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long) AbstractSessionManager.setGlobalSessionTimeout(long)}
      * for more.
      *
      * @param globalSessionTimeout the time in milliseconds that any {@link Session Session} may remain idle before expiring.
      * @throws IllegalStateException if the underlying {@code SessionManager} instance is not a subclass of
-     *                               {@link AbstractSessionManager AbstractSessionManager}.
-     * @see org.ki.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long)
+     *                               {@link org.apache.ki.session.mgt.AbstractSessionManager AbstractSessionManager}.
+     * @see org.apache.ki.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long)
      */
     public void setGlobalSessionTimeout(long globalSessionTimeout) {
         assertSessionManager(AbstractSessionManager.class);
@@ -195,19 +196,19 @@
     }
 
     /**
-     * Passthrough configuration property to the wrapped {@link AbstractValidatingSessionManager} - if it should
+     * Passthrough configuration property to the wrapped {@link org.apache.ki.session.mgt.AbstractValidatingSessionManager} - if it should
      * automatically create a new session when an invalid session is referenced.  The default value unless
      * overridden by this method is <code>true</code> for developer convenience and to match what most people are
      * accustomed based on years of servlet container behavior.
      * <p/>
      * When true (the default), the wrapped {@link AbstractValidatingSessionManager} implementation throws an
-     * {@link org.ki.session.ReplacedSessionException ReplacedSessionException} to the caller whenever a new
+     * {@link org.apache.ki.session.ReplacedSessionException ReplacedSessionException} to the caller whenever a new
      * session is created so the caller can receive the new session ID and react accordingly for future
      * {@link SessionManager SessionManager} method invocations.
      *
      * @param autoCreate if the wrapped {@link AbstractValidatingSessionManager} should automatically create a new
      *                   session when an invalid session is referenced
-     * @see org.ki.session.mgt.AbstractValidatingSessionManager#setAutoCreateAfterInvalidation(boolean)
+     * @see org.apache.ki.session.mgt.AbstractValidatingSessionManager#setAutoCreateAfterInvalidation(boolean)
      */
     public void setAutoCreateSessionAfterInvalidation(boolean autoCreate) {
         assertSessionManager(AbstractValidatingSessionManager.class);
@@ -216,19 +217,19 @@
 
     /**
      * Passthrough configuration property that returns <code>true</code> if the wrapped
-     * {@link AbstractValidatingSessionManager AbstractValidatingSessionManager} should automatically create a
+     * {@link org.apache.ki.session.mgt.AbstractValidatingSessionManager AbstractValidatingSessionManager} should automatically create a
      * new session when an invalid session is referenced, <code>false</code> otherwise.  Unless overridden by the
      * {@link #setAutoCreateSessionAfterInvalidation(boolean)} method, the default value is <code>true</code> for
      * developer convenience and to match what most people are accustomed based on years of servlet container behavior.
      * <p/>
-     * When true (the default), the wrapped {@link AbstractValidatingSessionManager AbstractValidatingSessionManager}
-     * implementation throws an {@link org.ki.session.ReplacedSessionException ReplacedSessionException} to
+     * When true (the default), the wrapped {@link org.apache.ki.session.mgt.AbstractValidatingSessionManager AbstractValidatingSessionManager}
+     * implementation throws an {@link org.apache.ki.session.ReplacedSessionException ReplacedSessionException} to
      * the caller whenever a new session is created so the caller can receive the new session ID and react accordingly
      * for future {@link SessionManager SessionManager} method invocations.
      *
      * @return <code>true</code> if this session manager should automatically create a new session when an invalid
      *         session is referenced, <code>false</code> otherwise.
-     * @see org.ki.session.mgt.AbstractValidatingSessionManager#isAutoCreateAfterInvalidation()
+     * @see org.apache.ki.session.mgt.AbstractValidatingSessionManager#isAutoCreateAfterInvalidation()
      */
     public boolean isAutoCreateSessionAfterInvalidation() {
         assertSessionManager(AbstractValidatingSessionManager.class);
@@ -237,7 +238,7 @@
 
     /**
      * Ensures the internal SessionManager instance is an <code>instanceof</code>
-     * {@link org.ki.session.SessionListenerRegistrar SessionListenerRegistrar} to ensure that any
+     * {@link org.apache.ki.session.SessionListenerRegistrar SessionListenerRegistrar} to ensure that any
      * listeners attempting to be registered can actually do so with the internal delegate instance.
      *
      * @throws IllegalStateException if the internal delegate SessionManager instance does not implement the
@@ -268,7 +269,7 @@
 
     /**
      * Removes the specified listener from receiving session events from the internal delegate
-     * {@link SessionManager} instance.
+     * {@link org.apache.ki.session.mgt.SessionManager} instance.
      *
      * @param listener the listener to remove that no longer wishes to be notified of session events.
      * @return <code>true</code> if the listener was removed from the internal delegate <code>SessionManager</code>

Copied: incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectBinder.java (from r752240, incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectBinder.java)
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectBinder.java?p2=incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectBinder.java&p1=incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectBinder.java&r1=752240&r2=752380&rev=752380&view=diff
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectBinder.java (original)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectBinder.java Wed Mar 11 05:40:38 2009
@@ -16,9 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.ki.mgt;
+package org.apache.ki.mgt;
+
+import org.apache.ki.subject.Subject;
 
-import org.ki.subject.Subject;
 
 /**
  * TODO - Class JavaDoc

Copied: incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectFactory.java (from r752240, incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectFactory.java)
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectFactory.java?p2=incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectFactory.java&p1=incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectFactory.java&r1=752240&r2=752380&rev=752380&view=diff
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/ki/mgt/SubjectFactory.java (original)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/SubjectFactory.java Wed Mar 11 05:40:38 2009
@@ -16,16 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.ki.mgt;
-
-import org.ki.authc.AuthenticationInfo;
-import org.ki.authc.AuthenticationToken;
-import org.ki.session.Session;
-import org.ki.subject.PrincipalCollection;
-import org.ki.subject.Subject;
+package org.apache.ki.mgt;
 
 import java.net.InetAddress;
 
+import org.apache.ki.authc.AuthenticationInfo;
+import org.apache.ki.authc.AuthenticationToken;
+import org.apache.ki.session.Session;
+import org.apache.ki.subject.PrincipalCollection;
+import org.apache.ki.subject.Subject;
+
 /**
  * A {@code SubjectFactory} is responsible for returning {@link Subject Subject} instances as needed.
  *
@@ -57,7 +57,7 @@
      * @param principals      the identifying attributes of the Subject instance to be created, or
      *                        {@code null} if the Subject's identity is unknown because they haven't logged in yet and are not 'remembered'
      *                        from {@code RememberMe} services.
-     * @param existing        any {@link Session Session} that might be in place for the specified {@link Subject}, or
+     * @param existing        any {@link org.apache.ki.session.Session Session} that might be in place for the specified {@link org.apache.ki.subject.Subject}, or
      *                        {@code null} if there is no session yet created for the specified {@code Subject}.  If non-{@code null},
      *                        it should be retained and used by the {@code Subject} instance returned from this method call.
      * @param authenticated   whether or not the {@code Subject} instance returned should be considered already

Copied: incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/ThreadContextSubjectBinder.java (from r752240, incubator/jsecurity/trunk/core/src/org/ki/mgt/ThreadContextSubjectBinder.java)
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/ThreadContextSubjectBinder.java?p2=incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/ThreadContextSubjectBinder.java&p1=incubator/jsecurity/trunk/core/src/org/ki/mgt/ThreadContextSubjectBinder.java&r1=752240&r2=752380&rev=752380&view=diff
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/ki/mgt/ThreadContextSubjectBinder.java (original)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/mgt/ThreadContextSubjectBinder.java Wed Mar 11 05:40:38 2009
@@ -16,12 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.ki.mgt;
+package org.apache.ki.mgt;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.ki.subject.Subject;
-import org.ki.util.ThreadContext;
+
+import org.apache.ki.subject.Subject;
+import org.apache.ki.util.ThreadContext;
+
 
 /**
  * Associates a {@link Subject Subject} instance to the currently executing thread via the {
@@ -29,7 +31,7 @@
  * @author Les Hazlewood
  * @link ThreadContext ThreadContext} to ensure that the <code>Subject</code> is accessible to any caller during
  * thread execution.
- * @see org.ki.SecurityUtils#getSubject SecurityUtils.getSubject()
+ * @see org.apache.ki.SecurityUtils#getSubject SecurityUtils.getSubject()
  * @since 1.0
  */
 public class ThreadContextSubjectBinder implements SubjectBinder {

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,243 @@
+/*
+ * 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.ki.realm;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.ki.authc.AuthenticationException;
+import org.apache.ki.authc.AuthenticationInfo;
+import org.apache.ki.authc.AuthenticationToken;
+import org.apache.ki.authc.IncorrectCredentialsException;
+import org.apache.ki.authc.LogoutAware;
+import org.apache.ki.authc.UsernamePasswordToken;
+import org.apache.ki.authc.credential.AllowAllCredentialsMatcher;
+import org.apache.ki.authc.credential.CredentialsMatcher;
+import org.apache.ki.authc.credential.SimpleCredentialsMatcher;
+import org.apache.ki.cache.CacheManager;
+import org.apache.ki.subject.PrincipalCollection;
+
+
+/**
+ * A top-level abstract implementation of the <tt>Realm</tt> interface that only implements authentication support
+ * (log-in) operations and leaves authorization (access control) behavior to subclasses.
+ *
+ * <p>Since a Realm provides both authentication <em>and</em> authorization operations, the implementation approach for
+ * this class could have been reversed.  That is, authorization support could have been implemented here and
+ * authentication support left to subclasses.
+ *
+ * <p>The reason the existing implementation is in place though
+ * (authentication support) is that most authentication operations are fairly common across the large majority of
+ * applications, whereas authorization operations are more so heavily dependent upon the application's data model, which
+ * can vary widely.
+ *
+ * <p>By providing the most common authentication operations here and leaving data-model specific authorization checks
+ * to subclasses, a top-level abstract class for most common authentication behavior is more useful as an extension
+ * point for most applications.
+ *
+ * @author Les Hazlewood
+ * @author Jeremy Haile
+ * @since 0.2
+ */
+public abstract class AuthenticatingRealm extends CachingRealm implements LogoutAware {
+
+    //TODO - complete JavaDoc
+
+    private static final Log log = LogFactory.getLog(AuthenticatingRealm.class);
+
+    /**
+     * Password matcher used to determine if the provided password matches
+     * the password stored in the data store.
+     */
+    private CredentialsMatcher credentialsMatcher = new SimpleCredentialsMatcher();
+
+    /**
+     * The class that this realm supports for authentication tokens.  This is used by the
+     * default implementation of the {@link Realm#supports(org.apache.ki.authc.AuthenticationToken)} method to
+     * determine whether or not the given authentication token is supported by this realm.
+     */
+    private Class<? extends AuthenticationToken> authenticationTokenClass = UsernamePasswordToken.class;
+
+    /*--------------------------------------------
+    |         C O N S T R U C T O R S           |
+    ============================================*/
+    public AuthenticatingRealm() {
+    }
+
+    public AuthenticatingRealm(CacheManager cacheManager) {
+        setCacheManager(cacheManager);
+    }
+
+    public AuthenticatingRealm(CredentialsMatcher matcher) {
+        setCredentialsMatcher(matcher);
+    }
+
+    public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
+        setCacheManager(cacheManager);
+        setCredentialsMatcher(matcher);
+    }
+
+    /*--------------------------------------------
+    |  A C C E S S O R S / M O D I F I E R S    |
+    ============================================*/
+    /**
+     * Returns the <code>CredentialsMatcher</code> used during an authentication attempt to verify submitted
+     * credentials with those stored in the system.
+     *
+     * <p>Unless overridden by the {@link #setCredentialsMatcher setCredentialsMatcher} method, the default
+     * value is a {@link org.apache.ki.authc.credential.SimpleCredentialsMatcher SimpleCredentialsMatcher} instance.
+     *
+     * @return the <code>CredentialsMatcher</code> used during an authentication attempt to verify submitted
+     *         credentials with those stored in the system.
+     */
+    public CredentialsMatcher getCredentialsMatcher() {
+        return credentialsMatcher;
+    }
+
+    /**
+     * Sets the CrendialsMatcher used during an authentication attempt to verify submitted credentials with those
+     * stored in the system.  The implementation of this matcher can be switched via configuration to
+     * support any number of schemes, including plain text comparisons, hashing comparisons, and others.
+     *
+     * <p>Unless overridden by this method, the default value is a
+     * {@link org.apache.ki.authc.credential.SimpleCredentialsMatcher} instance.
+     *
+     * @param credentialsMatcher the matcher to use.
+     */
+    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
+        this.credentialsMatcher = credentialsMatcher;
+    }
+
+    /**
+     * Returns the authenticationToken class supported by this realm.
+     *
+     * <p>The default value is <tt>{@link org.apache.ki.authc.UsernamePasswordToken UsernamePasswordToken.class}</tt>, since
+     * about 90% of realms use username/password authentication, regardless of their protocol (e.g. over jdbc, ldap,
+     * kerberos, http, etc).
+     *
+     * <p>If subclasses haven't already overridden the {@link Realm#supports Realm.supports(AuthenticationToken)} method,
+     * they must {@link #setAuthenticationTokenClass(Class) set a new class} if they won't support
+     * <tt>UsernamePasswordToken</tt> authentication token submissions.
+     *
+     * @return the authenticationToken class supported by this realm.
+     * @see #setAuthenticationTokenClass
+     */
+    public Class getAuthenticationTokenClass() {
+        return authenticationTokenClass;
+    }
+
+    /**
+     * Sets the authenticationToken class supported by this realm.
+     *
+     * <p>Unless overridden by this method, the default value is
+     * {@link org.apache.ki.authc.UsernamePasswordToken UsernamePasswordToken.class} to support the majority of applications.
+     *
+     * @param authenticationTokenClass the class of authentication token instances supported by this realm.
+     * @see #getAuthenticationTokenClass getAuthenticationTokenClass() for more explanation.
+     */
+    public void setAuthenticationTokenClass(Class<? extends AuthenticationToken> authenticationTokenClass) {
+        this.authenticationTokenClass = authenticationTokenClass;
+    }
+
+    /*--------------------------------------------
+    |               M E T H O D S               |
+    ============================================*/
+    /**
+     * Convenience implementation that returns
+     * <tt>getAuthenticationTokenClass().isAssignableFrom( token.getClass() );</tt>.  Can be overridden
+     * by subclasses for more complex token checking.
+     * <p>Most configurations will only need to set a different class via
+     * {@link #setAuthenticationTokenClass}, as opposed to overriding this method.
+     *
+     * @param token the token being submitted for authentication.
+     * @return true if this authentication realm can process the submitted token instance of the class, false otherwise.
+     */
+    public boolean supports(AuthenticationToken token) {
+        return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass());
+    }
+
+    public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+
+        AuthenticationInfo info = doGetAuthenticationInfo(token);
+
+        if (info == null) {
+            if (log.isDebugEnabled()) {
+                String msg = "No authentication information found for submitted authentication token [" + token + "].  " +
+                        "Returning null.";
+                log.debug(msg);
+            }
+            return null;
+        }
+
+        CredentialsMatcher cm = getCredentialsMatcher();
+        if (cm != null) {
+            if (!cm.doCredentialsMatch(token, info)) {
+                String msg = "The credentials provided for account [" + token +
+                        "] did not match the expected credentials.";
+                throw new IncorrectCredentialsException(msg);
+            }
+        } else {
+            throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
+                    "credentials during authentication.  If you do not wish for credentials to be examined, you " +
+                    "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
+        }
+
+        return info;
+    }
+
+    /**
+     * Retrieves authentication data from an implementation-specific datasource (RDBMS, LDAP, etc) for the given
+     * authentication token.
+     *
+     * <p>For most datasources, this means just 'pulling' authentication data for an associated subject/user and nothing
+     * more and letting JSecurity do the rest.  But in some systems, this method could actually perform EIS specific
+     * log-in logic in addition to just retrieving data - it is up to the Realm implementation.
+     *
+     * <p>A <tt>null</tt> return value means that no account could be associated with the specified token.
+     *
+     * @param token the authentication token containing the user's principal and credentials.
+     * @return an {@link AuthenticationInfo} object containing account data resulting from the
+     *         authentication ONLY if the lookup is successful (i.e. account exists and is valid, etc.)
+     * @throws org.apache.ki.authc.AuthenticationException
+     *          if there is an error acquiring data or performing
+     *          realm-specific authentication logic for the specified <tt>token</tt>
+     */
+    protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
+
+    /**
+     * Default implementation that does nothing (no-op) and exists as a convenience mechanism in case subclasses
+     * wish to override it to implement realm-specific logout logic for the given user account logging out.</p>
+     * <p/>
+     * In a single-realm JSecurity configuration (most applications), the <code>principals</code> method
+     * argument will be the same as that which is contained in the <code>AuthenticationInfo</code> object returned by the
+     * {@link #doGetAuthenticationInfo} method (that is, {@link AuthenticationInfo#getPrincipals info.getPrincipals()}).
+     * <p/>
+     * In a multi-realm JSecurity configuration, the given <code>principals</code> method
+     * argument could contain principals returned by many realms.  Therefore the subclass implementation would need
+     * to know how to extract the principal(s) relevant to only itself and ignore other realms' principals.  This is
+     * usually done by calling {@link org.apache.ki.subject.PrincipalCollection#fromRealm(String) principals.fromRealm(name)},
+     * using the realm's own {@link Realm#getName() name}.
+     *
+     * @param principals the application-specific Subject/user identifier that is logging out.
+     */
+    public void onLogout(PrincipalCollection principals) {
+        //no-op, here for subclass override if desired.
+    }
+
+}

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthenticatingRealm.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,630 @@
+/*
+ * 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.ki.realm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.ki.authc.credential.CredentialsMatcher;
+import org.apache.ki.authz.AuthorizationException;
+import org.apache.ki.authz.AuthorizationInfo;
+import org.apache.ki.authz.AuthorizingAccount;
+import org.apache.ki.authz.Permission;
+import org.apache.ki.authz.UnauthorizedException;
+import org.apache.ki.authz.permission.PermissionResolver;
+import org.apache.ki.authz.permission.PermissionResolverAware;
+import org.apache.ki.authz.permission.WildcardPermissionResolver;
+import org.apache.ki.cache.Cache;
+import org.apache.ki.cache.CacheManager;
+import org.apache.ki.subject.PrincipalCollection;
+import org.apache.ki.util.Initializable;
+
+
+/**
+ * An <tt>AuthorizingRealm</tt> extends the <tt>AuthenticatingRealm</tt>'s capabilities by adding Authorization
+ * (access control) support.
+ *
+ * <p>This implementation will perform all role and permission checks automatically (and subclasses do not have to
+ * write this logic) as long as the
+ * {@link #getAuthorizationInfo(org.apache.ki.subject.PrincipalCollection)} method returns an
+ * {@link AuthorizationInfo}.  Please see that method's JavaDoc for an in-depth explanation.
+ *
+ * <p>If you find that you do not want to utilize the {@link AuthorizationInfo AuthorizationInfo} construct,
+ * you are of course free to subclass the {@link AuthenticatingRealm AuthenticatingRealm} directly instead and
+ * implement the remaining Realm interface methods directly.  You might do this if you want have better control
+ * over how the Role and Permission checks occur for your specific data source.  However, using AuthorizationInfo
+ * (and its default implementation {@link org.apache.ki.authz.SimpleAuthorizationInfo SimpleAuthorizationInfo}) is sufficient in the large
+ * majority of Realm cases.
+ *
+ * @author Les Hazlewood
+ * @author Jeremy Haile
+ * @see org.apache.ki.authz.SimpleAuthorizationInfo
+ * @since 0.2
+ */
+public abstract class AuthorizingRealm extends AuthenticatingRealm implements Initializable, PermissionResolverAware {
+
+    //TODO - complete JavaDoc
+
+    /*--------------------------------------------
+    |             C O N S T A N T S             |
+    ============================================*/
+    private static final Log log = LogFactory.getLog(AuthorizingRealm.class);
+
+    /**
+     * The default postfix appended to the realm name for caching AuthorizationInfos.
+     */
+    private static final String DEFAULT_AUTHORIZATION_CACHE_POSTFIX = "-authorization";
+
+    private static int INSTANCE_COUNT = 0;
+
+    /*--------------------------------------------
+    |    I N S T A N C E   V A R I A B L E S    |
+    ============================================*/
+    /**
+     * The cache used by this realm to store AuthorizationInfos associated with individual Subject principals.
+     */
+    private Cache authorizationCache = null;
+    private String authorizationCacheName = null;
+
+    private PermissionResolver permissionResolver = new WildcardPermissionResolver();
+
+    /*--------------------------------------------
+    |         C O N S T R U C T O R S           |
+    ============================================*/
+    public AuthorizingRealm() {
+    }
+
+    public AuthorizingRealm(CacheManager cacheManager) {
+        super(cacheManager);
+    }
+
+    public AuthorizingRealm(CredentialsMatcher matcher) {
+        super(matcher);
+    }
+
+    public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
+        super(cacheManager, matcher);
+    }
+
+    /*--------------------------------------------
+    |  A C C E S S O R S / M O D I F I E R S    |
+    ============================================*/
+    public void setAuthorizationCache(Cache authorizationCache) {
+        this.authorizationCache = authorizationCache;
+        if (this.authorizationCache != null) {
+            afterAuthorizationCacheSet();
+        }
+    }
+
+    public Cache getAuthorizationCache() {
+        return this.authorizationCache;
+    }
+
+    public String getAuthorizationCacheName() {
+        return authorizationCacheName;
+    }
+
+    public void setAuthorizationCacheName(String authorizationCacheName) {
+        this.authorizationCacheName = authorizationCacheName;
+    }
+
+    public PermissionResolver getPermissionResolver() {
+        return permissionResolver;
+    }
+
+    public void setPermissionResolver(PermissionResolver permissionResolver) {
+        this.permissionResolver = permissionResolver;
+    }
+
+    /*--------------------------------------------
+    |               M E T H O D S               |
+    ============================================*/
+    /**
+     * Initializes this realm and potentially enables a cache, depending on configuration.
+     *
+     * <p>When this method is called, the following logic is executed:
+     * <ol>
+     * <li>If the {@link #setAuthorizationCache cache} property has been set, it will be
+     * used to cache the AuthorizationInfo objects returned from {@link #getAuthorizationInfo}
+     * method invocations.
+     * All future calls to <tt>getAuthorizationInfo</tt> will attempt to use this cache first
+     * to alleviate any potentially unnecessary calls to an underlying data store.</li>
+     * <li>If the {@link #setAuthorizationCache cache} property has <b>not</b> been set,
+     * the {@link #setCacheManager cacheManager} property will be checked.
+     * If a <tt>cacheManager</tt> has been set, it will be used to create an authorization
+     * <tt>cache</tt>, and this newly created cache which will be used as specified in #1.</li>
+     * <li>If neither the {@link #setAuthorizationCache (org.jsecurity.cache.Cache) cache}
+     * or {@link #setCacheManager(org.apache.ki.cache.CacheManager) cacheManager}
+     * properties are set, caching will be disabled and authorization lookups will be delegated to
+     * subclass implementations for each authorization check.</li>
+     * </ol>
+     */
+    public final void init() {
+        initAuthorizationCache();
+    }
+
+    protected void afterCacheManagerSet() {
+        this.authorizationCache = null;
+        initAuthorizationCache();
+    }
+
+    protected void afterAuthorizationCacheSet() {
+    }
+
+    public void initAuthorizationCache() {
+        if (log.isTraceEnabled()) {
+            log.trace("Initializing authorization cache.");
+        }
+
+        Cache cache = getAuthorizationCache();
+
+        if (cache == null) {
+
+            if (log.isDebugEnabled()) {
+                log.debug("No cache implementation set.  Checking cacheManager...");
+            }
+
+            CacheManager cacheManager = getCacheManager();
+
+            if (cacheManager != null) {
+                String cacheName = getAuthorizationCacheName();
+                if (cacheName == null) {
+                    //Simple default in case they didn't provide one:
+                    cacheName = getClass().getName() + "-" + INSTANCE_COUNT++ + DEFAULT_AUTHORIZATION_CACHE_POSTFIX;
+                    setAuthorizationCacheName(cacheName);
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug("CacheManager [" + cacheManager + "] has been configured.  Building " +
+                            "authorization cache named [" + cacheName + "]");
+                }
+                cache = cacheManager.getCache(cacheName);
+                setAuthorizationCache(cache);
+            } else {
+                if (log.isInfoEnabled()) {
+                    log.info("No cache or cacheManager properties have been set.  Authorization caching is " +
+                            "disabled.");
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Returns an account's authorization-specific information for the specified <code>principals</code>,
+     * or <tt>null</tt> if no account could be found.  The resulting <code>AuthorizationInfo</code> object is used
+     * by the other method implementations in this class to automatically perform access control checks for the
+     * corresponding <code>Subject</code>.
+     *
+     * <p>This implementation obtains the actual <code>AuthorizationInfo</code> object from the subclass's
+     * implementation of
+     * {@link #doGetAuthorizationInfo(org.apache.ki.subject.PrincipalCollection) doGetAuthorizationInfo}, and then
+     * caches it for efficient reuse if caching is enabled (see below).
+     *
+     * <p>Invocations of this method should be thought of as completely orthogonal to acquiring
+     * {@link #getAuthenticationInfo(org.apache.ki.authc.AuthenticationToken) authenticationInfo}, since either could
+     * occur in any order.
+     *
+     * <p>For example, in &quot;Remember Me&quot; scenarios, the user identity is remembered (and
+     * assumed) for their current session and an authentication attempt during that session might never occur.
+     * But because their identity would be remembered, that is sufficient enough information to call this method to
+     * execute any necessary authorization checks.  For this reason, authentication and authorization should be
+     * loosely coupled and not depend on each other.
+     *
+     * <h4>Caching</h4>
+     *
+     * <p>The <code>AuthorizationInfo</code> values returned from this method are cached for performant reuse
+     * if caching is enabled.  Caching is enabled automatically when a <code>CacheManager</code> has been
+     * {@link #setCacheManager injected} and then the realm is {@link #init initialized}.  It can also be enabled by explictly
+     * calling {@link #initAuthorizationCache() initAuthorizationCache()}.
+     *
+     * <p>If caching is enabled, the authorization cache will be checked first and if found, will return the cached
+     * <code>AuthorizationInfo</code> immediately.  If caching is disabled, or there is a cache miss from the cache
+     * lookup, the authorization info will be looked up from the underlying data store via the
+     * {@link #doGetAuthorizationInfo(org.apache.ki.subject.PrincipalCollection)} method, which must be implemented by subclasses.
+     *
+     * <p><b>Please note:</b>  If caching is enabled and if any authorization data for an account is changed at
+     * runtime, such as adding or removing roles and/or permissions, the subclass imlementation should clear the
+     * cached AuthorizationInfo for that account via the
+     * {@link #clearCachedAuthorizationInfo(org.apache.ki.subject.PrincipalCollection) clearCachedAuthorizationInfo}
+     * method.  This ensures that the next call to <code>getAuthorizationInfo(PrincipalCollection)</code> will
+     * acquire the account's fresh authorization data, where it will then be cached for efficient reuse.  This
+     * ensures that stale authorization data will not be reused.
+     *
+     * @param principals the corresponding Subject's identifying principals with which to look up the Subject's
+     *                   <code>AuthorizationInfo</code>.
+     * @return the authorization information for the account associated with the specified <code>principals</code>,
+     *         or <tt>null</tt> if no account could be found.
+     */
+    public AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
+
+        if (principals == null) {
+            return null;
+        }
+
+        AuthorizationInfo info = null;
+
+        if (log.isTraceEnabled()) {
+            log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
+        }
+
+        Cache authzCache = getAuthorizationCache();
+        if (authzCache != null) {
+            if (log.isTraceEnabled()) {
+                log.trace("Attempting to retrieve the AuthorizationIfno from cache.");
+            }
+            Object key = getAuthorizationCacheKey(principals);
+            info = (AuthorizationInfo) authzCache.get(key);
+            if (log.isTraceEnabled()) {
+                if (info == null) {
+                    log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
+                } else {
+                    log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
+                }
+            }
+        }
+
+
+        if (info == null) {
+            // Call template method if tbe info was not found in a cache
+            info = doGetAuthorizationInfo(principals);
+            // If the info is not null and the cache has been created, then cache the authorization info.
+            if (info != null && authzCache != null) {
+                if (log.isTraceEnabled()) {
+                    log.trace("Caching authorization info for principals: [" + principals + "].");
+                }
+                Object key = getAuthorizationCacheKey(principals);
+                authzCache.put(key, info);
+            }
+        }
+
+        return info;
+    }
+
+    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
+        return principals;
+    }
+
+    /**
+     * Clears out the AuthorizationInfo cache entry for the specified account.
+     * <p/>
+     * This method is provided as a convenience to subclasses so they can invalidate a cache entry when they
+     * change an account's authorization data (add/remove roles or permissions) during runtime.  Because an account's
+     * AuthorizationInfo can be cached, there needs to be a way to invalidate the cache for only that account so that
+     * subsequent authorization operations don't used the (old) cached value if account data changes.
+     * <p/>
+     * After this method is called, the next authorization check for that same account will result in a call to
+     * {@link #getAuthorizationInfo(org.apache.ki.subject.PrincipalCollection) getAuthorizationInfo}, and the
+     * resulting return value will be cached before being returned so it can be reused for later authorization checks.
+     *
+     * @param principals the principals of the account for which to clear the cached AuthorizationInfo.
+     */
+    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
+        if ( principals == null ) {
+            return;
+        }
+
+        Cache cache = getAuthorizationCache();
+        //cache instance will be non-null if caching is enabled:
+        if (cache != null) {
+            Object key = getAuthorizationCacheKey(principals);
+            cache.remove(key);
+        }
+    }
+
+    /**
+     * Retrieves the AuthorizationInfo for the given principals from the underlying data store.  When returning
+     * an instance from this method, you might want to consider using an instance of
+     * {@link org.apache.ki.authz.SimpleAuthorizationInfo SimpleAuthorizationInfo}, as it is suitable in most cases.
+     *
+     * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved.
+     * @return the AuthorizationInfo associated with this principals.
+     * @see org.apache.ki.authz.SimpleAuthorizationInfo
+     */
+    protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
+
+    @SuppressWarnings({"unchecked"})
+    private Collection<Permission> getPermissions(AuthorizationInfo info) {
+        Set<Permission> permissions = new HashSet<Permission>();
+
+        if (info != null) {
+            if (info.getObjectPermissions() != null) {
+                permissions.addAll(info.getObjectPermissions());
+            }
+
+            if (info.getStringPermissions() != null) {
+                for (String strPermission : info.getStringPermissions()) {
+                    Permission permission = getPermissionResolver().resolvePermission(strPermission);
+                    permissions.add(permission);
+                }
+            }
+        }
+
+        if (permissions.isEmpty()) {
+            return Collections.EMPTY_SET;
+        } else {
+            return Collections.unmodifiableSet(permissions);
+        }
+    }
+
+    public boolean isPermitted(PrincipalCollection principals, String permission) {
+        Permission p = getPermissionResolver().resolvePermission(permission);
+        return isPermitted(principals, p);
+    }
+
+    public boolean isPermitted(PrincipalCollection principals, Permission permission) {
+        AuthorizationInfo info = getAuthorizationInfo(principals);
+        return isPermitted(permission, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    private boolean isPermitted(Permission permission, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).isPermitted(permission);
+        }
+
+        Collection<Permission> perms = getPermissions(info);
+        if (perms != null && !perms.isEmpty()) {
+            for (Permission perm : perms) {
+                if (perm.implies(permission)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean[] isPermitted(PrincipalCollection subjectIdentifier, String... permissions) {
+        List<Permission> perms = new ArrayList<Permission>(permissions.length);
+        for (String permString : permissions) {
+            perms.add(getPermissionResolver().resolvePermission(permString));
+        }
+        return isPermitted(subjectIdentifier, perms);
+    }
+
+    public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {
+        AuthorizationInfo info = getAuthorizationInfo(principals);
+        return isPermitted(permissions, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).isPermitted(permissions);
+        }
+
+        boolean[] result;
+        if (permissions != null && !permissions.isEmpty()) {
+            int size = permissions.size();
+            result = new boolean[size];
+            int i = 0;
+            for (Permission p : permissions) {
+                result[i++] = isPermitted(p, info);
+            }
+        } else {
+            result = new boolean[0];
+        }
+        return result;
+    }
+
+    public boolean isPermittedAll(PrincipalCollection subjectIdentifier, String... permissions) {
+        if (permissions != null && permissions.length > 0) {
+            Collection<Permission> perms = new ArrayList<Permission>(permissions.length);
+            for (String permString : permissions) {
+                perms.add(getPermissionResolver().resolvePermission(permString));
+            }
+            return isPermittedAll(subjectIdentifier, perms);
+        }
+        return false;
+    }
+
+    public boolean isPermittedAll(PrincipalCollection principal, Collection<Permission> permissions) {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        return info != null && isPermittedAll(permissions, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).isPermittedAll(permissions);
+        }
+
+        if (permissions != null && !permissions.isEmpty()) {
+            for (Permission p : permissions) {
+                if (!isPermitted(p, info)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public void checkPermission(PrincipalCollection subjectIdentifier, String permission) throws AuthorizationException {
+        Permission p = getPermissionResolver().resolvePermission(permission);
+        checkPermission(subjectIdentifier, p);
+    }
+
+    public void checkPermission(PrincipalCollection principal, Permission permission) throws AuthorizationException {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        checkPermission(permission, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void checkPermission(Permission permission, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            ((AuthorizingAccount) info).checkPermission(permission);
+        } else {
+            if (!isPermitted(permission, info)) {
+                String msg = "User is not permitted [" + permission + "]";
+                throw new UnauthorizedException(msg);
+            }
+        }
+    }
+
+    public void checkPermissions(PrincipalCollection subjectIdentifier, String... permissions) throws AuthorizationException {
+        if (permissions != null) {
+            for (String permString : permissions) {
+                checkPermission(subjectIdentifier, permString);
+            }
+        }
+    }
+
+    public void checkPermissions(PrincipalCollection principal, Collection<Permission> permissions) throws AuthorizationException {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        checkPermissions(permissions, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void checkPermissions(Collection<Permission> permissions, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            ((AuthorizingAccount) info).checkPermissions(permissions);
+        } else {
+            if (permissions != null && !permissions.isEmpty()) {
+                for (Permission p : permissions) {
+                    checkPermission(p, info);
+                }
+            }
+        }
+    }
+
+    public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        return hasRole(roleIdentifier, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).hasRole(roleIdentifier);
+        }
+        return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);
+    }
+
+    public boolean[] hasRoles(PrincipalCollection principal, List<String> roleIdentifiers) {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        boolean[] result = new boolean[roleIdentifiers != null ? roleIdentifiers.size() : 0];
+        if (info != null) {
+            result = hasRoles(roleIdentifiers, info);
+        }
+        return result;
+    }
+
+    @SuppressWarnings("deprecation")
+    protected boolean[] hasRoles(List<String> roleIdentifiers, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).hasRoles(roleIdentifiers);
+        }
+
+        boolean[] result;
+        if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
+            int size = roleIdentifiers.size();
+            result = new boolean[size];
+            int i = 0;
+            for (String roleName : roleIdentifiers) {
+                result[i++] = hasRole(roleName, info);
+            }
+        } else {
+            result = new boolean[0];
+        }
+        return result;
+    }
+
+    public boolean hasAllRoles(PrincipalCollection principal, Collection<String> roleIdentifiers) {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        return info != null && hasAllRoles(roleIdentifiers, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    private boolean hasAllRoles(Collection<String> roleIdentifiers, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            return ((AuthorizingAccount) info).hasAllRoles(roleIdentifiers);
+        }
+
+        if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
+            for (String roleName : roleIdentifiers) {
+                if (!hasRole(roleName, info)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public void checkRole(PrincipalCollection principal, String role) throws AuthorizationException {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        checkRole(role, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void checkRole(String role, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            ((AuthorizingAccount) info).checkRole(role);
+        } else {
+            if (!hasRole(role, info)) {
+                String msg = "User does not have role [" + role + "]";
+                throw new UnauthorizedException(msg);
+            }
+        }
+    }
+
+    public void checkRoles(PrincipalCollection principal, Collection<String> roles) throws AuthorizationException {
+        AuthorizationInfo info = getAuthorizationInfo(principal);
+        checkRoles(roles, info);
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void checkRoles(Collection<String> roles, AuthorizationInfo info) {
+        //todo Remove this once AuthorizingAccount class is deleted
+        if (info instanceof AuthorizingAccount) {
+            ((AuthorizingAccount) info).checkRoles(roles);
+        } else {
+            if (roles != null && !roles.isEmpty()) {
+                for (String roleName : roles) {
+                    checkRole(roleName, info);
+                }
+            }
+        }
+    }
+
+    /**
+     * If authorization caching is enabled, this will remove the AuthorizationInfo from the cache.
+     * Subclasses are free to override for additional behavior, but be sure to call <tt>super.onLogout</tt>
+     * to ensure cache cleanup.
+     *
+     * @param principals the application-specific Subject/user identifier.
+     */
+    public void onLogout(PrincipalCollection principals) {
+        clearCachedAuthorizationInfo(principals);
+    }
+}

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/AuthorizingRealm.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,86 @@
+/*
+ * 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.ki.realm;
+
+import org.apache.ki.cache.CacheManager;
+import org.apache.ki.cache.CacheManagerAware;
+
+
+/**
+ * <p>A very basic abstract extension point for the {@link Realm} interface that provides logging and caching support.
+ *
+ * <p>All actual Realm method implementations are left to subclasses.
+ *
+ * @author Les Hazlewood
+ * @since 0.9
+ */
+public abstract class CachingRealm implements Realm, CacheManagerAware {
+
+    //TODO - complete JavaDoc
+
+    private static int INSTANCE_COUNT = 0;
+
+    /*--------------------------------------------
+    |    I N S T A N C E   V A R I A B L E S    |
+    ============================================*/
+    private String name = getClass().getName() + "_" + INSTANCE_COUNT++;
+
+    private CacheManager cacheManager;
+
+    public CachingRealm() {
+    }
+
+    public CachingRealm(CacheManager cacheManager) {
+        setCacheManager(cacheManager);
+    }
+
+    /**
+     * Returns the <tt>CacheManager</tt> used for data caching to reduce EIS round trips, or <tt>null</tt> if
+     * caching is disabled.
+     *
+     * @return the <tt>CacheManager</tt> used for data caching to reduce EIS round trips, or <tt>null</tt> if
+     *         caching is disabled.
+     */
+    public CacheManager getCacheManager() {
+        return this.cacheManager;
+    }
+
+    /**
+     * Sets the <tt>CacheManager</tt> to be used for data caching to reduce EIS round trips.
+     *
+     * <p>This property is <tt>null</tt> by default, indicating that caching is turned off.
+     *
+     * @param authzInfoCacheManager the <tt>CacheManager</tt> to use for data caching, or <tt>null</tt> to disable caching.
+     */
+    public void setCacheManager(CacheManager authzInfoCacheManager) {
+        this.cacheManager = authzInfoCacheManager;
+        afterCacheManagerSet();
+    }
+
+    protected void afterCacheManagerSet() {
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/CachingRealm.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,109 @@
+/*
+ * 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.ki.realm;
+
+import org.apache.ki.authc.AuthenticationException;
+import org.apache.ki.authc.AuthenticationInfo;
+import org.apache.ki.authc.AuthenticationToken;
+import org.apache.ki.authz.Authorizer;
+
+
+/**
+ * A <tt>Realm</tt> is a security component that can access application-specific security entities
+ * such as users, roles, and permissions to determine authentication and authorization operations.
+ *
+ * <p><tt>Realm</tt>s usually have a 1-to-1 correspondance with a datasource such as a relational database,
+ * file sysetem, or other similar resource.  As such, implementations of this interface use datasource-specific APIs to
+ * determine authorization data (roles, permissions, etc), such as JDBC, File IO, Hibernate or JPA, or any other
+ * Data Access API.  They are essentially security-specific
+ * <a href="http://en.wikipedia.org/wiki/Data_Access_Object" target="_blank">DAO</a>s.
+ *
+ * <p>Because most of these datasources usually contain Subject (a.k.a. User) information such as usernames and
+ * passwords, a Realm can act as a pluggable authentication module in a
+ * <a href="http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules">PAM</a> configuration.  This allows a Realm to
+ * perform <i>both</i> authentication and authorization duties for a single datasource, which caters to the large
+ * majority of applications.  If for some reason you don't want your Realm implementation to perform authentication
+ * duties, you should override the {@link #supports(org.apache.ki.authc.AuthenticationToken)} method to always
+ * return <tt>false</tt>.
+ *
+ * <p>Because every application is different, security data such as users and roles can be
+ * represented in any number of ways.  JSecurity tries to maintain a non-intrusive development philosophy whenever
+ * possible - it does not require you to implement or extend any <tt>User</tt>, <tt>Group</tt> or <tt>Role</tt>
+ * interfaces or classes.
+ *
+ * <p>Instead, JSecurity allows applications to implement this interface to access environment-specific datasources
+ * and data model objects.  The implementation can then be plugged in to the application's JSecurity configuration.
+ * This modular technique abstracts away any environment/modeling details and allows JSecurity to be deployed in
+ * practically any application environment.
+ *
+ * <p>Most users will not implement the <tt>Realm</tt> interface directly, but will extend one of the subclasses,
+ * {@link org.apache.ki.realm.AuthenticatingRealm AuthenticatingRealm} or {@link org.apache.ki.realm.AuthorizingRealm}, greatly reducing the effort requird
+ * to implement a <tt>Realm</tt> from scratch.</p>
+ *
+ * @author Les Hazlewood
+ * @author Jeremy Haile
+ * @see org.apache.ki.realm.CachingRealm CachingRealm
+ * @see org.apache.ki.realm.AuthenticatingRealm AuthenticatingRealm
+ * @see org.apache.ki.realm.AuthorizingRealm AuthorizingRealm
+ * @see org.apache.ki.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator
+ * @since 0.1
+ */
+public interface Realm extends Authorizer {
+
+    /**
+     * Returns the (application-unique) name assigned to this <code>Realm</code>. All realms configured for a single
+     * application must have a unique name.
+     *
+     * @return the (application-unique) name assigned to this <code>Realm</code>.
+     */
+    String getName();
+
+    /**
+     * Returns <tt>true</tt> if this realm wishes to authenticate the Subject represented by the given
+     * {@link org.apache.ki.authc.AuthenticationToken AuthenticationToken} instance, <tt>false</tt> otherwise.
+     *
+     * <p>If this method returns <tt>false</tt>, it will not be called to authenticate the Subject represented by
+     * the token - more specifically, a <tt>false</tt> return value means this Realm instance's
+     * {@link #getAuthenticationInfo} method will not be invoked for that token.
+     *
+     * @param token the AuthenticationToken submitted for the authentication attempt
+     * @return <tt>true</tt> if this realm can/will authenticate Subjects represented by specified token,
+     *         <tt>false</tt> otherwise.
+     */
+    boolean supports(AuthenticationToken token);
+
+    /**
+     * Returns an account's authentication-specific information for the specified <tt>token</tt>,
+     * or <tt>null</tt> if no account could be found based on the <tt>token</tt>.
+     *
+     * <p>This method effectively represents a login attempt for the corresponding user with the underlying EIS datasource.
+     * Most implementations merely just need to lookup and return the account data only (as the method name implies)
+     * and let JSecurity do the rest, but implementations may of course perform eis specific login operations if so
+     * desired.
+     *
+     * @param token the application-specific representation of an account principal and credentials.
+     * @return the authentication information for the account associated with the specified <tt>token</tt>,
+     *         or <tt>null</tt> if no account could be found.
+     * @throws org.apache.ki.authc.AuthenticationException
+     *          if there is an error obtaining or constructing an AuthenticationInfo object based on the
+     *          specified <tt>token</tt> or implementation-specifc login behavior fails.
+     */
+    AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
+
+}
\ No newline at end of file

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/Realm.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ki.realm;
+
+import java.util.Collection;
+
+/**
+ * Enables JSecurity end-users to configure and initialize one or more {@link Realm Realm} instances
+ * in any manner desired.
+ * <p/>
+ * This interface exists to support environments where end-users may not wish to use JSecurity's default
+ * text-based configuration to create and configure realms, and instead wish to retrieve a realm configured in a
+ * proprietary manner.  An implementation of this interface can access that proprietary mechanism to retrieve the
+ * already-created <tt>Realm</tt>s.
+ *
+ * <p>The <code>Realm</code> instances returned will used to construct the application's
+ * {@link org.apache.ki.mgt.SecurityManager SecurityManager} instance.
+ *
+ * @since 0.9
+ */
+public interface RealmFactory {
+
+    /**
+     * Returns a collection of {@link Realm Realm} instances that will be used to construct
+     * the application's SecurityManager instance.
+     *
+     * <p>The order of the collection is important.  The {@link org.apache.ki.mgt.SecurityManager SecurityManager}
+     * implementation will consult the Realms during authentication (log-in) and authorization (access control)
+     * operations in the collection's <b>iteration order</b>.  That is, the resulting collection's
+     * {@link java.util.Iterator Iterator} determines the order in which Realms are used.
+     *
+     * @return the <code>Collection</code> of Realms that the application's <code>SecurityManager</code> will use
+     *         for security data access.
+     */
+    Collection<Realm> getRealms();
+
+}

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/RealmFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java?rev=752380&view=auto
==============================================================================
--- incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java (added)
+++ incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java Wed Mar 11 05:40:38 2009
@@ -0,0 +1,172 @@
+/*
+ * 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.ki.realm;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ki.authc.Account;
+import org.apache.ki.authc.AuthenticationException;
+import org.apache.ki.authc.AuthenticationInfo;
+import org.apache.ki.authc.AuthenticationToken;
+import org.apache.ki.authc.ExpiredCredentialsException;
+import org.apache.ki.authc.LockedAccountException;
+import org.apache.ki.authc.SimpleAccount;
+import org.apache.ki.authc.UsernamePasswordToken;
+import org.apache.ki.authz.AuthorizationInfo;
+import org.apache.ki.authz.SimpleAuthorizingAccount;
+import org.apache.ki.authz.SimpleRole;
+import org.apache.ki.subject.PrincipalCollection;
+import org.apache.ki.util.CollectionUtils;
+
+
+/**
+ * <p>A simple implementation of the {@link Realm Realm} interface that
+ * uses a set of configured user accounts and roles to support authentication and authorization.  Each account entry
+ * specifies the username, password, and roles for a user.  Roles can also be mapped
+ * to permissions and associated with users.</p>
+ *
+ * <p>User accounts and roles are stored in two {@link org.apache.ki.cache.Cache cache}s, so it is the Cache manager implementation that
+ * determines if this class stores all data in memory or spools to disk or clusters it, etc based on the
+ * Caches it creates.
+ *
+ * @author Jeremy Haile
+ * @author Les Hazlewood
+ * @since 0.1
+ */
+public class SimpleAccountRealm extends AuthorizingRealm {
+
+    //TODO - complete JavaDoc
+
+    protected Map<String, SimpleRole> roles = null;
+
+    public SimpleAccountRealm() {
+        init();
+    }
+
+    public SimpleAccountRealm(String name) {
+        setName(name);
+        init();
+    }
+
+    public void afterAuthorizationCacheSet() {
+        initRoleCache();
+        afterRoleCacheSet();
+    }
+
+    public void afterRoleCacheSet() {
+    }
+
+    protected void initRoleCache() {
+        if (getAuthorizationCache() == null) {
+            initAuthorizationCache();
+        }
+
+        this.roles = new HashMap<String, SimpleRole>();
+        accountAndRoleCachesCreated();
+    }
+
+    protected SimpleAccount getUser(String username) {
+        return (SimpleAccount) getAuthorizationCache().get(username);
+    }
+
+    public boolean accountExists(String username) {
+        return getUser(username) != null;
+    }
+
+    public void addAccount(String username, String password) {
+        addAccount(username, password, (String[])null);
+    }
+
+    public void addAccount(String username, String password, String... roles) {
+        Set<String> roleNames = CollectionUtils.asSet(roles);
+        SimpleAccount account = new SimpleAuthorizingAccount(username, password, getName(), roleNames, null);
+        add(account);
+    }
+
+    protected void add(SimpleAccount account) {
+        Object key = getAuthorizationCacheKey(account.getPrincipals());
+        getAuthorizationCache().put(key, account);
+    }
+
+    protected SimpleRole getRole(String rolename) {
+        return roles.get(rolename);
+    }
+
+    public boolean roleExists(String name) {
+        return getRole(name) != null;
+    }
+
+    public void addRole(String name) {
+        add(new SimpleRole(name));
+    }
+
+    protected void add(SimpleRole role) {
+        roles.put(role.getName(), role);
+    }
+
+    protected static Set<String> toSet(String delimited, String delimiter) {
+        if (delimited == null || delimited.trim().equals("")) {
+            return null;
+        }
+
+        Set<String> values = new HashSet<String>();
+        String[] rolenamesArray = delimited.split(delimiter);
+        for (String s : rolenamesArray) {
+            String trimmed = s.trim();
+            if (trimmed.length() > 0) {
+                values.add(trimmed);
+            }
+        }
+
+        return values;
+    }
+
+    protected void accountAndRoleCachesCreated() {
+    }
+
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
+        SimpleAccount account = (SimpleAccount) getAuthorizationCache().get(upToken.getUsername());
+
+        if( account != null ) {
+
+            if (account.isLocked()) {
+                throw new LockedAccountException("Account [" + account + "] is locked.");
+            }
+            if (account.isCredentialsExpired()) {
+                String msg = "The credentials for account [" + account + "] are expired";
+                throw new ExpiredCredentialsException(msg);
+            }
+            
+        }
+
+        return account;
+    }
+
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        return (Account) getAuthorizationCache().get(getAuthorizationCacheKey(principals));
+    }
+
+    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
+        return principals.fromRealm(getName()).iterator().next(); //returns the username
+    }
+}
\ No newline at end of file

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Id Author

Propchange: incubator/jsecurity/trunk/core/src/org/apache/ki/realm/SimpleAccountRealm.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain