JSEC-42 - made SecurityManager extend SessionManager instead of SessionFactory (reasons documented in the issue).

git-svn-id: https://svn.apache.org/repos/asf/incubator/jsecurity/trunk@733434 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/org/jsecurity/authz/HostUnauthorizedException.java b/core/src/org/jsecurity/authz/HostUnauthorizedException.java
index 37b972e..843e166 100644
--- a/core/src/org/jsecurity/authz/HostUnauthorizedException.java
+++ b/core/src/org/jsecurity/authz/HostUnauthorizedException.java
@@ -26,7 +26,7 @@
  * or access a particular resource.
  *
  * @author Les Hazlewood
- * @see org.jsecurity.session.SessionFactory#start(java.net.InetAddress)
+ * @see org.jsecurity.session.mgt.SessionManager#start(java.net.InetAddress)
  * @since 0.1
  */
 public class HostUnauthorizedException extends UnauthorizedException {
diff --git a/core/src/org/jsecurity/mgt/SecurityManager.java b/core/src/org/jsecurity/mgt/SecurityManager.java
index 5a23e7d..47dfff2 100644
--- a/core/src/org/jsecurity/mgt/SecurityManager.java
+++ b/core/src/org/jsecurity/mgt/SecurityManager.java
@@ -21,20 +21,26 @@
 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.session.SessionFactory;

+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.

  *

  * <p>The interface itself primarily exists as a convenience - it extends the {@link Authenticator},

- * {@link Authorizer}, and {@link SessionFactory} interfaces, thereby consolidating

+ * {@link Authorizer}, and {@link SessionManager} interfaces, thereby consolidating

  * these behaviors into a single point of reference.  For most JSecurity usages, this simplifies configuration and

  * tends to be a more convenient approach than referencing <code>Authenticator</code>, <code>Authorizer</code>, and

- * <code>SessionFactory</code> instances seperately;  instead one only needs to interact with a

+ * <code>SessionManager</code> instances seperately;  instead one only needs to interact with a

  * single <tt>SecurityManager</tt> instance.</p>

  *

  * <p>In addition to the above three interfaces, three unique methods are provided by this interface by itself,

@@ -59,14 +65,14 @@
  * @see DefaultSecurityManager

  * @since 0.2

  */

-public interface SecurityManager extends Authenticator, Authorizer, SessionFactory {

+public interface SecurityManager extends Authenticator, Authorizer, SessionManager {

 

     /**

      * Logs in a user, returning a Subject instance if the authentication is successful or throwing an

      * <code>AuthenticationException</code> if it is not.

      * <p/>

      * Note that most application developers should probably not call this method directly unless they have a good

-     * reason for doing so.  The preferred way to log in a Subject is to call 

+     * reason for doing so.  The preferred way to log in a Subject is to call

      * <code>{@link Subject#login Subject.login(authenticationToken)}</code> (usually after acquiring the

      * Subject by calling {@link org.jsecurity.SecurityUtils#getSubject() SecurityUtils.getSubject()}).

      * <p/>

@@ -101,4 +107,37 @@
      * @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/SessionsSecurityManager.java b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
index f85d07d..023359b 100644
--- a/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
@@ -34,6 +34,7 @@
 import java.io.Serializable;
 import java.net.InetAddress;
 import java.util.Collection;
+import java.util.Date;
 
 /**
  * JSecurity support of a {@link SecurityManager} class hierarchy that delegates all
@@ -216,6 +217,58 @@
                 ((SessionListenerRegistrar) sm).remove(listener);
     }
 
+    public Serializable start(InetAddress originatingHost) throws HostUnauthorizedException, IllegalArgumentException {
+        return getSessionManager().start(originatingHost);
+    }
+
+    public Date getStartTimestamp(Serializable sessionId) {
+        return getSessionManager().getStartTimestamp(sessionId);
+    }
+
+    public Date getLastAccessTime(Serializable sessionId) {
+        return getSessionManager().getLastAccessTime(sessionId);
+    }
+
+    public boolean isValid(Serializable sessionId) {
+        return getSessionManager().isValid(sessionId);
+    }
+
+    public long getTimeout(Serializable sessionId) throws InvalidSessionException {
+        return getSessionManager().getTimeout(sessionId);
+    }
+
+    public void setTimeout(Serializable sessionId, long maxIdleTimeInMillis) throws InvalidSessionException {
+        getSessionManager().setTimeout(sessionId, maxIdleTimeInMillis);
+    }
+
+    public void touch(Serializable sessionId) throws InvalidSessionException {
+        getSessionManager().touch(sessionId);
+    }
+
+    public InetAddress getHostAddress(Serializable sessionId) {
+        return getSessionManager().getHostAddress(sessionId);
+    }
+
+    public void stop(Serializable sessionId) throws InvalidSessionException {
+        getSessionManager().stop(sessionId);
+    }
+
+    public Collection<Object> getAttributeKeys(Serializable sessionId) {
+        return getSessionManager().getAttributeKeys(sessionId);
+    }
+
+    public Object getAttribute(Serializable sessionId, Object key) throws InvalidSessionException {
+        return getSessionManager().getAttribute(sessionId, key);
+    }
+
+    public void setAttribute(Serializable sessionId, Object key, Object value) throws InvalidSessionException {
+        getSessionManager().setAttribute(sessionId, key, value);
+    }
+
+    public Object removeAttribute(Serializable sessionId, Object key) throws InvalidSessionException {
+        return getSessionManager().removeAttribute(sessionId, key);
+    }
+
     /**
      * Template hook for subclasses that wish to perform clean up behavior during shutdown.
      */
@@ -240,12 +293,6 @@
         destroySessionManager();
     }
 
-    public Session start(InetAddress hostAddress) throws HostUnauthorizedException, IllegalArgumentException {
-        SessionManager sm = getSessionManager();
-        Serializable sessionId = sm.start(hostAddress);
-        return new DelegatingSession(sm, sessionId);
-    }
-
     public Session getSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
         SessionManager sm = getSessionManager();
         if (!sm.isValid(sessionId)) {
diff --git a/core/src/org/jsecurity/session/Session.java b/core/src/org/jsecurity/session/Session.java
index efde797..721899d 100644
--- a/core/src/org/jsecurity/session/Session.java
+++ b/core/src/org/jsecurity/session/Session.java
@@ -33,7 +33,7 @@
  * {@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 SessionFactory#getSession(java.io.Serializable) SessionFactory.getSession(Serializable)}
+ * <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
@@ -107,7 +107,7 @@
      *
      * @return the <tt>InetAddress</tt> of the host that originated this session, or <tt>null</tt>
      *         if the host address is unknown.
-     * @see SessionFactory#start(java.net.InetAddress)
+     * @see org.jsecurity.session.mgt.SessionManager#start(java.net.InetAddress)
      */
     InetAddress getHostAddress();
 
diff --git a/core/src/org/jsecurity/session/SessionFactory.java b/core/src/org/jsecurity/session/SessionFactory.java
deleted file mode 100644
index 6d74066..0000000
--- a/core/src/org/jsecurity/session/SessionFactory.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.session;
-
-import org.jsecurity.authz.AuthorizationException;
-import org.jsecurity.authz.HostUnauthorizedException;
-
-import java.io.Serializable;
-import java.net.InetAddress;
-
-/**
- * A <tt>SessionFactory</tt> is responsible for starting new {@link Session Session}s and
- * acquiring existing {@link Session Session}s.
- *
- * @author Les Hazlewood
- * @since 0.1
- */
-public interface SessionFactory {
-
-    /**
-     * Starts a new session within the system for the host with the specified
-     * originating IP address.
-     *
-     * <p>An implementation of this interface may be configured to allow a <tt>null</tt> argument,
-     * thereby indicating the originating IP is either unknown or has been
-     * explicitly omitted by the caller.  However, if the implementation is configured to require
-     * a valid <tt>hostAddress</tt> and the argument is <tt>null</tt>, an
-     * {@link IllegalArgumentException IllegalArgumentException} will be thrown.
-     *
-     * <p>In web-based systems, this InetAddress can be inferred from the
-     * {@link javax.servlet.ServletRequest#getRemoteAddr() javax.servlet.ServletRequest.getRemoteAddr()}
-     * method, or in socket-based systems, it can be obtained via inspecting the socket
-     * initiator's host IP.
-     *
-     * <p>Most secure environments <em>should</em> require that a valid, non-<tt>null</tt>
-     * <tt>hostAddress</tt> be specified, since knowing the <tt>hostAddress</tt> allows for more
-     * flexibility when securing a system: by requiring an InetAddress, access control policies
-     * can also ensure access is restricted to specific client <em>locations</em> in
-     * addition to user principals, if so desired.
-     *
-     * <p><b>Caveat</b> - if clients to your system are on a
-     * public network (as would be the case for a public web site), odds are high the clients can be
-     * behind a NAT (Network Address Translation) router or HTTP proxy server.  If so, all clients
-     * accessing your system behind that router or proxy will have the same originating IP address.
-     * If your system is configured to allow only one session per IP, then the next request from a
-     * different NAT or proxy client will fail and access will be deny for that client.  Just be
-     * aware that ip-based security policies are best utilized in LAN or private WAN environments
-     * when you can be ensure clients will not share IPs or be behind such NAT routers or
-     * proxy servers.
-     *
-     * @param hostAddress the originating host InetAddress of the external party
-     *                    (user, 3rd party product, etc) that is attempting to interact with the system.
-     * @return a handle to the newly created session.
-     * @throws HostUnauthorizedException if the system access control policy restricts access based
-     *                                   on client location/IP and the specified hostAddress hasn't been enabled.
-     * @throws IllegalArgumentException  if the system is configured to require a valid,
-     *                                   non-<tt>null</tt> argument and the specified <tt>hostAddress</tt> is null.
-     */
-    Session start(InetAddress hostAddress) throws HostUnauthorizedException, IllegalArgumentException;
-
-    /**
-     * 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 InvalidSessionException if the session identified by <tt>sessionId</tt> has
-     *                                 been stopped, expired, or doesn't exist.
-     * @throws 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
-     */
-    Session getSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException;
-
-}
diff --git a/core/src/org/jsecurity/session/mgt/SessionManager.java b/core/src/org/jsecurity/session/mgt/SessionManager.java
index ab833d1..ba2f5a7 100644
--- a/core/src/org/jsecurity/session/mgt/SessionManager.java
+++ b/core/src/org/jsecurity/session/mgt/SessionManager.java
@@ -36,20 +36,42 @@
 public interface SessionManager {
 
     /**
-     * Starts a new session within the system for the host with the specified originating IP
-     * address.
+     * Starts a new session within the system for the host with the specified originating IP address.
      *
-     * <p><b>Note</b>: see the
-     * {@link org.jsecurity.session.SessionFactory#start(java.net.InetAddress) SessionFactory.init(InetAddress)} method
-     * about the implications of using <tt>InetAddress</tt>es in access control policies.
+     * <p>An implementation of this interface may be configured to allow a <tt>null</tt> argument,
+     * thereby indicating the originating IP is either unknown or has been
+     * explicitly omitted by the caller.  However, if the implementation is configured to require
+     * a valid <tt>hostAddress</tt> and the argument is <tt>null</tt>, an
+     * {@link IllegalArgumentException IllegalArgumentException} will be thrown.
+     *
+     * <p>In web-based systems, this InetAddress can be inferred from the
+     * {@link javax.servlet.ServletRequest#getRemoteAddr() javax.servlet.ServletRequest.getRemoteAddr()}
+     * method, or in socket-based systems, it can be obtained via inspecting the socket
+     * initiator's host IP.
+     *
+     * <p>Most secure environments <em>should</em> require that a valid, non-<tt>null</tt>
+     * <tt>hostAddress</tt> be specified, since knowing the <tt>hostAddress</tt> allows for more
+     * flexibility when securing a system: by requiring an InetAddress, access control policies
+     * can also ensure access is restricted to specific client <em>locations</em> in
+     * addition to user principals, if so desired.
+     *
+     * <p><b>Caveat</b> - if clients to your system are on a
+     * public network (as would be the case for a public web site), odds are high the clients can be
+     * behind a NAT (Network Address Translation) router or HTTP proxy server.  If so, all clients
+     * accessing your system behind that router or proxy will have the same originating IP address.
+     * If your system is configured to allow only one session per IP, then the next request from a
+     * different NAT or proxy client will fail and access will be deny for that client.  Just be
+     * aware that ip-based security policies are best utilized in LAN or private WAN environments
+     * when you can be ensure clients will not share IPs or be behind such NAT routers or
+     * proxy servers.
      *
      * @param originatingHost the originating host InetAddress of the external party
      *                        (user, 3rd party product, etc) that is attempting to interact with the system.
-     * @return the system identifier of the newly created session.
-     * @throws IllegalArgumentException if the host specified is not valid.
-     * @throws org.jsecurity.authz.HostUnauthorizedException
-     *                                  if the host specified is not allowed to start sessions.
-     * @see org.jsecurity.session.SessionFactory#start(InetAddress)
+     * @return a handle to the newly created session.
+     * @throws HostUnauthorizedException if the system access control policy restricts access based
+     *                                   on client location/IP and the specified hostAddress hasn't been enabled.
+     * @throws IllegalArgumentException  if the system is configured to require a valid,
+     *                                   non-<tt>null</tt> argument and the specified <tt>hostAddress</tt> is null.
      */
     Serializable start(InetAddress originatingHost)
             throws HostUnauthorizedException, IllegalArgumentException;
diff --git a/core/src/org/jsecurity/subject/DelegatingSubject.java b/core/src/org/jsecurity/subject/DelegatingSubject.java
index 3288c0c..f6f1e8f 100644
--- a/core/src/org/jsecurity/subject/DelegatingSubject.java
+++ b/core/src/org/jsecurity/subject/DelegatingSubject.java
@@ -30,8 +30,10 @@
 import org.jsecurity.session.InvalidSessionException;
 import org.jsecurity.session.ProxiedSession;
 import org.jsecurity.session.Session;
+import org.jsecurity.session.mgt.DelegatingSession;
 import org.jsecurity.util.ThreadContext;
 
+import java.io.Serializable;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Collection;
@@ -283,7 +285,8 @@
             if (log.isTraceEnabled()) {
                 log.trace("starting session for address [" + getInetAddress() + "]");
             }
-            Session target = securityManager.start(getInetAddress());
+            Serializable sessionId = this.securityManager.start(getInetAddress());
+            Session target = new DelegatingSession(this.securityManager, sessionId);
             this.session = new StoppingAwareProxiedSession(target, this);
         }
         return this.session;
diff --git a/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java b/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
index a0314d0..0fc4ecf 100644
--- a/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
+++ b/support/spring/src/org/jsecurity/spring/remoting/SecureRemoteInvocationExecutor.java
@@ -111,6 +111,7 @@
             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);