JSEC-37 - architectural refactoring in preparation for 1.0 - simplified implementations and implemented some best practices based on Joshua Bloch's "Effective Java" book.

git-svn-id: https://svn.apache.org/repos/asf/incubator/jsecurity/trunk@735625 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/org/jsecurity/authc/Authenticator.java b/core/src/org/jsecurity/authc/Authenticator.java
index c98d2ed..ca9e38d 100644
--- a/core/src/org/jsecurity/authc/Authenticator.java
+++ b/core/src/org/jsecurity/authc/Authenticator.java
@@ -21,16 +21,15 @@
 /**
  * An Authenticator is responsible for authenticating accounts in an application.  It
  * is one of the primary entry points into the JSecurity API.
- *
- * <p>Although not a requirement, there is usually a single 'master' Authenticator configured for
+ * <p/>
+ * Although not a requirement, there is usually a single 'master' Authenticator configured for
  * an application.  Enabling Pluggable Authentication Module (PAM) behavior
- * (Two Phase Commit, etc.) is usually achieved by the single <tt>Authenticator</tt> coordinating
- * and interacting with an application-configured set of
- * {@link org.jsecurity.realm.Realm Realm}s.
- *
- * <p>Note that most JSecurity users will not interact with an <tt>Authenticator</tt> instance directly.  JSecurity's
- * default architecture is based on an overall <tt>SecurityManager</tt> which typically wraps an
- * <tt>Authenticator</tt> instance.
+ * (Two Phase Commit, etc.) is usually achieved by the single {@code Authenticator} coordinating
+ * and interacting with an application-configured set of {@link org.jsecurity.realm.Realm Realm}s.
+ * <p/>
+ * Note that most JSecurity users will not interact with an {@code Authenticator} instance directly.
+ * JSecurity's default architecture is based on an overall {@code SecurityManager} which typically
+ * wraps an {@code Authenticator} instance.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
@@ -42,22 +41,22 @@
 public interface Authenticator {
 
     /**
-     * Authenticates a user based on the submitted <tt>authenticationToken</tt>.
+     * Authenticates a user based on the submitted {@code AuthenticationToken}.
+     * <p/>
+     * If the authentication is successful, an {@link AuthenticationInfo} instance is returned that represents the
+     * user's account data relevant to JSecurity.  This returned object is generally used in turn to construct a
+     * {@code Subject} representing a more complete security-specific 'view' of an account that also allows access to
+     * a {@code Session}.
      *
-     * <p>If the authentication is successful, an {@link AuthenticationInfo}
-     * object is returned that represents the user's account data relevant to JSecurity.  This returned object is
-     * generally used in turn to construct a <tt>Subject</tt> representing that user's identity and
-     * access to a <tt>Session</tt>
-     *
-     * @param authenticationToken any representation of a user's principals and credentials
-     *                            submitted during an authentication attempt.
+     * @param authenticationToken any representation of a user's principals and credentials submitted during an
+     *                            authentication attempt.
      * @return the AuthenticationInfo representing the authenticating user's account data.
      * @throws AuthenticationException if there is any problem during the authentication process.
-     *                                 See the specific exceptions listed below to as examples of what could happen in order
-     *                                 to accurately handle these problems and to notify the user in an appropriate manner why
-     *                                 the authentication attempt failed.  Realize an implementation of this interface may or may
-     *                                 not throw those listed or may throw other AuthenticationExceptions, but the list shows
-     *                                 the most common ones.
+     *                                 See the specific exceptions listed below to as examples of what could happen
+     *                                 in order to accurately handle these problems and to notify the user in an
+     *                                 appropriate manner why the authentication attempt failed.  Realize an
+     *                                 implementation of this interface may or may not throw those listed or may
+     *                                 throw other AuthenticationExceptions, but the list shows the most common ones.
      * @see ExpiredCredentialsException
      * @see IncorrectCredentialsException
      * @see ExcessiveAttemptsException
diff --git a/core/src/org/jsecurity/crypto/BlowfishCipher.java b/core/src/org/jsecurity/crypto/BlowfishCipher.java
index 38fa956..45c210b 100644
--- a/core/src/org/jsecurity/crypto/BlowfishCipher.java
+++ b/core/src/org/jsecurity/crypto/BlowfishCipher.java
@@ -94,9 +94,10 @@
      * Returns the default {@link Key Key} to use for symmetric encryption and decryption if one is not specified during
      * encryption/decryption.  For truly secure applications,
      * you should always specify your own key via the {@link #setKey(java.security.Key) setKey} method.
+     *
      * @return the {@link Key Key} to use for symmetric encryption and decryption.
      * @see #encrypt(byte[], byte[])
-     * @see #decrypt(byte[], byte[]) 
+     * @see #decrypt(byte[], byte[])
      */
     public Key getKey() {
         return key;
@@ -106,6 +107,7 @@
      * Sets the internal default {@link Key Key} to use for symmetric encryption and decryption if one is not
      * specified during encryption/decryption.   For truly secure applications, you should always specify your own
      * key via this method.
+     *
      * @param key the key to use for symmetric encryption and decryption.
      * @see #encrypt(byte[], byte[])
      * @see #decrypt(byte[], byte[])
@@ -142,9 +144,10 @@
     /**
      * Returns a new {@link javax.crypto.Cipher Cipher} instance to use for encryption/decryption operations, based on
      * the {@link #TRANSFORMATION_STRING TRANSFORMATION_STRING} constant.
+     *
      * @return a new Cipher instance.
      * @throws IllegalStateException if a new Cipher instance cannot be constructed based on the
-     * {@link #TRANSFORMATION_STRING TRANSFORMATION_STRING} constant.
+     *                               {@link #TRANSFORMATION_STRING TRANSFORMATION_STRING} constant.
      */
     protected javax.crypto.Cipher newCipherInstance() throws IllegalStateException {
         try {
@@ -163,8 +166,8 @@
      * potential {@link InvalidKeyException InvalidKeyException} that might arise.
      *
      * @param cipher the JDK Cipher to {@link javax.crypto.Cipher#init(int, java.security.Key) init}.
-     * @param mode the Cipher mode
-     * @param key the Cipher's Key
+     * @param mode   the Cipher mode
+     * @param key    the Cipher's Key
      */
     protected void init(javax.crypto.Cipher cipher, int mode, java.security.Key key) {
         try {
@@ -178,8 +181,9 @@
     /**
      * Calls the {@link javax.crypto.Cipher#doFinal(byte[]) doFinal(bytes)} method, propagating any exception that
      * might arise in an {@link IllegalStateException IllegalStateException}
+     *
      * @param cipher the JDK Cipher to finalize (perform the actual cryption)
-     * @param bytes the bytes to crypt
+     * @param bytes  the bytes to crypt
      * @return the resulting crypted byte array.
      */
     protected byte[] crypt(javax.crypto.Cipher cipher, byte[] bytes) {
@@ -195,9 +199,10 @@
      * Calls the {@link #init(javax.crypto.Cipher, int, java.security.Key)} and then
      * {@link #crypt(javax.crypto.Cipher, byte[])}.  Ensures that the key is never null by using the
      * {@link #getKey() default key} if the method argument key is <code>null</code>.
+     *
      * @param bytes the bytes to crypt
-     * @param mode the JDK Cipher mode
-     * @param key the key to use to do the cryption.  If <code>null</code> the {@link #getKey() default key} will be used.
+     * @param mode  the JDK Cipher mode
+     * @param key   the key to use to do the cryption.  If <code>null</code> the {@link #getKey() default key} will be used.
      * @return the resulting crypted byte array
      */
     protected byte[] crypt(byte[] bytes, int mode, byte[] key) {
@@ -216,7 +221,8 @@
 
     /**
      * Generates a new {@link Key Key} suitable for this Cipher by calling
-     * {@link #generateNewKey() generateNewKey(128)} (uses a 128 bit size by default).
+     * {@link #generateNewKey(int) generateNewKey(128)} (uses a 128 bit size by default).
+     *
      * @return a new {@link Key Key}, 128 bits in length.
      */
     public static Key generateNewKey() {
@@ -226,6 +232,7 @@
     /**
      * Generates a new {@link Key Key} of the specified size suitable for this Cipher
      * (based on the {@link #ALGORITHM ALGORITHM} using the JDK {@link KeyGenerator KeyGenerator}.
+     *
      * @param keyBitSize the bit size of the key to create
      * @return the created key suitable for use with this Cipher.
      */
@@ -243,6 +250,7 @@
 
     /**
      * Simple test main method to ensure functionality is correct.  Should really be moved to a proper test case.
+     *
      * @param unused ignored
      * @throws Exception if anything unexpected happens.
      */
diff --git a/core/src/org/jsecurity/crypto/Cipher.java b/core/src/org/jsecurity/crypto/Cipher.java
index 96af814..4fb37b8 100644
--- a/core/src/org/jsecurity/crypto/Cipher.java
+++ b/core/src/org/jsecurity/crypto/Cipher.java
@@ -23,10 +23,10 @@
  * an uninterpretable format.  The resulting encrypted output is only able to be converted back to original form with
  * a <tt>Key</tt> as well.
  *
- * <p>In what is known as <em>Symmetric</em> <tt>Cipher</tt>s, the <tt>Key</tt> used to encrypt the source is the same
+ * <p>For what is known as <em>Symmetric</em> <tt>Cipher</tt>s, the <tt>Key</tt> used to encrypt the source is the same
  * as (or trivially similar to) the <tt>Key</tt> used to decrypt it.
  *
- * <p>In <em>Assymetric</em> <tt>Cipher</tt>s, the encryption <tt>Key</tt> is not the same as the decryption <tt>Key</tt>.
+ * <p>For <em>Assymetric</em> <tt>Cipher</tt>s, the encryption <tt>Key</tt> is not the same as the decryption <tt>Key</tt>.
  * The most common type of Assymetric Ciphers are based on what is called public/private key pairs:
  *
  * <p>A <em>private</em> key is known only to a single party, and as its name implies, is supposed be kept very private
diff --git a/core/src/org/jsecurity/subject/AbstractRememberMeManager.java b/core/src/org/jsecurity/mgt/AbstractRememberMeManager.java
similarity index 94%
rename from core/src/org/jsecurity/subject/AbstractRememberMeManager.java
rename to core/src/org/jsecurity/mgt/AbstractRememberMeManager.java
index d417266..2ecdfdc 100644
--- a/core/src/org/jsecurity/subject/AbstractRememberMeManager.java
+++ b/core/src/org/jsecurity/mgt/AbstractRememberMeManager.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.jsecurity.subject;
+package org.jsecurity.mgt;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -31,6 +31,7 @@
 import org.jsecurity.io.DefaultSerializer;
 import org.jsecurity.io.SerializationException;
 import org.jsecurity.io.Serializer;
+import org.jsecurity.subject.PrincipalCollection;
 
 /**
  * Abstract implementation of the <code>RememberMeManager</code> interface that handles
@@ -47,7 +48,9 @@
 
     //TODO - complete JavaDoc
 
-    /** private inner log instance. */
+    /**
+     * private inner log instance.
+     */
     private static final Log log = LogFactory.getLog(AbstractRememberMeManager.class);
 
     private Serializer serializer = new DefaultSerializer();
@@ -207,20 +210,22 @@
             }
             return principals;
 
-        } catch( Exception e ) {
-            return onRememberedPrincipalFailure( e );
+        } catch (Exception e) {
+            return onRememberedPrincipalFailure(e);
         }
     }
 
     /**
      * Called when an exception is thrown while trying to retrieve principals.  The default implementation logs a
-     * warning and forgets the problem identity.  This most commonly would occur when an encryption key is
-     * updated and old principals are retrieved that have been encrypted with the previous key.
+     * warning and forgets ('unremembers') the problem identity by calling {@link #forgetIdentity() forgetIdentity()}.
+     * This most commonly would occur when an encryption key is updated and old principals are retrieved that have
+     * been encrypted with the previous key.\
+     *
      * @param e the exception that was thrown.
-     * @return the principal collection to be returned.
+     * @return <code>null</code> in all cases.
      */
     protected PrincipalCollection onRememberedPrincipalFailure(Exception e) {
-        if(log.isWarnEnabled() ) {
+        if (log.isWarnEnabled()) {
             log.warn("There was a failure while trying to retrieve remembered principals.  This could be due to a " +
                     "configuration problem or corrupted principals.  This could also be due to a recently " +
                     "changed encryption key.  The remembered identity will be forgotten and not used for this " +
diff --git a/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java b/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
index 9182f27..1584ae4 100644
--- a/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
@@ -51,10 +51,11 @@
 
     /**
      * Default no-arg constructor that initializes its internal
-     * <code>authenticator</code> instance by just calling {@link #createAuthenticator() createAuthenticator()}.
+     * <code>authenticator</code> instance to a
+     * {@link org.jsecurity.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator}.
      */
     public AuthenticatingSecurityManager() {
-        setAuthenticator(createAuthenticator());
+        this.authenticator = new ModularRealmAuthenticator();
     }
 
     /**
@@ -88,17 +89,6 @@
     }
 
     /**
-     * Creates the default <code>Authenticator</code> instance to use at startup.  This simple default implementation
-     * merely returns <code>new {@link ModularRealmAuthenticator ModularRealmAuthenticator}()</code>.
-     *
-     * @return the default <code>Authenticator</code> instance to use at startup.
-     * @since 1.0
-     */
-    protected Authenticator createAuthenticator() {
-        return new ModularRealmAuthenticator();
-    }
-
-    /**
      * Sets the {@link org.jsecurity.authc.pam.ModularAuthenticationStrategy ModularAuthenticationStrategy} to use
      * in multi-realm environments.
      *
@@ -149,6 +139,16 @@
         ((AuthenticationListenerRegistrar) this.authenticator).setAuthenticationListeners(listeners);
     }
 
+    public void add(AuthenticationListener listener) {
+        assertAuthenticatorListenerSupport();
+        ((AuthenticationListenerRegistrar) this.authenticator).add(listener);
+    }
+
+    public boolean remove(AuthenticationListener listener) {
+        return (this.authenticator instanceof AuthenticationListenerRegistrar) &&
+                ((AuthenticationListenerRegistrar) this.authenticator).remove(listener);
+    }
+
     /**
      * Ensures that <code>this.authenticator</code> implements the
      * {@link org.jsecurity.authc.AuthenticationListenerRegistrar AuthenticationListenerRegistrar} interface to ensure
@@ -164,18 +164,6 @@
         }
     }
 
-    public void add(AuthenticationListener listener) {
-        assertAuthenticatorListenerSupport();
-        Authenticator authc = getAuthenticator();
-        ((AuthenticationListenerRegistrar) authc).add(listener);
-    }
-
-    public boolean remove(AuthenticationListener listener) {
-        Authenticator authc = getAuthenticator();
-        return (authc instanceof AuthenticationListenerRegistrar) &&
-                ((AuthenticationListenerRegistrar) authc).remove(listener);
-    }
-
     /**
      * Immediately calls {@link RealmSecurityManager#setRealms(java.util.Collection) super.setRealms} and then
      * additionally passes on those realms to the internal delegate <code>Authenticator</code> instance so
diff --git a/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java b/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
index 6739979..c755c49 100644
--- a/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
@@ -52,14 +52,14 @@
     /**
      * The wrapped instance to which all of this <tt>SecurityManager</tt> authorization calls are delegated.
      */
-    protected Authorizer authorizer;
+    private Authorizer authorizer;
 
     /**
-     * Default no-arg constructor that initializes its internal <code>authorizer</code> instance by just
-     * calling {@link #createAuthorizer() createAuthorizer()}.
+     * Default no-arg constructor that initializes an internal default
+     * {@link ModularRealmAuthorizer ModularRealmAuthorizer}.
      */
     public AuthorizingSecurityManager() {
-        setAuthorizer(createAuthorizer());
+        this.authorizer = new ModularRealmAuthorizer();
     }
 
     /**
@@ -88,18 +88,6 @@
     }
 
     /**
-     * Creates a new {@link Authorizer Authorizer} instance to be used by this <code>AuthorizingSecurityManager</code> instance.
-     * <p/>
-     * This default implementation merely returns
-     * <code>new {@link org.jsecurity.authz.ModularRealmAuthorizer ModularRealmAuthorizer}()</code>
-     *
-     * @return a new {@link Authorizer Authorizer} instance to be used by this <code>AuthorizingSecurityManager</code> instance.
-     */
-    protected Authorizer createAuthorizer() {
-        return new ModularRealmAuthorizer();
-    }
-
-    /**
      * Sets the <tt>PermissionResolver</tt> instance that will be passed on to the underlying default wrapped
      * {@link Authorizer Authorizer}.
      *
@@ -140,9 +128,8 @@
      */
     public void setRealms(Collection<Realm> realms) {
         super.setRealms(realms);
-        Authorizer authz = getAuthorizer();
-        if (authz instanceof ModularRealmAuthorizer) {
-            ((ModularRealmAuthorizer) authz).setRealms(realms);
+        if (this.authorizer instanceof ModularRealmAuthorizer) {
+            ((ModularRealmAuthorizer) this.authorizer).setRealms(realms);
         }
     }
 
@@ -176,62 +163,62 @@
     }
 
     public boolean isPermitted(PrincipalCollection principals, String permissionString) {
-        return getAuthorizer().isPermitted(principals, permissionString);
+        return this.authorizer.isPermitted(principals, permissionString);
     }
 
     public boolean isPermitted(PrincipalCollection principals, Permission permission) {
-        return getAuthorizer().isPermitted(principals, permission);
+        return this.authorizer.isPermitted(principals, permission);
     }
 
     public boolean[] isPermitted(PrincipalCollection principals, String... permissions) {
-        return getAuthorizer().isPermitted(principals, permissions);
+        return this.authorizer.isPermitted(principals, permissions);
     }
 
     public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {
-        return getAuthorizer().isPermitted(principals, permissions);
+        return this.authorizer.isPermitted(principals, permissions);
     }
 
     public boolean isPermittedAll(PrincipalCollection principals, String... permissions) {
-        return getAuthorizer().isPermittedAll(principals, permissions);
+        return this.authorizer.isPermittedAll(principals, permissions);
     }
 
     public boolean isPermittedAll(PrincipalCollection principals, Collection<Permission> permissions) {
-        return getAuthorizer().isPermittedAll(principals, permissions);
+        return this.authorizer.isPermittedAll(principals, permissions);
     }
 
     public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {
-        getAuthorizer().checkPermission(principals, permission);
+        this.authorizer.checkPermission(principals, permission);
     }
 
     public void checkPermission(PrincipalCollection principals, Permission permission) throws AuthorizationException {
-        getAuthorizer().checkPermission(principals, permission);
+        this.authorizer.checkPermission(principals, permission);
     }
 
     public void checkPermissions(PrincipalCollection principals, String... permissions) throws AuthorizationException {
-        getAuthorizer().checkPermissions(principals, permissions);
+        this.authorizer.checkPermissions(principals, permissions);
     }
 
     public void checkPermissions(PrincipalCollection principals, Collection<Permission> permissions) throws AuthorizationException {
-        getAuthorizer().checkPermissions(principals, permissions);
+        this.authorizer.checkPermissions(principals, permissions);
     }
 
     public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
-        return getAuthorizer().hasRole(principals, roleIdentifier);
+        return this.authorizer.hasRole(principals, roleIdentifier);
     }
 
     public boolean[] hasRoles(PrincipalCollection principals, List<String> roleIdentifiers) {
-        return getAuthorizer().hasRoles(principals, roleIdentifiers);
+        return this.authorizer.hasRoles(principals, roleIdentifiers);
     }
 
     public boolean hasAllRoles(PrincipalCollection principals, Collection<String> roleIdentifiers) {
-        return getAuthorizer().hasAllRoles(principals, roleIdentifiers);
+        return this.authorizer.hasAllRoles(principals, roleIdentifiers);
     }
 
     public void checkRole(PrincipalCollection principals, String role) throws AuthorizationException {
-        getAuthorizer().checkRole(principals, role);
+        this.authorizer.checkRole(principals, role);
     }
 
     public void checkRoles(PrincipalCollection principals, Collection<String> roles) throws AuthorizationException {
-        getAuthorizer().checkRoles(principals, roles);
+        this.authorizer.checkRoles(principals, roles);
     }
 }
diff --git a/core/src/org/jsecurity/mgt/CachingSecurityManager.java b/core/src/org/jsecurity/mgt/CachingSecurityManager.java
index db7f5d8..683baa2 100644
--- a/core/src/org/jsecurity/mgt/CachingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/CachingSecurityManager.java
@@ -18,8 +18,6 @@
  */
 package org.jsecurity.mgt;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.jsecurity.cache.CacheManager;
 import org.jsecurity.cache.CacheManagerAware;
 import org.jsecurity.cache.DefaultCacheManager;
@@ -27,13 +25,12 @@
 import org.jsecurity.util.LifecycleUtils;
 
 /**
- * A very basic extension point for the SecurityManager interface that merely provides logging and caching
- * support.  All <tt>SecurityManager</tt> method implementations are left to subclasses.
+ * A very basic starting point for the SecurityManager interface that merely provides logging and caching
+ * support.  All actual {@code SecurityManager} method implementations are left to subclasses.
  *
- * <p>Upon instantiation, a sensible default {@link CacheManager CacheManager} will be created automatically via the
- * {@link #createCacheManager() createCacheManager() method.  This <code>CacheManager</code>
- * can then be used by subclass implementations and children components for use to achieve better application
- * performance.
+ * <p>Upon instantiation, a sensible default {@link CacheManager CacheManager} will be created automatically.  This
+ * {@code CacheManager} can then be used by subclass implementations and children components for use to achieve better
+ * application performance if so desired.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
@@ -42,20 +39,15 @@
 public abstract class CachingSecurityManager implements SecurityManager, Destroyable, CacheManagerAware {
 
     /**
-     * Internal private static log instance.
-     */
-    private static final Log log = LogFactory.getLog(CachingSecurityManager.class);
-
-    /**
      * The CacheManager to use to perform caching operations to enhance performance.  Can be null.
      */
-    protected CacheManager cacheManager;
+    private CacheManager cacheManager;
 
     /**
      * Default no-arg constructor that will automatically attempt to initialize a default cacheManager
      */
     public CachingSecurityManager() {
-        setCacheManager(createCacheManager());
+        this.cacheManager = new DefaultCacheManager();
     }
 
     /**
@@ -93,24 +85,6 @@
     }
 
     /**
-     * Creates a {@link CacheManager CacheManager} instance to be used by this <code>SecurityManager</code>
-     * and potentially any of its children components.
-     * <p/>
-     * This default implementation returns a new
-     * {@link org.jsecurity.cache.DefaultCacheManager DefaultCacheManager}, which uses in-memory (memory-leak safe)
-     * caches which are production safe.
-     * <p/>
-     * This can be overridden by subclasses for a different implementation, but it is often easier to set a
-     * different implementation via the {@link #setCacheManager(org.jsecurity.cache.CacheManager) setCacheManager}
-     * method, for example in code or Dependency Injection frameworks (a la Spring or JEE 3).
-     *
-     * @return a newly created <code>CacheManager</code> instance.
-     */
-    protected CacheManager createCacheManager() {
-        return new DefaultCacheManager();
-    }
-
-    /**
      * First calls {@link #beforeCacheManagerDestroyed() beforeCacheManagerDestroyed()} to allow subclasses to clean up
      * first, then calls {@link #destroyCacheManager() destroyCacheManager()} to clean up the internal
      * {@link CacheManager CacheManager}.
diff --git a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
index 5487675..2041a97 100644
--- a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
@@ -21,17 +21,19 @@
 import org.apache.commons.logging.Log;

 import org.apache.commons.logging.LogFactory;

 import org.jsecurity.authc.*;

+import org.jsecurity.authz.AuthorizationException;

 import org.jsecurity.authz.Authorizer;

 import org.jsecurity.crypto.Cipher;

 import org.jsecurity.realm.Realm;

 import org.jsecurity.session.InvalidSessionException;

 import org.jsecurity.session.Session;

-import org.jsecurity.subject.AbstractRememberMeManager;

+import org.jsecurity.session.mgt.DelegatingSession;

 import org.jsecurity.subject.PrincipalCollection;

-import org.jsecurity.subject.RememberMeManager;

 import org.jsecurity.subject.Subject;

 import org.jsecurity.util.ThreadContext;

 

+import java.io.Serializable;

+import java.net.InetAddress;

 import java.util.Collection;

 

 /**

@@ -42,11 +44,9 @@
  * implementation.</p>

  *

  * <p>To greatly reduce and simplify configuration, this implementation (and its superclasses) will

- * create suitable defaults for <em>all</em> of its required dependencies.  Therefore, you only need to override

- * attributes for custom behavior.  But, note the following:</p>

- *

- * <p>Unless you're happy with the default simple {@link org.jsecurity.realm.text.PropertiesRealm properties file}-based realm, which may or

- * may not be flexible enough for enterprise applications, you might want to specify at least one custom

+ * create suitable defaults for all of its required dependencies, <em>except</em> the required one or more

+ * {@link Realm Realm}s.  Because <code>Realm</code> implementations usually interact with an application's data model,

+ * they are almost always application specific;  you will want to specify at least one custom

  * <tt>Realm</tt> implementation that 'knows' about your application's data/security model

  * (via {@link #setRealm} or one of the overloaded constructors).  All other attributes in this class hierarchy

  * will have suitable defaults for most enterprise applications.</p>

@@ -58,7 +58,7 @@
  *

  * <p>Because RememberMe services are inherently client tier-specific and

  * therefore aplication-dependent, if you want <tt>RememberMe</tt> services enabled, you will have to specify an

- * instance yourself via the {@link #setRememberMeManager(org.jsecurity.subject.RememberMeManager) setRememberMeManager}

+ * instance yourself via the {@link #setRememberMeManager(RememberMeManager) setRememberMeManager}

  * mutator.  However if you're reading this JavaDoc with the

  * expectation of operating in a Web environment, take a look at the

  * {@link org.jsecurity.web.DefaultWebSecurityManager DefaultWebSecurityManager} implementation, which

@@ -85,8 +85,8 @@
      * Default no-arg constructor.

      */

     public DefaultSecurityManager() {

+        setSubjectFactory(new DefaultSubjectFactory());

         setSubjectBinder(new SessionSubjectBinder());

-        setSubjectFactory(new DefaultSubjectFactory(this));

     }

 

     /**

@@ -115,6 +115,9 @@
 

     public void setSubjectFactory(SubjectFactory subjectFactory) {

         this.subjectFactory = subjectFactory;

+        if (this.subjectFactory instanceof SecurityManagerAware) {

+            ((SecurityManagerAware) this.subjectFactory).setSecurityManager(this);

+        }

     }

 

     public SubjectBinder getSubjectBinder() {

@@ -134,14 +137,13 @@
     }

 

     private AbstractRememberMeManager getRememberMeManagerForCipherAttributes() {

-        RememberMeManager rmm = getRememberMeManager();

-        if (!(rmm instanceof AbstractRememberMeManager)) {

+        if (!(this.rememberMeManager instanceof AbstractRememberMeManager)) {

             String msg = "The convenience passthrough methods for setting remember me cipher attributes " +

                     "are only available when the underlying RememberMeManager implementation is a subclass of " +

                     AbstractRememberMeManager.class.getName() + ".";

             throw new IllegalStateException(msg);

         }

-        return (AbstractRememberMeManager) rmm;

+        return (AbstractRememberMeManager) this.rememberMeManager;

     }

 

     public void setRememberMeCipher(Cipher cipher) {

@@ -185,8 +187,32 @@
     }

 

     protected Subject createSubject() {

-        PrincipalCollection principals = getRememberedIdentity();

-        return getSubjectFactory().createSubject(principals, null, false, null);

+        Subject subject = null;

+

+        Serializable sessionId = ThreadContext.getSessionId();

+        if (sessionId != null) {

+            try {

+                subject = getSubjectBySessionId(sessionId);

+            } catch (InvalidSessionException e) {

+                if (log.isDebugEnabled()) {

+                    log.debug("Session id referenced on the current thread [" + sessionId + "] is invalid.  " +

+                            "Ignoring and creating a new Subject instance to continue.  This message can be " +

+                            "safely ignored.", e);

+                }

+            } catch (AuthorizationException e) {

+                if (log.isWarnEnabled()) {

+                    log.warn("Session id referenced on the current thread [" + sessionId + "] is not allowed to be " +

+                            "referenced.  Ignoring and creating a Subject instance without a session to continue.", e);

+                }

+            }

+        }

+

+        if (subject == null) {

+            PrincipalCollection principals = getRememberedIdentity();

+            return getSubjectFactory().createSubject(principals, null, false, null);

+        }

+

+        return subject;

     }

 

     /**

@@ -405,4 +431,62 @@
     public Subject getSubject() {

         return getSubject(true);

     }

+

+    protected PrincipalCollection getPrincipals(Session session) {

+        return (PrincipalCollection) session.getAttribute(SessionSubjectBinder.PRINCIPALS_SESSION_KEY);

+    }

+

+    protected boolean isAuthenticated(Session session, PrincipalCollection principals) {

+        if (principals != null) {

+            Boolean authc = (Boolean) session.getAttribute(SessionSubjectBinder.AUTHENTICATED_SESSION_KEY);

+            return authc != null && authc;

+        }

+        return false;

+    }

+

+    /**

+     * Acquires the {@link Subject Subject} that owns the {@link Session Session} with the specified {@code sessionId}.

+     *

+     * <p><b>Although simple in concept, this method provides incredibly powerful functionality:</b>

+     *

+     * <p>The ability to reference a {@code Subject} and their server-side session

+     * <em>across clients of different mediums</em> such as web applications, Java applets,

+     * standalone C# clients over XMLRPC and/or SOAP, and many others. This is a <em>huge</em>

+     * benefit in heterogeneous enterprise applications.

+     *

+     * <p>To maintain session integrity across client mediums, the {@code sessionId} <b>must</b> be transmitted

+     * to all client mediums securely (e.g. over SSL) to prevent man-in-the-middle attacks.  This

+     * is nothing new - all web applications are susceptible to the same problem when transmitting

+     * {@link javax.servlet.http.Cookie Cookie}s or when using URL rewriting.  As long as the

+     * {@code sessionId} is transmitted securely, session integrity can be maintained.

+     *

+     * @param sessionId the id of the session that backs the desired Subject being acquired.

+     * @return the {@code Subject} that owns the {@code Session Session} with the specified {@code sessionId}

+     * @throws org.jsecurity.session.InvalidSessionException

+     *          if the session identified by <tt>sessionId</tt> has

+     *          been stopped, expired, or doesn't exist.

+     * @throws org.jsecurity.authz.AuthorizationException

+     *          if the executor of this method is not allowed to acquire the owning {@code Subject}.  The reason

+     *          for the exception is implementation-specific and could be for any number of reasons.  A common

+     *          reason in many systems would be if one host tried to acquire a {@code Subject} based on a

+     *          {@code Session} that originated on an entirely different host (although it is not a JSecurity

+     *          requirement this scenario is disallowed - its just an example that <em>may</em> throw an Exception in

+     *          some systems).

+     * @see org.jsecurity.authz.HostUnauthorizedException

+     * @since 1.0

+     */

+    protected Subject getSubjectBySessionId(Serializable sessionId) throws InvalidSessionException, AuthorizationException {

+        if (!isValid(sessionId)) {

+            String msg = "Specified id [" + sessionId + "] does not correspond to a valid Session  It either " +

+                    "does not exist or the corresponding session has been stopped or expired.";

+            throw new InvalidSessionException(msg, sessionId);

+        }

+

+        Session existing = new DelegatingSession(this, sessionId);

+        PrincipalCollection principals = getPrincipals(existing);

+        boolean authenticated = isAuthenticated(existing, principals);

+        InetAddress host = existing.getHostAddress();

+

+        return getSubjectFactory().createSubject(principals, existing, authenticated, host);

+    }

 }
\ No newline at end of file
diff --git a/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java b/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java
index a7f612c..7857bf6 100644
--- a/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java
+++ b/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java
@@ -30,12 +30,13 @@
 import java.net.InetAddress;
 
 /**
- * TODO - Class JavaDoc
+ * Default {@link SubjectFactory SubjectFactory} implementation that creates {@link DelegatingSubject DelegatingSubject}
+ * instances.
  *
  * @author Les Hazlewood
  * @since 1.0
  */
-public class DefaultSubjectFactory implements SubjectFactory {
+public class DefaultSubjectFactory implements SubjectFactory, SecurityManagerAware {
 
     private SecurityManager securityManager;
 
@@ -43,7 +44,7 @@
     }
 
     public DefaultSubjectFactory(SecurityManager securityManager) {
-        setSecurityManager(securityManager);
+        this.securityManager = securityManager;
     }
 
     public SecurityManager getSecurityManager() {
@@ -54,11 +55,6 @@
         this.securityManager = securityManager;
     }
 
-    public Subject createSubject(PrincipalCollection principals, Session existing,
-                                 boolean authenticated, InetAddress inetAddress) {
-        return new DelegatingSubject(principals, authenticated, inetAddress, existing, getSecurityManager());
-    }
-
     private void assertPrincipals(AuthenticationInfo info) {
         PrincipalCollection principals = info.getPrincipals();
         if (principals == null || principals.isEmpty()) {
@@ -67,14 +63,6 @@
         }
     }
 
-    /**
-     * Creates a <tt>Subject</tt> instance for the user represented by the given method arguments.
-     *
-     * @param token the <tt>AuthenticationToken</tt> submitted for the successful authentication.
-     * @param info  the <tt>AuthenticationInfo</tt> of a newly authenticated user.
-     * @return the <tt>Subject</tt> instance that represents the user and session data for the newly
-     *         authenticated user.
-     */
     public Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {
         assertPrincipals(info);
 
@@ -95,4 +83,9 @@
 
         return createSubject(info.getPrincipals(), session, true, authcSourceIP);
     }
+
+    public Subject createSubject(PrincipalCollection principals, Session existing,
+                                 boolean authenticated, InetAddress inetAddress) {
+        return new DelegatingSubject(principals, authenticated, inetAddress, existing, getSecurityManager());
+    }
 }
diff --git a/core/src/org/jsecurity/mgt/RealmSecurityManager.java b/core/src/org/jsecurity/mgt/RealmSecurityManager.java
index 8f117b5..4c58f85 100644
--- a/core/src/org/jsecurity/mgt/RealmSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/RealmSecurityManager.java
@@ -18,8 +18,6 @@
  */
 package org.jsecurity.mgt;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.jsecurity.cache.CacheManager;
 import org.jsecurity.cache.CacheManagerAware;
 import org.jsecurity.realm.Realm;
@@ -30,7 +28,7 @@
 
 /**
  * JSecurity support of a {@link SecurityManager} class hierarchy based around a collection of
- * {@link org.jsecurity.realm.Realm}s.  All actual <tt>SecurityManager</tt> method implementations are left to
+ * {@link org.jsecurity.realm.Realm}s.  All actual {@code SecurityManager} method implementations are left to
  * subclasses.
  *
  * @author Les Hazlewood
@@ -39,14 +37,9 @@
 public abstract class RealmSecurityManager extends CachingSecurityManager {
 
     /**
-     * Internal private log instance.
-     */
-    private static final Log log = LogFactory.getLog(RealmSecurityManager.class);
-
-    /**
      * Internal collection of <code>Realm</code>s used for all authentication and authorization operations.
      */
-    protected Collection<Realm> realms;
+    private Collection<Realm> realms;
 
     /**
      * Default no-arg constructor.
@@ -74,6 +67,7 @@
      * Sets the realms managed by this <tt>SecurityManager</tt> instance.
      *
      * @param realms the realms managed by this <tt>SecurityManager</tt> instance.
+     * @throws IllegalArgumentException if the realms collection is null or empty.
      */
     public void setRealms(Collection<Realm> realms) {
         if (realms == null) {
@@ -110,7 +104,7 @@
     protected void applyCacheManagerToRealms() {
         CacheManager cacheManager = getCacheManager();
         Collection<Realm> realms = getRealms();
-        if (cacheManager != null && realms != null && !realms.isEmpty()) {
+        if (realms != null && !realms.isEmpty()) {
             for (Realm realm : realms) {
                 if (realm instanceof CacheManagerAware) {
                     ((CacheManagerAware) realm).setCacheManager(cacheManager);
diff --git a/core/src/org/jsecurity/subject/RememberMeManager.java b/core/src/org/jsecurity/mgt/RememberMeManager.java
similarity index 94%
rename from core/src/org/jsecurity/subject/RememberMeManager.java
rename to core/src/org/jsecurity/mgt/RememberMeManager.java
index eebba0b..e381a8b 100644
--- a/core/src/org/jsecurity/subject/RememberMeManager.java
+++ b/core/src/org/jsecurity/mgt/RememberMeManager.java
@@ -16,11 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.jsecurity.subject;
+package org.jsecurity.mgt;
 
 import org.jsecurity.authc.AuthenticationException;
 import org.jsecurity.authc.AuthenticationInfo;
 import org.jsecurity.authc.AuthenticationToken;
+import org.jsecurity.subject.PrincipalCollection;
 
 /**
  * A RememberMeManager is responsible for remembering a Subject's identity across that Subject's sessions with
diff --git a/core/src/org/jsecurity/mgt/SecurityManager.java b/core/src/org/jsecurity/mgt/SecurityManager.java
index 47dfff2..09510ab 100644
--- a/core/src/org/jsecurity/mgt/SecurityManager.java
+++ b/core/src/org/jsecurity/mgt/SecurityManager.java
@@ -21,17 +21,11 @@
 import org.jsecurity.authc.AuthenticationException;

 import org.jsecurity.authc.AuthenticationToken;

 import org.jsecurity.authc.Authenticator;

-import org.jsecurity.authz.AuthorizationException;

 import org.jsecurity.authz.Authorizer;

-import org.jsecurity.authz.HostUnauthorizedException;

-import org.jsecurity.session.InvalidSessionException;

-import org.jsecurity.session.Session;

 import org.jsecurity.session.mgt.SessionManager;

 import org.jsecurity.subject.PrincipalCollection;

 import org.jsecurity.subject.Subject;

 

-import java.io.Serializable;

-

 /**

  * A <tt>SecurityManager</tt> executes all security operations for <em>all</em> Subjects (aka users) across a

  * single application.

@@ -107,37 +101,4 @@
      * @since 0.9

      */

     Subject getSubject();

-

-    /**

-     * Acquires a handle to the session identified by the specified <tt>sessionId</tt>.

-     *

-     * <p><b>Although simple, this method finally enables behavior absent in Java for years:</b>

-     *

-     * <p>the

-     * ability to participate in a server-side session across clients of different mediums,

-     * such as web appliations, Java applets, standalone C# clients over XMLRPC and/or SOAP, and

-     * many others.  This is a <em>huge</em> benefit in heterogeneous enterprise applications.

-     *

-     * <p>To maintain session integrity across client mediums, the sessionId must be transmitted

-     * to all client mediums securely (e.g. over SSL) to prevent man-in-the-middle attacks.  This

-     * is nothing new - all web applications are susceptible to the same problem when transmitting

-     * {@link javax.servlet.http.Cookie Cookie}s or when using URL rewriting.  As long as the

-     * <tt>sessionId</tt> is transmitted securely, session integrity can be maintained.

-     *

-     * @param sessionId the id of the session to acquire.

-     * @return a handle to the session identified by <tt>sessionId</tt>

-     * @throws org.jsecurity.session.InvalidSessionException

-     *          if the session identified by <tt>sessionId</tt> has

-     *          been stopped, expired, or doesn't exist.

-     * @throws org.jsecurity.authz.AuthorizationException

-     *          if the executor of this method is not allowed to acquire

-     *          (i.e. join) the session identified by <tt>sessionId</tt>.  The reason for the exception

-     *          is implementation specific and could be for any number of reasons.  A common reason in many

-     *          systems would be if one host tried to acquire/join a session that originated on an entirely

-     *          different host (although it is not a JSecurity requirement this scenario is disallowed -

-     *          its just an example that <em>may</em> throw an Exception in many systems).

-     * @see HostUnauthorizedException

-     * @since 1.0

-     */

-    Session getSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException;

 }
\ No newline at end of file
diff --git a/core/src/org/jsecurity/mgt/SecurityManagerAware.java b/core/src/org/jsecurity/mgt/SecurityManagerAware.java
new file mode 100644
index 0000000..c3739a8
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/SecurityManagerAware.java
@@ -0,0 +1,38 @@
+/*
+ * 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.jsecurity.mgt;
+
+/**
+ * Interface providing a callback method that allows an implementation of this interface to receive a reference to
+ * the {@link SecurityManager SecurityManager} if they require one.  This is mostly used by core implementation classes
+ * for framework code and is rarely necessary for software developers enabling JSecurity in their applications.
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public interface SecurityManagerAware {
+
+    /**
+     * Callback method that allows a component to receive the {@link SecurityManager SecurityManager} instance if it
+     * requires one.
+     *
+     * @param securityManager the application's <code>SecurityManager</code>
+     */
+    void setSecurityManager(SecurityManager securityManager);
+}
diff --git a/core/src/org/jsecurity/mgt/SessionSubjectBinder.java b/core/src/org/jsecurity/mgt/SessionSubjectBinder.java
index 0597541..7b96e20 100644
--- a/core/src/org/jsecurity/mgt/SessionSubjectBinder.java
+++ b/core/src/org/jsecurity/mgt/SessionSubjectBinder.java
@@ -23,20 +23,54 @@
 import org.jsecurity.subject.Subject;
 
 /**
- * Binds the Subject to the accessible Session in addition to the ThreadContext.
+ * Binds the Subject's state to the accessible {@link Session Session} in addition to the
+ * {@link org.jsecurity.util.ThreadContext ThreadContext}
+ * <p/>
+ * The very notion of this class's existence might sound backwards:  typically a {@link Session Session} is something
+ * that is created <em>after</em> a {@link Subject Subject} is acquired - for example by calling
+ * <code>Subject.{@link Subject#getSession getSession()}</code>.  This might imply that a <code>Session</code> is also
+ * therefore constrained to the 'owning' <code>Subject</code>'s lifecycle.
+ * <p/>
+ * However, in many environments, the <code>Subject</code> instance in memory is transient and exists only for the
+ * duration of thread execution or during an incoming request in web environments.  The <code>Session</code> however
+ * must be persistent over time since that is the very nature of the concept of a <code>Session</code>.  So, this
+ * particular <code>SubjectBinder</code> implementation will save the relevant <code>Subject</code> state as
+ * <code>Session</code> attributes to enable the <code>Subject</code> to be constructed on subsequent requests or
+ * method invocations.
+ * <p/>
+ * This paradigm requires some framework code elsewhere to re-create the <code>Subject</code>:
+ * <ol>
+ * <li>A session ID would be acquired based on an incoming request or remote method invocation</li>
+ * <li>The <code>Session</code> would be retrieved from the application's {@link SecurityManager SecurityManager}
+ * (using the {@link org.jsecurity.session.mgt.SessionManager SessionManager} parent methods)</li>
+ * <li>A <code>Subject</code> instance would be created based on the attributes found in that session</code>
+ * <li>The constructed <code>Subject</code> would be 'bound' to the application for use during the request or method
+ * invocation (say, bound to the processing thread)</li>
+ * <li>The subject would then be accessible to the application for the duration of the thread</li>
+ * <li>Any state changed to the subject at the end of the thread execution would be saved to back to the
+ * <code>Session</code></li>
+ * <li>The <code>Subject</code> instance wold be 'unbound' from the application/thread and garbage collected at the
+ * end of request/thread execution, and a new one is created on the next request/method invocation as per step #1.</li>
+ * </ol>
+ * <p/>
+ * Indeed this is exactly how JSecurity's default behavior works in enterprise server and web-based environments.  It is
+ * enabled in the <code>JSecurityFilter</code> for web-based environments as well as remote-method-invocation-based
+ * components for non-web environments.
  *
  * @author Les Hazlewood
  * @since 1.0
  */
 public class SessionSubjectBinder extends ThreadContextSubjectBinder {
 
+    //TODO - finish JavaDoc
+
     /**
-     * The key that is used to store subject principals in the session.
+     * The session key that is used to store subject principals.
      */
     public static final String PRINCIPALS_SESSION_KEY = SessionSubjectBinder.class.getName() + "_PRINCIPALS_SESSION_KEY";
 
     /**
-     * The key that is used to store whether or not the user is authenticated in the session.
+     * The session key that is used to store whether or not the user is authenticated.
      */
     public static final String AUTHENTICATED_SESSION_KEY = SessionSubjectBinder.class.getName() + "_AUTHENTICATED_SESSION_KEY";
 
diff --git a/core/src/org/jsecurity/mgt/SessionsSecurityManager.java b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
index 023359b..2453867 100644
--- a/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
@@ -18,16 +18,13 @@
  */
 package org.jsecurity.mgt;
 
-import org.jsecurity.authz.AuthorizationException;
 import org.jsecurity.authz.HostUnauthorizedException;
-import org.jsecurity.cache.CacheManager;
 import org.jsecurity.cache.CacheManagerAware;
 import org.jsecurity.session.InvalidSessionException;
 import org.jsecurity.session.Session;
 import org.jsecurity.session.SessionListener;
 import org.jsecurity.session.SessionListenerRegistrar;
 import org.jsecurity.session.mgt.DefaultSessionManager;
-import org.jsecurity.session.mgt.DelegatingSession;
 import org.jsecurity.session.mgt.SessionManager;
 import org.jsecurity.util.LifecycleUtils;
 
@@ -41,12 +38,12 @@
  * {@link org.jsecurity.session.Session session} operations to a wrapped {@link 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' <tt>SessionManager</tt> instance.
- *
- * <p>The remaining <tt>SecurityManager</tt> methods not implemented by this class or its parents are left to be
+ * the underlying 'real' {@code SessionManager} instance.
+ * <p/>
+ * The remaining {@code SecurityManager} methods not implemented by this class or its parents are left to be
  * implemented by subclasses.
- *
- * <p>In keeping with the other classes in this hierarchy and JSecurity's desire to minimize configuration whenever
+ * <p/>
+ * In keeping with the other classes in this hierarchy and JSecurity's desire to minimize configuration whenever
  * possible, suitable default instances for all dependencies will be created upon instantiation.
  *
  * @author Les Hazlewood
@@ -58,14 +55,19 @@
      * The internal delegate <code>SessionManager</code> used by this security manager that manages all the
      * application's {@link Session Session}s.
      */
-    protected SessionManager sessionManager;
+    private SessionManager sessionManager;
 
     /**
      * Default no-arg constructor, internally creates a suitable default {@link SessionManager SessionManager} delegate
-     * instance via the {@link #createSessionManager() createSessionManager()} method.
+     * instance.
      */
     public SessionsSecurityManager() {
-        setSessionManager(createSessionManager());
+        applySessionManager(new DefaultSessionManager());
+    }
+
+    protected final void applySessionManager(SessionManager sm) {
+        setSessionManager(sm);
+        applyCacheManagerToSessionManager();
     }
 
     /**
@@ -96,37 +98,6 @@
     }
 
     /**
-     * Constructs a new <code>SessionManager</code> instance to be used as the internal delegate for this security
-     * manager.  After creation via the {@link #newSessionManagerInstance() newSessionManagerInstance()} call, the
-     * internal {@link #getCacheManager CacheManager} is set on it if the session manager instance implements the
-     * {@link CacheManagerAware CacheManagerAware} interface to allow it to utilize the cache manager for its own
-     * internal caching needs.
-     *
-     * @return a new initialized {@link SessionManager SessionManager} to use as this security manager's internal
-     *         delegate.
-     */
-    protected SessionManager createSessionManager() {
-        SessionManager sm = newSessionManagerInstance();
-        CacheManager cm = getCacheManager();
-        if (cm != null) {
-            if (sm instanceof CacheManagerAware) {
-                ((CacheManagerAware) sm).setCacheManager(cm);
-            }
-        }
-        return sm;
-    }
-
-    /**
-     * Merely instantiates (but does not initalize) the default <code>SessionManager</code> implementation.  This method
-     * merely returns <code>new {@link DefaultSessionManager DefaultSessionManager}()</code>.
-     *
-     * @return a new, uninitialized {@link SessionManager SessionManager} instance.
-     */
-    protected SessionManager newSessionManagerInstance() {
-        return new DefaultSessionManager();
-    }
-
-    /**
      * Calls {@link AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
      * {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()} to ensure the
      * <code>CacheManager</code> is applied to the SessionManager as necessary.
@@ -144,9 +115,8 @@
      * instance implements the {@link CacheManagerAware CacheManagerAware} interface.
      */
     protected void applyCacheManagerToSessionManager() {
-        SessionManager sm = getSessionManager();
-        if (sm instanceof CacheManagerAware) {
-            ((CacheManagerAware) sm).setCacheManager(cacheManager);
+        if (this.sessionManager instanceof CacheManagerAware) {
+            ((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());
         }
     }
 
@@ -199,8 +169,7 @@
      */
     public void add(SessionListener listener) {
         assertSessionListenerSupport();
-        SessionManager sm = getSessionManager();
-        ((SessionListenerRegistrar) sm).add(listener);
+        ((SessionListenerRegistrar) this.sessionManager).add(listener);
     }
 
     /**
@@ -212,61 +181,60 @@
      *         instance, <code>false</code> otherwise.
      */
     public boolean remove(SessionListener listener) {
-        SessionManager sm = getSessionManager();
-        return (sm instanceof SessionListenerRegistrar) &&
-                ((SessionListenerRegistrar) sm).remove(listener);
+        return (this.sessionManager instanceof SessionListenerRegistrar) &&
+                ((SessionListenerRegistrar) this.sessionManager).remove(listener);
     }
 
     public Serializable start(InetAddress originatingHost) throws HostUnauthorizedException, IllegalArgumentException {
-        return getSessionManager().start(originatingHost);
+        return this.sessionManager.start(originatingHost);
     }
 
     public Date getStartTimestamp(Serializable sessionId) {
-        return getSessionManager().getStartTimestamp(sessionId);
+        return this.sessionManager.getStartTimestamp(sessionId);
     }
 
     public Date getLastAccessTime(Serializable sessionId) {
-        return getSessionManager().getLastAccessTime(sessionId);
+        return this.sessionManager.getLastAccessTime(sessionId);
     }
 
     public boolean isValid(Serializable sessionId) {
-        return getSessionManager().isValid(sessionId);
+        return this.sessionManager.isValid(sessionId);
     }
 
     public long getTimeout(Serializable sessionId) throws InvalidSessionException {
-        return getSessionManager().getTimeout(sessionId);
+        return this.sessionManager.getTimeout(sessionId);
     }
 
     public void setTimeout(Serializable sessionId, long maxIdleTimeInMillis) throws InvalidSessionException {
-        getSessionManager().setTimeout(sessionId, maxIdleTimeInMillis);
+        this.sessionManager.setTimeout(sessionId, maxIdleTimeInMillis);
     }
 
     public void touch(Serializable sessionId) throws InvalidSessionException {
-        getSessionManager().touch(sessionId);
+        this.sessionManager.touch(sessionId);
     }
 
     public InetAddress getHostAddress(Serializable sessionId) {
-        return getSessionManager().getHostAddress(sessionId);
+        return this.sessionManager.getHostAddress(sessionId);
     }
 
     public void stop(Serializable sessionId) throws InvalidSessionException {
-        getSessionManager().stop(sessionId);
+        this.sessionManager.stop(sessionId);
     }
 
     public Collection<Object> getAttributeKeys(Serializable sessionId) {
-        return getSessionManager().getAttributeKeys(sessionId);
+        return this.sessionManager.getAttributeKeys(sessionId);
     }
 
     public Object getAttribute(Serializable sessionId, Object key) throws InvalidSessionException {
-        return getSessionManager().getAttribute(sessionId, key);
+        return this.sessionManager.getAttribute(sessionId, key);
     }
 
     public void setAttribute(Serializable sessionId, Object key, Object value) throws InvalidSessionException {
-        getSessionManager().setAttribute(sessionId, key, value);
+        this.sessionManager.setAttribute(sessionId, key, value);
     }
 
     public Object removeAttribute(Serializable sessionId, Object key) throws InvalidSessionException {
-        return getSessionManager().removeAttribute(sessionId, key);
+        return this.sessionManager.removeAttribute(sessionId, key);
     }
 
     /**
@@ -277,10 +245,10 @@
 
     /**
      * Cleans up ('destroys') the internal delegate <code>SessionManager</code> by calling
-     * {@link LifecycleUtils#destroy LifecycleUtils.destroy(getSessionManager())}.
+     * {@link LifecycleUtils#destroy LifecycleUtils.destroy(this.sessionManager)}.
      */
     protected void destroySessionManager() {
-        LifecycleUtils.destroy(getSessionManager());
+        LifecycleUtils.destroy(this.sessionManager);
     }
 
     /**
@@ -293,14 +261,4 @@
         destroySessionManager();
     }
 
-    public Session getSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
-        SessionManager sm = getSessionManager();
-        if (!sm.isValid(sessionId)) {
-            String msg = "Specified id [" + sessionId + "] does not correspond to a valid Session  It either " +
-                    "does not exist or the corresponding session has been stopped or expired.";
-            throw new InvalidSessionException(msg, sessionId);
-        }
-        return new DelegatingSession(sm, sessionId);
-    }
-
 }
diff --git a/core/src/org/jsecurity/mgt/SubjectFactory.java b/core/src/org/jsecurity/mgt/SubjectFactory.java
index 51c8712..1fe22ba 100644
--- a/core/src/org/jsecurity/mgt/SubjectFactory.java
+++ b/core/src/org/jsecurity/mgt/SubjectFactory.java
@@ -27,16 +27,44 @@
 import java.net.InetAddress;
 
 /**
- * TODO - Class JavaDoc
+ * A {@code SubjectFactory} is responsible for returning {@link Subject Subject} instances as needed.
  *
  * @author Les Hazlewood
  * @since 1.0
  */
 public interface SubjectFactory {
 
+    /**
+     * Returns a {@code Subject} instance reflecting the state of a <em>successful</em> authentication attempt.
+     * <p/>
+     * The '{@code existing}' {@code Subject} method argument is the {@code Subject} that executed the
+     * authentication attempt but still reflects an unauthenticated state.  The instance returned from this method
+     * is the {code Subject} instance to use for future application use and reflects an authenticated state.
+     *
+     * @param token    the {@code AuthenticationToken} submitted during the successful authentication attempt.
+     * @param info     the {@code AuthenticationInfo} generated due to the successful authentication attempt.
+     * @param existing the {@code Subject} that executed the attempt, still in an 'unauthenticated' state.
+     * @return the {@code Subject} for the application to use going forward, but in an 'authenticated' state.
+     */
     Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing);
 
-    Subject createSubject(PrincipalCollection principals, Session existing,
-                          boolean authenticated, InetAddress originatingHost);
+    /**
+     * Returns a {@code Subject} instance reflecting the specified Subject identity (aka 'principals'), any
+     * existing {@code Session} that might be in place for that identity, whether or not the Subject is to be
+     * considered already authenticated, and the originating host from where the Subject instance to be created is
+     * being acquired.
+     *
+     * @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
+     *                        {@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
+     *                        authenticated.
+     * @param originatingHost the host location indicating where the {@code Subject} is located.
+     * @return a {@code Subject} instance representing the aggregate state of the specified method arguments.
+     */
+    Subject createSubject(PrincipalCollection principals, Session existing, boolean authenticated, InetAddress originatingHost);
 
 }
diff --git a/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java b/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java
index 1fd310a..8af9b00 100644
--- a/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java
+++ b/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java
@@ -24,19 +24,32 @@
 import org.jsecurity.util.ThreadContext;
 
 /**
- * TODO - Class JavaDoc
+ * Associates a {@link Subject Subject} instance to the currently executing thread via the {
  *
  * @author Les Hazlewood
+ * @link ThreadContext ThreadContext} to ensure that the <code>Subject</code> is accessible to any caller during
+ * thread execution.
+ * @see org.jsecurity.SecurityUtils#getSubject SecurityUtils.getSubject()
  * @since 1.0
  */
 public class ThreadContextSubjectBinder implements SubjectBinder {
 
     private static final Log log = LogFactory.getLog(ThreadContextSubjectBinder.class);
 
+    /**
+     * This implementation returns the {@link Subject Subject} from the {@link ThreadContext ThreadContext}.
+     *
+     * @return the {@link Subject Subject} in the {@link ThreadContext ThreadContext}
+     */
     public Subject getSubject() {
         return ThreadContext.getSubject();
     }
 
+    /**
+     * Associates the specified subject to the currently executing thread via the {@link ThreadContext ThreadContext}.
+     *
+     * @param subject the subject to accosiate to the currently executing thread.
+     */
     public void bind(Subject subject) {
         if (log.isTraceEnabled()) {
             log.trace("Binding Subject [" + subject + "] to a thread local...");
@@ -44,6 +57,12 @@
         ThreadContext.bind(subject);
     }
 
+    /**
+     * Removes the specified Subject instance from the currently executing thread by removing it from the
+     * {@link ThreadContext ThreadContext}
+     *
+     * @param subject the <code>Subject</code> instance to unbind from the currently executing thread.
+     */
     public void unbind(Subject subject) {
         ThreadContext.unbindSubject();
     }
diff --git a/core/src/org/jsecurity/session/Session.java b/core/src/org/jsecurity/session/Session.java
index 721899d..11171ba 100644
--- a/core/src/org/jsecurity/session/Session.java
+++ b/core/src/org/jsecurity/session/Session.java
@@ -33,9 +33,6 @@
  * {@link javax.servlet.http.HttpSession HttpSession} or Stateful Session EJB's, which many times
  * unnecessarily coupled applications to web or ejb technologies.
  *
- * <p>See the {@link org.jsecurity.mgt.SecurityManager#getSession(java.io.Serializable) SecurityManager.getSession(Serializable)}
- * JavaDoc for more on the benefits of a POJO-based <tt>Session</tt> framework.
- *
  * @author Les Hazlewood
  * @since 0.1
  */
diff --git a/core/src/org/jsecurity/session/mgt/DefaultSessionManager.java b/core/src/org/jsecurity/session/mgt/DefaultSessionManager.java
index 42ac514..a4a765a 100644
--- a/core/src/org/jsecurity/session/mgt/DefaultSessionManager.java
+++ b/core/src/org/jsecurity/session/mgt/DefaultSessionManager.java
@@ -45,9 +45,10 @@
 
     private static final Log log = LogFactory.getLog(DefaultSessionManager.class);
 
-    protected SessionDAO sessionDAO = new MemorySessionDAO();
+    protected SessionDAO sessionDAO;
 
     public DefaultSessionManager() {
+        this.sessionDAO = new MemorySessionDAO();
     }
 
     public void setSessionDAO(SessionDAO sessionDAO) {
@@ -59,7 +60,9 @@
     }
 
     public void setCacheManager(CacheManager cacheManager) {
-        ((CacheManagerAware) getSessionDAO()).setCacheManager(cacheManager);
+        if (this.sessionDAO instanceof CacheManagerAware) {
+            ((CacheManagerAware) this.sessionDAO).setCacheManager(cacheManager);
+        }
     }
 
     protected Session doCreateSession(InetAddress originatingHost) {
diff --git a/core/src/org/jsecurity/util/ThreadContext.java b/core/src/org/jsecurity/util/ThreadContext.java
index 12b8aa6..c0f46ff 100644
--- a/core/src/org/jsecurity/util/ThreadContext.java
+++ b/core/src/org/jsecurity/util/ThreadContext.java
@@ -23,6 +23,7 @@
 import org.jsecurity.mgt.SecurityManager;
 import org.jsecurity.subject.Subject;
 
+import java.io.Serializable;
 import java.net.InetAddress;
 import java.util.HashMap;
 import java.util.Map;
@@ -46,11 +47,14 @@
 @SuppressWarnings(value = {"unchecked", "unsafe"})
 public abstract class ThreadContext {
 
-    /** Private internal log instance. */
+    /**
+     * Private internal log instance.
+     */
     private static final Log log = LogFactory.getLog(ThreadContext.class);
 
     public static final String SECURITY_MANAGER_KEY = ThreadContext.class.getName() + "_SECURITY_MANAGER_KEY";
     public static final String SUBJECT_KEY = ThreadContext.class.getName() + "_SUBJECT_KEY";
+    public static final String SESSION_ID_KEY = ThreadContext.class.getName() + "_SESSION_ID_KEY";
     public static final String INET_ADDRESS_KEY = ThreadContext.class.getName() + "_INET_ADDRESS_KEY";
 
     protected static ThreadLocal<Map<Object, Object>> resources =
@@ -366,5 +370,22 @@
     public static InetAddress unbindInetAddress() {
         return (InetAddress) remove(INET_ADDRESS_KEY);
     }
+
+    //TODO - complete JavaDoc
+
+    public static Serializable getSessionId() {
+        return (Serializable) get(SESSION_ID_KEY);
+    }
+
+    public static void bindSessionId(Serializable sessionId) {
+        if (sessionId != null) {
+            put(SESSION_ID_KEY, sessionId);
+        }
+    }
+
+    public Serializable unbindSessionId() {
+        return (Serializable) remove(SESSION_ID_KEY);
+
+    }
 }
 
diff --git a/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java b/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
index 0fc4ecf..5afeede 100644
--- a/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
+++ b/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
@@ -21,24 +21,18 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jsecurity.mgt.SecurityManager;
-import org.jsecurity.session.Session;
-import org.jsecurity.subject.DelegatingSubject;
-import org.jsecurity.subject.PrincipalCollection;
-import org.jsecurity.subject.Subject;
 import org.jsecurity.util.ThreadContext;
-import org.jsecurity.web.DefaultWebSecurityManager;
 import org.springframework.remoting.support.DefaultRemoteInvocationExecutor;
 import org.springframework.remoting.support.RemoteInvocation;
 
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 
 /**
  * An implementation of the Spring {@link org.springframework.remoting.support.RemoteInvocationExecutor}
- * that binds the correct {@link Session} and {@link org.jsecurity.subject.Subject} to the
- * remote invocation thread during a remote execution.
+ * that binds a {@code sessionId} to the incoming thread to make it available to the {@code SecurityManager}
+ * implementation during the thread execution.  The {@code SecurityManager} implementation can use this sessionId
+ * to reconstitute the {@code Subject} instance based on persistent state in the corresponding {@code Session}.
  *
  * @author Jeremy Haile
  * @author Les Hazlewood
@@ -78,59 +72,23 @@
     /*--------------------------------------------
     |               M E T H O D S               |
     ============================================*/
-
-    protected InetAddress getInetAddress(RemoteInvocation invocation, Object targetObject) {
-        try {
-            return InetAddress.getLocalHost();
-        } catch (UnknownHostException e) {
-            return null;
-        }
-    }
-
-    protected PrincipalCollection getPrincipals(RemoteInvocation invocation, Object targetObject, Session session) {
-        return (PrincipalCollection) session.getAttribute(DefaultWebSecurityManager.PRINCIPALS_SESSION_KEY);
-    }
-
-    protected boolean isAuthenticated(RemoteInvocation invocation, Object targetObject, Session session, PrincipalCollection principals) {
-        if (principals != null) {
-            Boolean authc = (Boolean) session.getAttribute(DefaultWebSecurityManager.AUTHENTICATED_SESSION_KEY);
-            return authc != null && authc;
-        }
-        return false;
-    }
-
     @SuppressWarnings({"unchecked"})
     public Object invoke(RemoteInvocation invocation, Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
-
         try {
-            PrincipalCollection principals = null;
-            boolean authenticated = false;
-            InetAddress inetAddress = getInetAddress(invocation, targetObject);
-            Session session = null;
-
             Serializable sessionId = invocation.getAttribute(SecureRemoteInvocationFactory.SESSION_ID_KEY);
-
             if (sessionId != null) {
-
-                session = securityManager.getSession(sessionId);
-                principals = getPrincipals(invocation, targetObject, session);
-                authenticated = isAuthenticated(invocation, targetObject, session, principals);
+                ThreadContext.bindSessionId(sessionId);
             } else {
-                if (log.isWarnEnabled()) {
-                    log.warn("RemoteInvocation object did not contain a JSecurity Session id under " +
-                            "attribute name [" + SecureRemoteInvocationFactory.SESSION_ID_KEY + "].  A Session will not " +
-                            "be available to the method.  Ensure that clients are using a " +
-                            "SecureRemoteInvocationFactory to prevent this problem.");
+                if (log.isTraceEnabled()) {
+                    log.trace("RemoteInvocation did not contain a JSecurity Session id attribute under " +
+                            "key [" + SecureRemoteInvocationFactory.SESSION_ID_KEY + "].  A Subject based " +
+                            "on an existing Session will not be available during the method invocatin.");
                 }
             }
-
-            Subject subject = new DelegatingSubject(principals, authenticated, inetAddress, session, securityManager);
-
             ThreadContext.bind(securityManager);
-            ThreadContext.bind(subject);
+            ThreadContext.bind(securityManager.getSubject());
 
             return super.invoke(invocation, targetObject);
-
         } catch (NoSuchMethodException nsme) {
             throw nsme;
         } catch (IllegalAccessException iae) {
diff --git a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
index f8731b7..a4b98d0 100644
--- a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
+++ b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
@@ -59,15 +59,19 @@
     private String sessionMode = HTTP_SESSION_MODE; //default

 

     public DefaultWebSecurityManager() {

+        WebSessionManager sm = new DefaultWebSessionManager();

+        applySessionManager(sm);

         setRememberMeManager(new WebRememberMeManager());

-        setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) getSessionManager()));

+        setSubjectFactory(new WebSubjectFactory(this, sm));

     }

 

     public DefaultWebSecurityManager(Realm singleRealm) {

+        this();

         setRealm(singleRealm);

     }

 

     public DefaultWebSecurityManager(Collection<Realm> realms) {

+        this();

         setRealms(realms);

     }

 

@@ -126,8 +130,12 @@
     }

 

     public void setSessionMode(String sessionMode) {

-        if (sessionMode == null ||

-                (!sessionMode.equals(HTTP_SESSION_MODE) && !sessionMode.equals(JSECURITY_SESSION_MODE))) {

+        String mode = sessionMode;

+        if (mode == null) {

+            throw new IllegalArgumentException("sessionMode argument cannot be null.");

+        }

+        mode = sessionMode.toLowerCase();

+        if (!HTTP_SESSION_MODE.equals(mode) && !JSECURITY_SESSION_MODE.equals(mode)) {

             String msg = "Invalid sessionMode [" + sessionMode + "].  Allowed values are " +

                     "public static final String constants in the " + getClass().getName() + " class: '"

                     + HTTP_SESSION_MODE + "' or '" + JSECURITY_SESSION_MODE + "', with '" +

@@ -138,9 +146,9 @@
         this.sessionMode = sessionMode;

         if (recreate) {

             LifecycleUtils.destroy(getSessionManager());

-            SessionManager sm = createSessionManager();

-            setSessionManager(sm);

-            setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) getSessionManager()));

+            SessionManager sessionManager = newSessionManagerInstance();

+            applySessionManager(sessionManager);

+            setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) sessionManager));

         }

     }

 

diff --git a/web/src/org/jsecurity/web/WebRememberMeManager.java b/web/src/org/jsecurity/web/WebRememberMeManager.java
index f2739ab..ef79b4d 100644
--- a/web/src/org/jsecurity/web/WebRememberMeManager.java
+++ b/web/src/org/jsecurity/web/WebRememberMeManager.java
@@ -21,7 +21,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jsecurity.codec.Base64;
-import org.jsecurity.subject.AbstractRememberMeManager;
+import org.jsecurity.mgt.AbstractRememberMeManager;
 import org.jsecurity.web.attr.CookieAttribute;
 import org.jsecurity.web.attr.WebAttribute;
 
@@ -57,7 +57,7 @@
 
     //TODO - complete JavaDoc
 
-    private static transient final Log log = LogFactory.getLog( WebRememberMeManager.class );
+    private static transient final Log log = LogFactory.getLog(WebRememberMeManager.class);
 
     /**
      * The default name of the underlying rememberMe cookie which is <code>rememberMe</code>.
@@ -207,12 +207,12 @@
         ServletResponse response = WebUtils.getRequiredServletResponse();
         String base64 = getIdentityAttribute().retrieveValue(request, response);
         if (base64 != null) {
-            if ( log.isTraceEnabled() ) {
-                log.trace( "Acquired Base64 encoded identity [" + base64 + "]" );
+            if (log.isTraceEnabled()) {
+                log.trace("Acquired Base64 encoded identity [" + base64 + "]");
             }
             byte[] decoded = Base64.decode(base64);
-            if ( log.isTraceEnabled() ) {
-                log.trace( "Base64 decoded byte array length: " + (decoded != null ? decoded.length : 0) + " bytes." );
+            if (log.isTraceEnabled()) {
+                log.trace("Base64 decoded byte array length: " + (decoded != null ? decoded.length : 0) + " bytes.");
             }
             return decoded;
         } else {