Modified destroy() method chaining - previously used destroy and chain of before*Destroyed() method calls, which was confusing and hard to trace across the class hierarchy. Now using simple super.* overriding calls for easy traceability. The previous before*Destroyed() methods existed for simple subclassing overrides, but are no longer relevant since the next release will favor a composition over inheritance model (subclasses should be very rare). Also modified some JavaDoc to reflect this.
git-svn-id: https://svn.apache.org/repos/asf/incubator/jsecurity/trunk@736202 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/org/jsecurity/cache/DefaultCacheManager.java b/core/src/org/jsecurity/cache/DefaultCacheManager.java
index 0db9179..daabc92 100644
--- a/core/src/org/jsecurity/cache/DefaultCacheManager.java
+++ b/core/src/org/jsecurity/cache/DefaultCacheManager.java
@@ -18,6 +18,9 @@
*/
package org.jsecurity.cache;
+import org.jsecurity.util.Destroyable;
+import org.jsecurity.util.LifecycleUtils;
+
import java.util.HashMap;
import java.util.Map;
@@ -32,7 +35,7 @@
* @author Les Hazlewood
* @since 1.0
*/
-public class DefaultCacheManager implements CacheManager {
+public class DefaultCacheManager implements CacheManager, Destroyable {
/**
* Retains all Cache objects maintained by this cache manager.
@@ -56,4 +59,13 @@
return cache;
}
+
+ public void destroy() throws Exception {
+ synchronized (caches) {
+ for (Cache cache : caches.values()) {
+ LifecycleUtils.destroy(cache);
+ }
+ caches.clear();
+ }
+ }
}
diff --git a/core/src/org/jsecurity/cache/MapCache.java b/core/src/org/jsecurity/cache/MapCache.java
index 1bcce67..8b1fa08 100644
--- a/core/src/org/jsecurity/cache/MapCache.java
+++ b/core/src/org/jsecurity/cache/MapCache.java
@@ -18,6 +18,8 @@
*/
package org.jsecurity.cache;
+import org.jsecurity.util.Destroyable;
+
import java.util.*;
/**
@@ -27,7 +29,7 @@
* @author Les Hazlewood
* @since 1.0
*/
-public class MapCache implements Cache {
+public class MapCache implements Cache, Destroyable {
/**
* Backing instance.
@@ -40,6 +42,12 @@
private final String name;
public MapCache(String name, Map backingMap) {
+ if (name == null) {
+ throw new IllegalArgumentException("Cache name cannot be null.");
+ }
+ if (backingMap == null) {
+ throw new IllegalArgumentException("Backing map cannot be null.");
+ }
this.name = name;
this.map = backingMap;
}
@@ -89,6 +97,10 @@
}
public String toString() {
- return "MapCache [" + name + "]";
+ return getClass().getName() + " : [" + name + "]";
+ }
+
+ public void destroy() throws Exception {
+ clear();
}
}
diff --git a/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java b/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
index 1584ae4..a064223 100644
--- a/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/AuthenticatingSecurityManager.java
@@ -21,7 +21,6 @@
import org.jsecurity.authc.*;
import org.jsecurity.authc.pam.ModularAuthenticationStrategy;
import org.jsecurity.authc.pam.ModularRealmAuthenticator;
-import org.jsecurity.realm.Realm;
import org.jsecurity.util.LifecycleUtils;
import java.util.Collection;
@@ -55,6 +54,7 @@
* {@link org.jsecurity.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator}.
*/
public AuthenticatingSecurityManager() {
+ super();
this.authenticator = new ModularRealmAuthenticator();
}
@@ -165,47 +165,26 @@
}
/**
- * 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
+ * Passes on the {@link #getRealms() realms} to the internal delegate <code>Authenticator</code> instance so
* that it may use them during authentication attempts.
- *
- * @param realms realms the realms managed by this <tt>SecurityManager</tt> instance and subsequently the internal
- * delegate <code>Authenticator</code> instance.
*/
- public void setRealms(Collection<Realm> realms) {
- super.setRealms(realms);
+ protected void afterRealmsSet() {
+ super.afterRealmsSet();
if (this.authenticator instanceof ModularRealmAuthenticator) {
- ((ModularRealmAuthenticator) this.authenticator).setRealms(realms);
+ ((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms());
}
}
/**
- * Lifecycle cleanup method that first calls {@link #beforeAuthenticatorDestroyed() beforeAuthenticatorDestroyed()}
- * to allow subclass cleanup and then calls {@link #destroyAuthenticator() destroyAuthenticator()} to actually
- * clean up the internal delegate instance.
- */
- protected void beforeRealmsDestroyed() {
- beforeAuthenticatorDestroyed();
- destroyAuthenticator();
- }
-
- /**
- * Template hook to allow subclass cleanup when the SecurityManager is being shut down.
- */
- protected void beforeAuthenticatorDestroyed() {
- }
-
- /**
- * Cleans up ('destroys') the internal delegate <code>Authenticator</code> instance. Called during shut down.
- */
- protected void destroyAuthenticator() {
- LifecycleUtils.destroy(getAuthenticator());
- }
-
- /**
* Delegates to the wrapped {@link Authenticator Authenticator} for authentication.
*/
public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
return this.authenticator.authenticate(token);
}
+
+ public void destroy() {
+ LifecycleUtils.destroy(getAuthenticator());
+ this.authenticator = null;
+ super.destroy();
+ }
}
diff --git a/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java b/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
index c755c49..650523b 100644
--- a/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/AuthorizingSecurityManager.java
@@ -24,7 +24,6 @@
import org.jsecurity.authz.Permission;
import org.jsecurity.authz.permission.PermissionResolver;
import org.jsecurity.authz.permission.PermissionResolverAware;
-import org.jsecurity.realm.Realm;
import org.jsecurity.subject.PrincipalCollection;
import org.jsecurity.util.LifecycleUtils;
@@ -59,6 +58,7 @@
* {@link ModularRealmAuthorizer ModularRealmAuthorizer}.
*/
public AuthorizingSecurityManager() {
+ super();
this.authorizer = new ModularRealmAuthorizer();
}
@@ -114,52 +114,27 @@
}
/**
- * First calls <code>super.realms</code> and then sets these same <code>Realm</code> objects on this instance's
- * {@link Authorizer Authorizer}.
+ * First calls <code>super.afterRealmsSet()</code> and then sets these same <code>Realm</code> objects on this
+ * instance's wrapped {@link Authorizer Authorizer}.
* <p/>
- * The setting on the Authorizer will only occur if it is an instance of
+ * The setting of realms the Authorizer will only occur if it is an instance of
* {@link org.jsecurity.authz.ModularRealmAuthorizer ModularRealmAuthorizer}, that is:
- * <pre> Authorizer authz = getAuthorizer();
- * if ( authz instanceof ModularRealmAuthorizer ) {
- * ((ModularRealmAuthorizer)authz).setRealms(realms);
+ * <pre>
+ * if ( this.authorizer instanceof ModularRealmAuthorizer ) {
+ * ((ModularRealmAuthorizer)this.authorizer).setRealms(realms);
* }</pre>
- *
- * @param realms the realms managed by this <tt>SecurityManager</tt> instance.
*/
- public void setRealms(Collection<Realm> realms) {
- super.setRealms(realms);
+ protected void afterRealmsSet() {
+ super.afterRealmsSet();
if (this.authorizer instanceof ModularRealmAuthorizer) {
- ((ModularRealmAuthorizer) this.authorizer).setRealms(realms);
+ ((ModularRealmAuthorizer) this.authorizer).setRealms(getRealms());
}
}
- /**
- * Template hook for subclasses to implement destruction/cleanup logic. This will be called before this
- * instance's <tt>Authorizer</tt> instance will be cleaned up.
- */
- protected void beforeAuthorizerDestroyed() {
- }
-
- /**
- * Cleanup method that destroys/cleans up the wrapped {@link #getAuthorizer Authorizer} instance.
- * <p/>
- * The default implementation merely delegates to
- * <code>{@link LifecycleUtils#destroy LifecycleUtils.destroy}({@link #getAuthorizer getAuthorizer()})</code>.
- */
- protected void destroyAuthorizer() {
+ public void destroy() {
LifecycleUtils.destroy(getAuthorizer());
- }
-
- /**
- * Implementation of parent class's template hook for destruction/cleanup logic.
- *
- * <p>This implementation ensures subclasses are cleaned up first by calling
- * {@link #beforeAuthorizerDestroyed() beforeAuthorizerDestroyed()} and then actually cleans up the
- * wrapped <tt>Authorizer</tt> via the {@link #destroyAuthorizer() desroyAuthorizer()} method.
- */
- protected void beforeAuthenticatorDestroyed() {
- beforeAuthorizerDestroyed();
- destroyAuthorizer();
+ this.authorizer = null;
+ super.destroy();
}
public boolean isPermitted(PrincipalCollection principals, String permissionString) {
diff --git a/core/src/org/jsecurity/mgt/CachingSecurityManager.java b/core/src/org/jsecurity/mgt/CachingSecurityManager.java
index 683baa2..a67caae 100644
--- a/core/src/org/jsecurity/mgt/CachingSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/CachingSecurityManager.java
@@ -75,7 +75,6 @@
afterCacheManagerSet();
}
-
/**
* Template callback to notify subclasses that a
* {@link CacheManager CacheManager} has been set and is available for use via the
@@ -85,25 +84,10 @@
}
/**
- * 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}.
+ * Destroys the {@link #getCacheManager() cacheManager} via {@link LifecycleUtils#destroy LifecycleUtils.destroy}.
*/
public void destroy() {
- beforeCacheManagerDestroyed();
- destroyCacheManager();
- }
-
- /**
- * Template hook for subclasses to perform cleanup behavior during shutdown.
- */
- protected void beforeCacheManagerDestroyed() {
- }
-
- /**
- * Cleans up the internal <code>CacheManager</code> instance during shutdown.
- */
- protected void destroyCacheManager() {
LifecycleUtils.destroy(getCacheManager());
+ this.cacheManager = null;
}
}
diff --git a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
index 2041a97..f3d9fd6 100644
--- a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
@@ -85,8 +85,9 @@
* Default no-arg constructor.
*/
public DefaultSecurityManager() {
- setSubjectFactory(new DefaultSubjectFactory());
- setSubjectBinder(new SessionSubjectBinder());
+ super();
+ this.subjectFactory = new DefaultSubjectFactory(this);
+ this.subjectBinder = new SessionSubjectBinder();
}
/**
diff --git a/core/src/org/jsecurity/mgt/RealmSecurityManager.java b/core/src/org/jsecurity/mgt/RealmSecurityManager.java
index 4c58f85..4e20277 100644
--- a/core/src/org/jsecurity/mgt/RealmSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/RealmSecurityManager.java
@@ -45,6 +45,7 @@
* Default no-arg constructor.
*/
public RealmSecurityManager() {
+ super();
}
/**
@@ -77,6 +78,10 @@
throw new IllegalArgumentException("Realms collection argument cannot be empty.");
}
this.realms = realms;
+ afterRealmsSet();
+ }
+
+ protected void afterRealmsSet() {
applyCacheManagerToRealms();
}
@@ -122,29 +127,10 @@
applyCacheManagerToRealms();
}
- /**
- * First calls {@link #beforeRealmsDestroyed() beforeRealmsDestroyed()} to allow subclasses to clean up
- * first, then calls {@link #destroyRealms() destroyRealms()} to clean up the internal <code>Realm</code>s
- * collection.
- */
- protected void beforeCacheManagerDestroyed() {
- beforeRealmsDestroyed();
- destroyRealms();
- }
-
- /**
- * Template hook for subclasses to perform clean up logic during shut-down.
- */
- protected void beforeRealmsDestroyed() {
- }
-
- /**
- * Cleans up ('destroys') the internal collection of Realms by calling
- * {@link LifecycleUtils#destroy(Collection) LifecycleUtils.destroy(getRealms())}.
- */
- protected void destroyRealms() {
+ public void destroy() {
LifecycleUtils.destroy(getRealms());
this.realms = null;
+ super.destroy();
}
}
diff --git a/core/src/org/jsecurity/mgt/SessionsSecurityManager.java b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
index 2453867..e4676c0 100644
--- a/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/SessionsSecurityManager.java
@@ -24,6 +24,8 @@
import org.jsecurity.session.Session;
import org.jsecurity.session.SessionListener;
import org.jsecurity.session.SessionListenerRegistrar;
+import org.jsecurity.session.mgt.AbstractSessionManager;
+import org.jsecurity.session.mgt.AbstractValidatingSessionManager;
import org.jsecurity.session.mgt.DefaultSessionManager;
import org.jsecurity.session.mgt.SessionManager;
import org.jsecurity.util.LifecycleUtils;
@@ -62,11 +64,8 @@
* instance.
*/
public SessionsSecurityManager() {
- applySessionManager(new DefaultSessionManager());
- }
-
- protected final void applySessionManager(SessionManager sm) {
- setSessionManager(sm);
+ super();
+ this.sessionManager = new DefaultSessionManager();
applyCacheManagerToSessionManager();
}
@@ -85,6 +84,11 @@
*/
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
+ afterSessionManagerSet();
+ }
+
+ protected void afterSessionManagerSet() {
+ applyCacheManagerToSessionManager();
}
/**
@@ -141,6 +145,55 @@
((SessionListenerRegistrar) this.sessionManager).setSessionListeners(sessionListeners);
}
+ private void assertSessionManager(Class<? extends SessionManager> requiredType) {
+ if (this.sessionManager == null) {
+ throw new IllegalStateException("SessionManager is null - cannot configure property!");
+ }
+ if (!(this.sessionManager instanceof AbstractValidatingSessionManager)) {
+ String msg = "Property configuration failed. The target property is only configurable when the " +
+ "underlying SessionManager instance is a part of the " +
+ "[" + requiredType.getName() + "] class hierarchy. " +
+ "The current SessionManager is of type [" + this.sessionManager.getClass().getName() + "]. " +
+ "This might occur for example if you're trying to set the validation interval " +
+ "in a servlet container-backed session environment ('http' session mode). If that is the case " +
+ "however, that property is only useful when using 'jsecurity' session mode and using " +
+ "JSecurity enterprise sessions which do not rely on a servlet container.";
+ throw new IllegalStateException(msg);
+ }
+ }
+
+ /**
+ * Passthrough configuration property to the underlying {@link AbstractSessionManager AbstractSessionManager}
+ * instance. Please read the
+ * {@link org.jsecurity.session.mgt.AbstractSessionManager#getGlobalSessionTimeout() AbstractSessionManager.getGlobalSessionTimeout()}
+ * for more.
+ *
+ * @return the time in milliseconds that any {@link Session Session} may remain idle before expiring.
+ * @throws IllegalStateException if the underlying {@code SessionManager} instance is not a subclass of
+ * {@link AbstractSessionManager AbstractSessionManager}.
+ * @see org.jsecurity.session.mgt.AbstractSessionManager#getGlobalSessionTimeout()
+ */
+ public long getGlobalSessionTimeout() {
+ assertSessionManager(AbstractSessionManager.class);
+ return ((AbstractSessionManager) this.sessionManager).getGlobalSessionTimeout();
+ }
+
+ /**
+ * Passthrough configuration property to the underlying {@link AbstractSessionManager AbstractSessionManager}
+ * instance. Please read the
+ * {@link org.jsecurity.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long) AbstractSessionManager.setGlobalSessionTimeout(long)}
+ * for more.
+ *
+ * @param globalSessionTimeout the time in milliseconds that any {@link Session Session} may remain idle before expiring.
+ * @throws IllegalStateException if the underlying {@code SessionManager} instance is not a subclass of
+ * {@link AbstractSessionManager AbstractSessionManager}.
+ * @see org.jsecurity.session.mgt.AbstractSessionManager#setGlobalSessionTimeout(long)
+ */
+ public void setGlobalSessionTimeout(long globalSessionTimeout) {
+ assertSessionManager(AbstractSessionManager.class);
+ ((AbstractSessionManager) this.sessionManager).setGlobalSessionTimeout(globalSessionTimeout);
+ }
+
/**
* Ensures the internal SessionManager instance is an <code>instanceof</code>
* {@link org.jsecurity.session.SessionListenerRegistrar SessionListenerRegistrar} to ensure that any
@@ -237,28 +290,9 @@
return this.sessionManager.removeAttribute(sessionId, key);
}
- /**
- * Template hook for subclasses that wish to perform clean up behavior during shutdown.
- */
- protected void beforeSessionManagerDestroyed() {
- }
-
- /**
- * Cleans up ('destroys') the internal delegate <code>SessionManager</code> by calling
- * {@link LifecycleUtils#destroy LifecycleUtils.destroy(this.sessionManager)}.
- */
- protected void destroySessionManager() {
- LifecycleUtils.destroy(this.sessionManager);
- }
-
- /**
- * Calls {@link #beforeSessionManagerDestroyed() beforeSessionManagerDestroyed()} to allow subclass clean up and
- * then immediatley calls {@link #destroySessionManager() destroySessionManager()} to clean up the internal
- * delegate instance.
- */
- protected void beforeAuthorizerDestroyed() {
- beforeSessionManagerDestroyed();
- destroySessionManager();
+ public void destroy() {
+ LifecycleUtils.destroy(getSessionManager());
+ this.sessionManager = null;
}
}
diff --git a/core/src/org/jsecurity/session/mgt/AbstractSessionManager.java b/core/src/org/jsecurity/session/mgt/AbstractSessionManager.java
index e58dac8..4bbe953 100644
--- a/core/src/org/jsecurity/session/mgt/AbstractSessionManager.java
+++ b/core/src/org/jsecurity/session/mgt/AbstractSessionManager.java
@@ -31,18 +31,65 @@
/**
* TODO - complete JavaDoc
+ *
* @author Les Hazlewood
* @since 0.1
*/
public abstract class AbstractSessionManager implements SessionManager, SessionListenerRegistrar {
+ protected static final long MILLIS_PER_SECOND = 1000;
+ protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
+ protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
+
+ /**
+ * Default main session timeout value, equal to {@code 30} minutes.
+ */
+ public static final long DEFAULT_GLOBAL_SESSION_TIMEOUT = 30 * MILLIS_PER_MINUTE;
+
private static final Log log = LogFactory.getLog(AbstractSessionManager.class);
- protected Collection<SessionListener> listeners = new ArrayList<SessionListener>();
+ private long globalSessionTimeout = DEFAULT_GLOBAL_SESSION_TIMEOUT;
+ private Collection<SessionListener> listeners = new ArrayList<SessionListener>();
public AbstractSessionManager() {
}
+ /**
+ * Returns the system-wide default time in milliseconds that any session may remain idle before expiring. This
+ * value is just a main default for all sessions and may be overridden on a <em>per-session</em> basis by calling
+ * {@code Subject.getSession().}{@link Session#setTimeout setTimeout(long)} if so desired.
+ * <ul>
+ * <li>A negative return value means sessions never expire.</li>
+ * <li>A non-negative return value (0 or greater) means session timeout will occur as expected.</li>
+ * </ul>
+ * <p/>
+ * Unless overridden via the {@link #setGlobalSessionTimeout} method, the default value is
+ * {@link #DEFAULT_GLOBAL_SESSION_TIMEOUT}.
+ *
+ * @return the time in milliseconds that any session may remain idle before expiring.
+ */
+ public long getGlobalSessionTimeout() {
+ return this.globalSessionTimeout;
+ }
+
+ /**
+ * Sets the system-wide default time in milliseconds that any session may remain idle before expiring. This
+ * value is just a main default for all sessions and may be overridden on a <em>per-session</em> basis by calling
+ * {@code Subject.getSession().}{@link Session#setTimeout setTimeout(long)} if so desired.
+ *
+ * <ul>
+ * <li>A negative return value means sessions never expire.</li>
+ * <li>A non-negative return value (0 or greater) means session timeout will occur as expected.</li>
+ * </ul>
+ * <p/>
+ * Unless overridden by calling this method, the default value is {@link #DEFAULT_GLOBAL_SESSION_TIMEOUT}.
+ *
+ * @param globalSessionTimeout the time in milliseconds that any session may remain idel before expiring.
+ */
+ public void setGlobalSessionTimeout(long globalSessionTimeout) {
+ this.globalSessionTimeout = globalSessionTimeout;
+ }
+
public void setSessionListeners(Collection<SessionListener> listeners) {
if (listeners == null) {
this.listeners = new ArrayList<SessionListener>();
@@ -188,12 +235,7 @@
}
public boolean isValid(Serializable sessionId) {
- try {
- getSession(sessionId);
- } catch (InvalidSessionException e) {
- return false;
- }
- return true;
+ return doGetSession(sessionId) != null;
}
protected void onChange(Session s) {
diff --git a/core/src/org/jsecurity/session/mgt/AbstractValidatingSessionManager.java b/core/src/org/jsecurity/session/mgt/AbstractValidatingSessionManager.java
index 18b2176..0209c7e 100644
--- a/core/src/org/jsecurity/session/mgt/AbstractValidatingSessionManager.java
+++ b/core/src/org/jsecurity/session/mgt/AbstractValidatingSessionManager.java
@@ -45,15 +45,6 @@
private static final Log log = LogFactory.getLog(AbstractValidatingSessionManager.class);
- protected static final long MILLIS_PER_SECOND = 1000;
- protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
- protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
-
- /**
- * Default main session timeout value (30 * 60 * 1000 milliseconds = 30 minutes).
- */
- public static final long DEFAULT_GLOBAL_SESSION_TIMEOUT = 30 * MILLIS_PER_MINUTE;
-
/**
* The default interval at which sessions will be validated (1 hour);
* This can be overridden by calling {@link #setSessionValidationInterval(long)}
@@ -67,7 +58,7 @@
protected SessionValidationScheduler sessionValidationScheduler = null;
protected long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
- protected long globalSessionTimeout = DEFAULT_GLOBAL_SESSION_TIMEOUT;
+
public AbstractValidatingSessionManager() {
}
@@ -88,7 +79,7 @@
return sessionValidationScheduler;
}
- public void enableSessionValidationIfNecessary() {
+ private void enableSessionValidationIfNecessary() {
SessionValidationScheduler scheduler = getSessionValidationScheduler();
if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) {
enableSessionValidation();
@@ -96,38 +87,6 @@
}
/**
- * Returns the time in milliseconds that any session may remain idle before expiring. This
- * value is just a main default for all sessions and may be overridden by subclasses on a
- * <em>per-session</em> basis by overriding the {@link #getTimeout(Session)} method if
- * so desired.
- *
- * <ul>
- * <li>A negative return value means sessions never expire.</li>
- * <li>A non-negative return value (0 or greater) means session timeout will occur as expected.</li>
- * </ul>
- *
- * <p>Unless overridden via the {@link #setGlobalSessionTimeout} method, the default value is
- * {@link #DEFAULT_GLOBAL_SESSION_TIMEOUT}.
- *
- * @return the time in milliseconds that any session may remain idle before expiring.
- */
- public long getGlobalSessionTimeout() {
- return globalSessionTimeout;
- }
-
- /**
- * Sets the time in milliseconds that any session may remain idle before expiring. This
- * value is just a main default for all sessions. Subclasses may override the
- * {@link #getTimeout} method to determine time-out values on a <em>per-session</em> basis.
- *
- * @param globalSessionTimeout the time in milliseconds any session may remain idle before
- * expiring.
- */
- public void setGlobalSessionTimeout(int globalSessionTimeout) {
- this.globalSessionTimeout = globalSessionTimeout;
- }
-
- /**
* If using the underlying default <tt>SessionValidationScheduler</tt> (that is, the
* {@link #setSessionValidationScheduler(SessionValidationScheduler) setSessionValidationScheduler} method is
* never called) , this method allows one to specify how
@@ -196,13 +155,13 @@
}
protected SessionValidationScheduler createSessionValidationScheduler() {
- SessionValidationScheduler scheduler;
+ ExecutorServiceSessionValidationScheduler scheduler;
if (log.isDebugEnabled()) {
log.debug("No sessionValidationScheduler set. Attempting to create default instance.");
}
scheduler = new ExecutorServiceSessionValidationScheduler(this);
- ((ExecutorServiceSessionValidationScheduler) scheduler).setInterval(getSessionValidationInterval());
+ scheduler.setInterval(getSessionValidationInterval());
if (log.isTraceEnabled()) {
log.trace("Created default SessionValidationScheduler instance of type [" + scheduler.getClass().getName() + "].");
}
diff --git a/core/test/org/jsecurity/mgt/DefaultSecurityManagerTest.java b/core/test/org/jsecurity/mgt/DefaultSecurityManagerTest.java
index affee67..1ecfba9 100644
--- a/core/test/org/jsecurity/mgt/DefaultSecurityManagerTest.java
+++ b/core/test/org/jsecurity/mgt/DefaultSecurityManagerTest.java
@@ -39,9 +39,9 @@
@Before
public void setup() {
+ ThreadContext.clear();
sm = new DefaultSecurityManager();
sm.setRealm(new PropertiesRealm());
- ThreadContext.clear();
}
@After
diff --git a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
index a4b98d0..668916f 100644
--- a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
+++ b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
@@ -59,8 +59,9 @@
private String sessionMode = HTTP_SESSION_MODE; //default
public DefaultWebSecurityManager() {
- WebSessionManager sm = new DefaultWebSessionManager();
- applySessionManager(sm);
+ super();
+ WebSessionManager sm = new ServletContainerSessionManager();
+ setSessionManager(sm);
setRememberMeManager(new WebRememberMeManager());
setSubjectFactory(new WebSubjectFactory(this, sm));
}
@@ -142,13 +143,13 @@
HTTP_SESSION_MODE + "' being the default.";
throw new IllegalArgumentException(msg);
}
- boolean recreate = this.sessionMode == null || !this.sessionMode.equals(sessionMode);
- this.sessionMode = sessionMode;
+ boolean recreate = this.sessionMode == null || !this.sessionMode.equals(mode);
+ this.sessionMode = mode;
if (recreate) {
LifecycleUtils.destroy(getSessionManager());
- SessionManager sessionManager = newSessionManagerInstance();
- applySessionManager(sessionManager);
- setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) sessionManager));
+ WebSessionManager sessionManager = createSessionManager(mode);
+ setSessionManager(sessionManager);
+ setSubjectFactory(new WebSubjectFactory(this, sessionManager));
}
}
@@ -156,17 +157,18 @@
return this.sessionMode == null || this.sessionMode.equals(HTTP_SESSION_MODE);
}
- protected SessionManager newSessionManagerInstance() {
- if (isHttpSessionMode()) {
+ protected WebSessionManager createSessionManager(String sessionMode) {
+ if (sessionMode == null || sessionMode.equalsIgnoreCase(HTTP_SESSION_MODE)) {
if (log.isInfoEnabled()) {
- log.info(HTTP_SESSION_MODE + " mode - enabling ServletContainerSessionManager (Http Sessions)");
+ log.info(HTTP_SESSION_MODE + " mode - enabling ServletContainerSessionManager (HTTP-only Sessions)");
}
return new ServletContainerSessionManager();
} else {
if (log.isInfoEnabled()) {
- log.info(JSECURITY_SESSION_MODE + " mode - enabling WebSessionManager (JSecurity heterogenous sessions)");
+ log.info(JSECURITY_SESSION_MODE + " mode - enabling DefaultWebSessionManager (HTTP + heterogeneous-client sessions)");
}
return new DefaultWebSessionManager();
}
}
+
}
diff --git a/web/src/org/jsecurity/web/session/ServletContainerSessionManager.java b/web/src/org/jsecurity/web/session/ServletContainerSessionManager.java
index 7d18ac8..a7f4262 100644
--- a/web/src/org/jsecurity/web/session/ServletContainerSessionManager.java
+++ b/web/src/org/jsecurity/web/session/ServletContainerSessionManager.java
@@ -35,18 +35,19 @@
/**
* SessionManager implementation providing Session implementations that are merely wrappers for the
* Servlet container's HttpSession.
- *
- * <p>Despite its name, this implementation <em>does not</em> itself manage Sessions since the Servlet container
+ * <p/>
+ * Despite its name, this implementation <em>does not</em> itself manage Sessions since the Servlet container
* provides the actual management support. This class mainly exists to 'impersonate' a regular JSecurity
* <tt>SessionManager</tt> so it can be pluggable into a normal JSecurity configuration in a pure web application.
+ * <p/>
+ * Note that because this implementation relies on the {@link HttpSession HttpSession}, it is only functional in a
+ * servlet container. I.e. it is <em>NOT</em> capable of supporting Sessions any clients other than
+ * {@code HttpRequest/HttpResponse} based clients.
*
- * <p>Note that because this implementation relies on the <tt>HttpSession</tt>, it is only functional in a servlet
- * container. I.e. it is <em>NOT</em> capable of supporting Sessions any clients other than HttpRequest/HttpResponse
- * based clients.
- *
- * <p>Therefore, if you need heterogenous Session support across multiple client mediums (e.g. web pages,
- * Flash applets, Java Web Start applications, etc.), use the {@link DefaultWebSessionManager WebSessionManager} instead. The
- * <tt>WebSessionManager</tt> supports both traditional web-based access as well as non web-based clients.
+ * <p>Therefore, if you need {@code Session} access from heterogenous client mediums (e.g. web pages,
+ * Flash applets, Java Web Start applications, etc.), use the {@link DefaultWebSessionManager DefaultWebSessionManager}
+ * instead. The {@code DefaultWebSessionManager} supports both traditional web-based access as well as non web-based
+ * clients.
*
* @author Les Hazlewood
* @since 0.9
@@ -55,6 +56,8 @@
//TODO - complete JavaDoc
+ //TODO - read session timeout value from web.xml
+
public ServletContainerSessionManager() {
}
@@ -78,6 +81,11 @@
protected Session createSession(InetAddress originatingHost) throws HostUnauthorizedException, IllegalArgumentException {
ServletRequest request = WebUtils.getRequiredServletRequest();
HttpSession httpSession = ((HttpServletRequest) request).getSession();
+
+ //ensure that the httpSession timeout reflects what is configured:
+ long timeoutMillis = getGlobalSessionTimeout();
+ httpSession.setMaxInactiveInterval((int) (timeoutMillis / MILLIS_PER_SECOND));
+
return createSession(httpSession, originatingHost);
}