You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2010/03/26 02:41:05 UTC
svn commit: r927664 - in /incubator/shiro/trunk:
core/src/main/java/org/apache/shiro/cache/
core/src/main/java/org/apache/shiro/mgt/
core/src/main/java/org/apache/shiro/session/mgt/eis/ samples/spring-client/
samples/spring/
Author: lhazlewood
Date: Fri Mar 26 01:41:04 2010
New Revision: 927664
URL: http://svn.apache.org/viewvc?rev=927664&view=rev
Log:
SHIRO-144:
- Created AbstractSessionDAO and made CachingSessionDAO an abstract subclass.
- MemorySessionDAO is now a concrete class of AbstractSessionDAO and does not subclass CachingSessionDAO.
- The DefaultSessionManager now uses the MemorySessionDAO due to the previous SoftHashMap based default CacheManager losing sessions due to garbage collection.
- Deprecated HashtableCacheManager and HashtableCache classes have been deleted in preparation for the 1.0 release.
SHIRO-122:
- New AbstractSessionDAO now supports the concept of a SessionIdGenerator.
- Existing code has been refactored into two new implementations: RandomSessionIdGenerator and JavaUuidSessionIdGenerator.
- The AbstractSessionDAO now defaults to the JavaUuidSessionIdgGenerator as its default ID generation strategy.
Added:
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/AbstractCacheManager.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MemoryConstrainedCacheManager.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/JavaUuidSessionIdGenerator.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionIdGenerator.java
Removed:
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/HashtableCache.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/HashtableCacheManager.java
Modified:
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MapCache.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java
incubator/shiro/trunk/samples/spring-client/pom.xml
incubator/shiro/trunk/samples/spring/pom.xml
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/AbstractCacheManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/AbstractCacheManager.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/AbstractCacheManager.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/AbstractCacheManager.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2008 Les Hazlewood
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.cache;
+
+import org.apache.shiro.util.Destroyable;
+import org.apache.shiro.util.LifecycleUtils;
+import org.apache.shiro.util.StringUtils;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Very simple abstract {@code CacheManager} implementation that retains all created {@link Cache Cache} instances in
+ * an in-memory {@link ConcurrentMap ConcurrentMap}. {@code Cache} instance creation is left to subclasses via
+ * the {@link #createCache createCache} method implementation.
+ *
+ * @since 1.0
+ */
+public abstract class AbstractCacheManager implements CacheManager, Destroyable {
+
+ /**
+ * Retains all Cache objects maintained by this cache manager.
+ */
+ private final ConcurrentMap<String, Cache> caches;
+
+ /**
+ * Default no-arg constructor that instantiates an internal name-to-cache {@code ConcurrentMap}.
+ */
+ public AbstractCacheManager() {
+ this.caches = new ConcurrentHashMap<String, Cache>();
+ }
+
+ /**
+ * Returns the cache with the specified {@code name}. If the cache instance does not yet exist, it will be lazily
+ * created, retained for further access, and then returned.
+ *
+ * @param name the name of the cache to acquire.
+ * @return the cache with the specified {@code name}.
+ * @throws IllegalArgumentException if the {@code name} argument is {@code null} or does not contain text.
+ * @throws CacheException if there is a problem lazily creating a {@code Cache} instance.
+ */
+ public Cache getCache(String name) throws IllegalArgumentException, CacheException {
+ if (!StringUtils.hasText(name)) {
+ throw new IllegalArgumentException("Cache name cannot be null or empty.");
+ }
+
+ Cache cache;
+
+ cache = caches.get(name);
+ if (cache == null) {
+ cache = createCache(name);
+ Cache existing = caches.putIfAbsent(name, cache);
+ if (existing != null) {
+ cache = existing;
+ }
+ }
+
+ return cache;
+ }
+
+ /**
+ * Creates a new {@code Cache} instance associated with the specified {@code name}.
+ *
+ * @param name the name of the cache to create
+ * @return a new {@code Cache} instance associated with the specified {@code name}.
+ * @throws CacheException if the {@code Cache} instance cannot be created.
+ */
+ protected abstract Cache createCache(String name) throws CacheException;
+
+ /**
+ * Cleanup method that first {@link LifecycleUtils#destroy destroys} all of it's managed caches and then
+ * {@link java.util.Map#clear clears} out the internally referenced cache map.
+ *
+ * @throws Exception if any of the managed caches can't destroy properly.
+ */
+ public void destroy() throws Exception {
+ while (!caches.isEmpty()) {
+ for (Cache cache : caches.values()) {
+ LifecycleUtils.destroy(cache);
+ }
+ caches.clear();
+ }
+ }
+
+ public String toString() {
+ Collection<Cache> values = caches.values();
+ StringBuilder sb = new StringBuilder(getClass().getSimpleName())
+ .append(" with ")
+ .append(caches.size())
+ .append(" cache(s)): [");
+ int i = 0;
+ for (Cache cache : values) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(cache.toString());
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+}
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MapCache.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MapCache.java?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MapCache.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MapCache.java Fri Mar 26 01:41:04 2010
@@ -95,6 +95,10 @@ public class MapCache implements Cache {
}
public String toString() {
- return getClass().getName() + " : [" + name + "]";
+ return new StringBuilder("MapCache '")
+ .append(name).append("' (")
+ .append(map.size())
+ .append(" entries)")
+ .toString();
}
}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MemoryConstrainedCacheManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MemoryConstrainedCacheManager.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MemoryConstrainedCacheManager.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/cache/MemoryConstrainedCacheManager.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 Les Hazlewood
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.cache;
+
+import org.apache.shiro.util.SoftHashMap;
+
+/**
+ * Simple memory-only based {@link CacheManager CacheManager} implementation usable in production
+ * environments. It will not cause memory leaks as it produces {@link Cache Cache}s backed by
+ * {@link SoftHashMap SoftHashMap}s which auto-size themselves based on the runtime environment's memory
+ * limitations and garbage collection behavior.
+ * <p/>
+ * While the {@code Cache} instances created are thread-safe, they do not offer any enterprise-level features such as
+ * cache coherency, optimistic locking, failover or other similar features. For more enterprise features, consider
+ * using a different {@code CacheManager} implementation backed by an enterprise-grade caching product (EhCache,
+ * TerraCotta, Coherence, GigaSpaces, etc, etc).
+ *
+ * @since 1.0
+ */
+public class MemoryConstrainedCacheManager extends AbstractCacheManager {
+
+ /**
+ * Returns a new {@link MapCache MapCache} instance backed by a {@link SoftHashMap}.
+ *
+ * @param name the name of the cache
+ * @return a new {@link MapCache MapCache} instance backed by a {@link SoftHashMap}.
+ */
+ @Override
+ protected Cache createCache(String name) {
+ return new MapCache(name, new SoftHashMap());
+ }
+}
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java Fri Mar 26 01:41:04 2010
@@ -20,7 +20,7 @@ package org.apache.shiro.mgt;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.CacheManagerAware;
-import org.apache.shiro.cache.DefaultCacheManager;
+import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.util.Destroyable;
import org.apache.shiro.util.LifecycleUtils;
@@ -48,7 +48,7 @@ public abstract class CachingSecurityMan
* Default no-arg constructor that will automatically attempt to initialize a default cacheManager
*/
public CachingSecurityManager() {
- this.cacheManager = new DefaultCacheManager();
+ this.cacheManager = new MemoryConstrainedCacheManager();
}
/**
@@ -91,4 +91,5 @@ public abstract class CachingSecurityMan
LifecycleUtils.destroy(getCacheManager());
this.cacheManager = null;
}
+
}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.session.mgt.eis;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.session.mgt.SimpleSession;
+
+import java.io.Serializable;
+
+
+/**
+ * An abstract {@code SessionDAO} implementation that performs some sanity checks on session creation and reading and
+ * allows for pluggable Session ID generation strategies if desired. The {@code SessionDAO}
+ * {@link SessionDAO#update update} and {@link SessionDAO#delete delete} methods are left to
+ * subclasses.
+ * <h3>Session ID Generation</h3>
+ * This class also allows for plugging in a {@link SessionIdGenerator} for custom ID generation strategies. This is
+ * optional, as the default generator is probably sufficient for most cases. Subclass implementations that do use a
+ * generator (default or custom) will want to call the
+ * {@link #generateSessionId(org.apache.shiro.session.Session)} method from within their {@link #doCreate}
+ * implementations.
+ * <p/>
+ * Subclass implementations that rely on the EIS data store to generate the ID automatically (e.g. when the session
+ * ID is also an auto-generated primary key), they can simply ignore the {@code SessionIdGenerator} concept
+ * entirely and just return the data store's ID from the {@link #doCreate} implementation.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public abstract class AbstractSessionDAO implements SessionDAO {
+
+ /**
+ * Optional SessionIdGenerator instance available to subclasses via the
+ * {@link #generateSessionId(org.apache.shiro.session.Session)} method.
+ */
+ private SessionIdGenerator sessionIdGenerator;
+
+ /**
+ * Default no-arg constructor that defaults the {@link #setSessionIdGenerator sessionIdGenerator} to be a
+ * {@link org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator}.
+ */
+ public AbstractSessionDAO() {
+ this.sessionIdGenerator = new JavaUuidSessionIdGenerator();
+ }
+
+ /**
+ * Returns the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)}
+ * method. Unless overridden by the {@link #setSessionIdGenerator(SessionIdGenerator)} method, the default instance
+ * is a {@link JavaUuidSessionIdGenerator}.
+ *
+ * @return the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)}
+ * method.
+ */
+ public SessionIdGenerator getSessionIdGenerator() {
+ return sessionIdGenerator;
+ }
+
+ /**
+ * Sets the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)}
+ * method. Unless overridden by this method, the default instance ss a {@link JavaUuidSessionIdGenerator}.
+ *
+ * @param sessionIdGenerator the {@code SessionIdGenerator} to use in the
+ * {@link #generateSessionId(org.apache.shiro.session.Session)} method.
+ */
+ public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator) {
+ this.sessionIdGenerator = sessionIdGenerator;
+ }
+
+ /**
+ * Generates a new ID to be applied to the specified {@code session} instance. This method is usually called
+ * from within a subclass's {@link #doCreate} implementation where they assign the returned id to the session
+ * instance and then create a record with this ID in the EIS data store.
+ * <p/>
+ * Subclass implementations backed by EIS data stores that auto-generate IDs during record creation, such as
+ * relational databases, don't need to use this method or the {@link #getSessionIdGenerator() sessionIdGenerator}
+ * attribute - they can simply return the data store's generated ID from the {@link #doCreate} implementation
+ * if desired.
+ * <p/>
+ * This implementation uses the {@link #setSessionIdGenerator configured} {@link SessionIdGenerator} to create
+ * the ID.
+ *
+ * @param session the new session instance for which an ID will be generated and then assigned
+ * @return the generated ID to assign
+ */
+ protected Serializable generateSessionId(Session session) {
+ if (this.sessionIdGenerator == null) {
+ String msg = "sessionIdGenerator attribute has not been configured.";
+ throw new IllegalStateException(msg);
+ }
+ return this.sessionIdGenerator.generateId(session);
+ }
+
+ /**
+ * Creates the session by delegating EIS creation to subclasses via the {@link #doCreate} method, and then
+ * asserting that the returned sessionId is not null.
+ *
+ * @param session Session object to create in the EIS and associate with an ID.
+ */
+ public Serializable create(Session session) {
+ Serializable sessionId = doCreate(session);
+ verifySessionId(sessionId);
+ return sessionId;
+ }
+
+ /**
+ * Ensures the sessionId returned from the subclass implementation of {@link #doCreate} is not null and not
+ * already in use.
+ *
+ * @param sessionId session id returned from the subclass implementation of {@link #doCreate}
+ */
+ private void verifySessionId(Serializable sessionId) {
+ if (sessionId == null) {
+ String msg = "sessionId returned from doCreate implementation is null. Please verify the implementation.";
+ throw new IllegalStateException(msg);
+ }
+ }
+
+ /**
+ * Utility method available to subclasses that wish to
+ * assign a generated session ID to the session instance directly. This method is not used by the
+ * {@code AbstractSessionDAO} implementation directly, but it is provided so subclasses don't
+ * need to know the {@code Session} implementation if they don't need to.
+ * <p/>
+ * This default implementation casts the argument to a {@link SimpleSession}, Shiro's default EIS implementation.
+ *
+ * @param session the session instance to which the sessionId will be applied
+ * @param sessionId the id to assign to the specified session instance.
+ */
+ protected void assignSessionId(Session session, Serializable sessionId) {
+ ((SimpleSession) session).setId(sessionId);
+ }
+
+ /**
+ * Subclass hook to actually persist the given <tt>Session</tt> instance to the underlying EIS.
+ *
+ * @param session the Session instance to persist to the EIS.
+ * @return the id of the session created in the EIS (i.e. this is almost always a primary key and should be the
+ * value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}.
+ */
+ protected abstract Serializable doCreate(Session session);
+
+ /**
+ * Retrieves the Session object from the underlying EIS identified by <tt>sessionId</tt> by delegating to
+ * the {@link #doReadSession(java.io.Serializable)} method. If {@code null} is returned from that method, an
+ * {@link UnknownSessionException} will be thrown.
+ *
+ * @param sessionId the id of the session to retrieve from the EIS.
+ * @return the session identified by <tt>sessionId</tt> in the EIS.
+ * @throws UnknownSessionException if the id specified does not correspond to any session in the EIS.
+ */
+ public Session readSession(Serializable sessionId) throws UnknownSessionException {
+ Session s = doReadSession(sessionId);
+ if (s == null) {
+ throw new UnknownSessionException("There is no session with id [" + sessionId + "]");
+ }
+ return s;
+ }
+
+ /**
+ * Subclass implementation hook that retrieves the Session object from the underlying EIS or {@code null} if a
+ * session with that ID could not be found.
+ *
+ * @param sessionId the id of the <tt>Session</tt> to retrieve.
+ * @return the Session in the EIS identified by <tt>sessionId</tt> or {@code null} if a
+ * session with that ID could not be found.
+ */
+ protected abstract Session doReadSession(Serializable sessionId);
+
+}
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java Fri Mar 26 01:41:04 2010
@@ -23,28 +23,33 @@ import org.apache.shiro.cache.CacheManag
import org.apache.shiro.cache.CacheManagerAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.session.mgt.ValidatingSession;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
-
/**
* An CachingSessionDAO is a SessionDAO that provides a transparent caching layer between the components that
- * use it and the underlying EIS (Enterprise Information System) for enhanced performance.
+ * use it and the underlying EIS (Enterprise Information System) session backing store (for example, filesystem,
+ * database, enterprise grid/cloud, etc).
+ * <p/>
+ * This implementation caches all active sessions in a configured
+ * {@link #getActiveSessionsCache() activeSessionsCache}. This property is {@code null} by default and if one is
+ * not explicitly set, a {@link #setCacheManager cacheManager} is expected to be configured which will in turn be used
+ * to acquire the {@code Cache} instance to use for the {@code activeSessionsCache}.
* <p/>
- * <p>This implementation caches all active sessions in a cache created by a
- * {@link org.apache.shiro.cache.CacheManager}. All <tt>SessionDAO</tt> methods are implemented by this class to employ
+ * All {@code SessionDAO} methods are implemented by this class to employ
* caching behavior and delegates the actual EIS operations to respective do* methods to be implemented by
* subclasses (doCreate, doRead, etc).
*
* @author Les Hazlewood
* @since 0.2
*/
-public abstract class CachingSessionDAO implements SessionDAO, CacheManagerAware {
+public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware {
/**
- * The default active sessions cache name, equal to <code>shiro-activeSessionCache</code>.
+ * The default active sessions cache name, equal to {@code shiro-activeSessionCache}.
*/
public static final String ACTIVE_SESSION_CACHE_NAME = "shiro-activeSessionCache";
@@ -70,18 +75,23 @@ public abstract class CachingSessionDAO
}
/**
- * Sets the cacheManager to use for constructing the session cache.
+ * Sets the cacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if
+ * one is not configured.
*
* @param cacheManager the manager to use for constructing the session cache.
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
- //force cache reload:
- this.activeSessions = null;
+ if (cacheManager != null) {
+ //force cache reload:
+ this.activeSessions = null;
+ }
}
/**
- * Returns the CacheManager used by the implementation that creates the activeSessions Cache.
+ * Returns the CacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if
+ * one is not configured. That is, the {@code CacheManager} will only be used if the
+ * {@link #getActiveSessionsCache() activeSessionsCache} property is {@code null}.
*
* @return the CacheManager used by the implementation that creates the activeSessions Cache.
*/
@@ -90,7 +100,7 @@ public abstract class CachingSessionDAO
}
/**
- * Returns the name of the actives sessions cache to be returned by the <code>CacheManager</code>. Unless
+ * Returns the name of the actives sessions cache to be returned by the {@code CacheManager}. Unless
* overridden by {@link #setActiveSessionsCacheName(String)}, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}.
*
* @return the name of the active sessions cache.
@@ -100,57 +110,65 @@ public abstract class CachingSessionDAO
}
/**
- * Sets the name of the active sessions cache to be returned by the <code>CacheManager</code>. Defaults to
+ * Sets the name of the active sessions cache to be returned by the {@code CacheManager}. Defaults to
* {@link #ACTIVE_SESSION_CACHE_NAME}.
*
- * @param activeSessionsCacheName the name of the active sessions cache to be returned by the <code>CacheManager</code>.
+ * @param activeSessionsCacheName the name of the active sessions cache to be returned by the {@code CacheManager}.
*/
public void setActiveSessionsCacheName(String activeSessionsCacheName) {
this.activeSessionsCacheName = activeSessionsCacheName;
}
/**
- * Returns the cache instance to use for storing active sessions.
+ * Returns the cache instance to use for storing active sessions. If one is not available (it is {@code null}),
+ * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured}
+ * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
*
- * @return the cache instance to use for storing active sessions.
+ * @return the cache instance to use for storing active sessions or {@code null} if the {@code Cache} instance
+ * should be retrieved from the
*/
public Cache getActiveSessionsCache() {
return this.activeSessions;
}
/**
+ * Sets the cache instance to use for storing active sessions. If one is not set (it remains {@code null}),
+ * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured}
+ * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
+ *
+ * @param cache the cache instance to use for storing active sessions or {@code null} if the cache is to be
+ * acquired from the {@link #setCacheManager configured} {@code CacheManager}.
+ */
+ public void setActiveSessionsCache(Cache cache) {
+ this.activeSessions = cache;
+ }
+
+ /**
* Returns the active sessions cache, but if that cache instance is null, first lazily creates the cache instance
* via the {@link #createActiveSessionsCache()} method and then returns the instance.
* <p/>
- * Note that this method will only return a non-null value code if the <code>CacheManager</code> has been set. If
+ * Note that this method will only return a non-null value code if the {@code CacheManager} has been set. If
* not set, there will be no cache.
*
* @return the active sessions cache instance.
*/
protected Cache getActiveSessionsCacheLazy() {
- if (this.activeSessions == null) {
- this.activeSessions = createActiveSessionsCache();
+ Cache activeSessions = getActiveSessionsCache();
+ if (activeSessions == null) {
+ activeSessions = createActiveSessionsCache();
+ setActiveSessionsCache(activeSessions);
}
- return this.activeSessions;
- }
-
- /**
- * Sets the cache instance to use for storing active sessions.
- *
- * @param cache the cache instance to use for storing active sessions.
- */
- public void setActiveSessionsCache(Cache cache) {
- this.activeSessions = cache;
+ return activeSessions;
}
/**
* Creates a cache instance used to store active sessions. Creation is done by first
- * {@link #getCacheManager() acquiring} the <code>CacheManager</code>. If the cache manager is not null, the
+ * {@link #getCacheManager() acquiring} the {@code CacheManager}. If the cache manager is not null, the
* cache returned is that resulting from the following call:
* <pre> String name = {@link #getActiveSessionsCacheName() getActiveSessionsCacheName()};
* cacheManager.getCache(name);</pre>
*
- * @return a cache instance used to store active sessions, or <em>null</code> if the <code>CacheManager</code> has
+ * @return a cache instance used to store active sessions, or {@code null} if the {@code CacheManager} has
* not been set.
*/
protected Cache createActiveSessionsCache() {
@@ -164,24 +182,23 @@ public abstract class CachingSessionDAO
}
/**
- * Creates the session by delegating EIS creation to subclasses via the {@link #doCreate} method, and then
- * caches the session.
+ * Calls {@code super.create(session)}, then caches the session keyed by the returned {@code sessionId}, and then
+ * returns this {@code sessionId}.
*
* @param session Session object to create in the EIS and then cache.
*/
public Serializable create(Session session) {
- Serializable sessionId = doCreate(session);
- verifySessionId(sessionId);
+ Serializable sessionId = super.create(session);
cache(session, sessionId);
return sessionId;
}
/**
- * Returns the cached session with the corresponding <code>sessionId</code> or <code>null</code> if there is
+ * Returns the cached session with the corresponding {@code sessionId} or {@code null} if there is
* no session cached under that id (or if there is no Cache).
*
* @param sessionId the id of the cached session to acquire.
- * @return the cached session with the corresponding <code>sessionId</code>, or <code>null</code> if the session
+ * @return the cached session with the corresponding {@code sessionId}, or {@code null} if the session
* does not exist or is not cached.
*/
protected Session getCachedSession(Serializable sessionId) {
@@ -197,11 +214,11 @@ public abstract class CachingSessionDAO
/**
* Returns the Session with the specified id from the specified cache. This method simply calls
- * <code>cache.get(sessionId)</code> and can be overridden by subclasses for custom acquisition behavior.
+ * {@code cache.get(sessionId)} and can be overridden by subclasses for custom acquisition behavior.
*
* @param sessionId the id of the session to acquire.
* @param cache the cache to acquire the session from
- * @return the cached session, or <code>null</code> if the session wasn't in the cache.
+ * @return the cached session, or {@code null} if the session wasn't in the cache.
*/
protected Session getCachedSession(Serializable sessionId, Cache cache) {
return (Session) cache.get(sessionId);
@@ -226,8 +243,8 @@ public abstract class CachingSessionDAO
}
/**
- * Caches the specified session in the given cache under the key of <code>sessionId</code>. This implementation
- * simply calls <code>cache.put(sessionId, session)</code> and can be overridden for custom behavior.
+ * Caches the specified session in the given cache under the key of {@code sessionId}. This implementation
+ * simply calls {@code cache.put(sessionId,session)} and can be overridden for custom behavior.
*
* @param session the session to cache
* @param sessionId the id of the session, expected to be the cache key.
@@ -238,69 +255,26 @@ public abstract class CachingSessionDAO
}
/**
- * Ensures the sessionId returned from the subclass implementation of {@link #doCreate} is not null and not
- * already in use.
- *
- * @param sessionId session id returned from the subclass implementation of {@link #doCreate}
- */
- protected void verifySessionId(Serializable sessionId) {
- if (sessionId == null) {
- String msg = "sessionId returned from doCreate implementation is null. Please verify the implementation.";
- throw new IllegalStateException(msg);
- }
- }
-
- /**
- * Subclass hook to actually persist the given <tt>Session</tt> instance to the underlying EIS.
- *
- * @param session the Session instance to persist to the EIS.
- * @return the id of the session created in the EIS (i.e. this is almost always a primary key and should be the
- * value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}.
- */
- protected abstract Serializable doCreate(Session session);
-
- /**
- * Retrieves the Session object from the underlying EIS identified by <tt>sessionId</tt>.
- * <p/>
- * <p>Upon receiving the Session object from the subclass's {@link #doReadSession} implementation, it will be
- * cached first and then returned to the caller.
+ * Attempts to acquire the Session from the cache first using the session ID as the cache key. If no session
+ * is found, {@code super.readSession(sessionId)} is called to perform the actual retrieval.
*
* @param sessionId the id of the session to retrieve from the EIS.
- * @return the session identified by <tt>sessionId</tt> in the EIS.
+ * @return the session identified by {@code sessionId} in the EIS.
* @throws UnknownSessionException if the id specified does not correspond to any session in the cache or EIS.
*/
public Session readSession(Serializable sessionId) throws UnknownSessionException {
-
Session s = getCachedSession(sessionId);
-
- if (s == null) {
- s = doReadSession(sessionId);
- }
-
if (s == null) {
- throw new UnknownSessionException("There is no session with id [" + sessionId + "]");
+ s = super.readSession(sessionId);
}
return s;
}
/**
- * Subclass implmentation hook to actually retrieve the Session object from the underlying EIS.
- *
- * @param sessionId the id of the <tt>Session</tt> to retrieve.
- * @return the Session in the EIS identified by <tt>sessionId</tt>
- */
- protected abstract Session doReadSession(Serializable sessionId);
-
- /**
- * Updates the state of the given session to the EIS.
- * <p/>
- * <p>If the specified session was previously cached, and the session is now invalid,
- * it will be removed from the cache.
- * <p/>
- * <p>If the specified session is not stopped or expired, and was not yet in the cache, it will be added to the
- * cache.
- * <p/>
- * <p>Finally, this method calls {@link #doUpdate} for the subclass to actually push the object state to the EIS.
+ * Updates the state of the given session to the EIS by first delegating to
+ * {@link #doUpdate(org.apache.shiro.session.Session)}. If the session is a {@link ValidatingSession}, it will
+ * be added to the cache only if it is {@link ValidatingSession#isValid()} and if invalid, will be removed from the
+ * cache. If it is not a {@code ValidatingSession} instance, it will be added to the cache in any event.
*
* @param session the session object to update in the EIS.
* @throws UnknownSessionException if no existing EIS session record exists with the
@@ -308,11 +282,19 @@ public abstract class CachingSessionDAO
*/
public void update(Session session) throws UnknownSessionException {
doUpdate(session);
- cache(session, session.getId());
+ if (session instanceof ValidatingSession) {
+ if (((ValidatingSession) session).isValid()) {
+ cache(session, session.getId());
+ } else {
+ uncache(session);
+ }
+ } else {
+ cache(session, session.getId());
+ }
}
/**
- * Subclass implementation hook to actually persist the <tt>Session</tt>'s state to the underlying EIS.
+ * Subclass implementation hook to actually persist the {@code Session}'s state to the underlying EIS.
*
* @param session the session object whose state will be propagated to the EIS.
*/
@@ -370,7 +352,7 @@ public abstract class CachingSessionDAO
if (cache != null) {
return cache.values();
} else {
- return Collections.EMPTY_LIST;
+ return Collections.emptySet();
}
}
}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.session.mgt.eis;
+
+import org.apache.shiro.cache.AbstractCacheManager;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheException;
+import org.apache.shiro.cache.MapCache;
+import org.apache.shiro.session.Session;
+
+import java.io.Serializable;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * SessionDAO implementation that relies on an enterprise caching product as the EIS system of record for all sessions.
+ * It is expected that an injected {@link org.apache.shiro.cache.Cache Cache} or
+ * {@link org.apache.shiro.cache.CacheManager CacheManager} is backed by an enterprise caching product that can support
+ * all application sessions and/or provide disk paging for resilient data storage.
+ * <h2>Production Note</h2>
+ * This implementation defaults to using an in-memory map-based {@code CacheManager}, which is great for testing but
+ * will typically not scale for production environments and could easily cause {@code OutOfMemoryException}s. Just
+ * don't forget to configure<b>*</b> an instance of this class with a production-grade {@code CacheManager} that can
+ * handle disk paging for large numbers of sessions and you'll be fine.
+ * <p/>
+ * <b>*</b>If you configure Shiro's {@code SecurityManager} instance with such a {@code CacheManager}, it will be
+ * automatically applied to an instance of this class and you won't need to explicitly set it in configuration.
+ * <h3>Implementation Details</h3>
+ * This implementation relies heavily on the {@link CachingSessionDAO parent class}'s transparent caching behavior for
+ * all storage operations with the enterprise caching product. Because the parent class uses a {@code Cache} or
+ * {@code CacheManager} to perform caching, and the cache is considered the system of record, nothing further needs to
+ * be done for the {@link #doReadSession}, {@link #doUpdate} and {@link #doDelete} method implementations. This class
+ * implements those methods as required by the parent class, but they essentially do nothing.
+ *
+ * @since 1.0
+ */
+public class EnterpriseCacheSessionDAO extends CachingSessionDAO {
+
+ public EnterpriseCacheSessionDAO() {
+ setCacheManager(new AbstractCacheManager() {
+ @Override
+ protected Cache createCache(String name) throws CacheException {
+ return new MapCache(name, new ConcurrentHashMap());
+ }
+ });
+ }
+
+ protected Serializable doCreate(Session session) {
+ Serializable sessionId = generateSessionId(session);
+ assignSessionId(session, sessionId);
+ return sessionId;
+ }
+
+ protected Session doReadSession(Serializable sessionId) {
+ return null; //should never execute because this implementation relies on parent class to access cache, which
+ //is where all sessions reside - it is the cache implementation that determines if the
+ //cache is memory only or disk-persistent, etc.
+ }
+
+ protected void doUpdate(Session session) {
+ //does nothing - parent class persists to cache.
+ }
+
+ protected void doDelete(Session session) {
+ //does nothing - parent class removes from cache.
+ }
+}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/JavaUuidSessionIdGenerator.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/JavaUuidSessionIdGenerator.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/JavaUuidSessionIdGenerator.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/JavaUuidSessionIdGenerator.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.session.mgt.eis;
+
+import org.apache.shiro.session.Session;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * {@link SessionIdGenerator} that generates String values of JDK {@link java.util.UUID}'s as the session IDs.
+ *
+ * @since 1.0
+ */
+public class JavaUuidSessionIdGenerator implements SessionIdGenerator {
+
+ /**
+ * Ignores the method argument and simply returns
+ * {@code UUID}.{@link java.util.UUID#randomUUID() randomUUID()}.{@code toString()}.
+ *
+ * @param session the {@link Session} instance to which the ID will be applied.
+ * @return the String value of the JDK's next {@link UUID#randomUUID() randomUUID()}.
+ */
+ public Serializable generateId(Session session) {
+ return UUID.randomUUID().toString();
+ }
+}
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java Fri Mar 26 01:41:04 2010
@@ -18,104 +18,90 @@
*/
package org.apache.shiro.session.mgt.eis;
-import org.apache.shiro.cache.HashtableCacheManager;
import org.apache.shiro.session.Session;
-import org.apache.shiro.session.mgt.SimpleSession;
-import org.apache.shiro.util.JavaEnvironment;
+import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
-import java.util.Random;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
- * Simple memory-based implementation of the SessionDAO that relies on its configured
- * {@link #setCacheManager CacheManager} for Session caching and in-memory persistence.
+ * Simple memory-based implementation of the SessionDAO that stores all of its sessions in an in-memory
+ * {@link ConcurrentMap}. <b>This implementation does not page to disk and is therefore unsuitable for applications
+ * that could experience a large amount of sessions</b> and would therefore cause {@code OutOfMemoryException}s. It is
+ * <em>not</em> recommended for production use in most environments.
+ * <h2>Memory Restrictions</h2>
+ * If your application is expected to host many sessions beyond what can be stored in the
+ * memory available to the JVM, it is highly recommended to use a different {@code SessionDAO} implementation which
+ * uses a more expansive or permanent backing data store.
* <p/>
- * <p><b>PLEASE NOTE</b> the default CacheManager internal to this implementation is a
- * {@link org.apache.shiro.cache.HashtableCacheManager HashtableCacheManager}, which IS NOT RECOMMENDED for production environments.
- * <p/>
- * <p>If you
- * want to use the MemorySessionDAO in production environments, such as those that require session data to be
- * recoverable in case of a server restart, you should do one of two things (or both):
- * <p/>
- * <ul>
- * <li>Configure it with a production-quality CacheManager. The
- * {@code org.apache.shiro.cache.ehcache.EhCacheManager} is one such implementation. It is not used by default
- * to prevent a forced runtime dependency on ehcache.jar that may not be required in many environments)</li><br/>
- * <li>If you need session information beyond their transient start/stop lifetimes, you should subclass this one and
- * override the <tt>do*</tt> methods to perform CRUD operations using an EIS-tier API (e.g. Hibernate/JPA/JCR/etc).
- * This class implementation does not retain sessions after they have been stopped or expired, so you would need to
- * override these methods to ensure Sessions can be accessed beyond Shiro's needs.</li>
- * </ul>
+ * In this case, it is recommended to instead use a custom
+ * {@link CachingSessionDAO} implementation that communicates with a higher-capacity data store of your choice
+ * (file system, database, etc).
+ * <h2>Changes in 1.0</h2>
+ * This implementation prior to 1.0 used to subclass the {@link CachingSessionDAO}, but this caused problems with many
+ * cache implementations that would expunge entries due to TTL settings, resulting in Sessions that would be randomly
+ * (and permanently) lost. The Shiro 1.0 release refactored this implementation to be 100% memory-based (without
+ * {@code Cache} usage to avoid this problem.
*
- * @author Les Hazlewood
+ * @see CachingSessionDAO
* @since 0.1
*/
-public class MemorySessionDAO extends CachingSessionDAO {
-
- //TODO - complete JavaDoc
+public class MemorySessionDAO extends AbstractSessionDAO {
private static final Logger log = LoggerFactory.getLogger(MemorySessionDAO.class);
- private static final String RANDOM_NUM_GENERATOR_ALGORITHM_NAME = "SHA1PRNG";
- private Random randomNumberGenerator = null;
+ private ConcurrentMap<Serializable, Session> sessions;
public MemorySessionDAO() {
- setCacheManager(new HashtableCacheManager());
- }
-
- private Random getRandomNumberGenerator() {
- if (randomNumberGenerator == null) {
- if (log.isInfoEnabled()) {
- String msg = "On Java 1.4 platforms and below, there is no built-in UUID class (Java 1.5 and above " +
- "only) to use for Session ID generation - reverting to SecureRandom number generator. " +
- "Although this is probably sufficient for all but high user volume applications, if you " +
- "see ID collision, you will want to upgrade to JDK 1.5 or better as soon as possible, or " +
- "subclass the " + getClass().getName() + " class and override the #generateNewSessionId() " +
- "method to use a better algorithm.";
- log.info(msg);
- }
-
- try {
- randomNumberGenerator = java.security.SecureRandom.getInstance(RANDOM_NUM_GENERATOR_ALGORITHM_NAME);
- } catch (java.security.NoSuchAlgorithmException e) {
- randomNumberGenerator = new java.security.SecureRandom();
- }
- }
- return randomNumberGenerator;
- }
-
- protected Serializable generateNewSessionId() {
- if (JavaEnvironment.isAtLeastVersion15()) {
- return java.util.UUID.randomUUID().toString();
- } else {
- return Long.toString(getRandomNumberGenerator().nextLong());
- }
+ this.sessions = new ConcurrentHashMap<Serializable, Session>();
}
protected Serializable doCreate(Session session) {
- Serializable sessionId = generateNewSessionId();
+ Serializable sessionId = generateSessionId(session);
assignSessionId(session, sessionId);
+ storeSession(sessionId, session);
return sessionId;
}
- protected void assignSessionId(Session session, Serializable sessionId) {
- ((SimpleSession) session).setId(sessionId);
+ protected Session storeSession(Serializable id, Session session) {
+ if (id == null) {
+ throw new NullPointerException("id argument cannot be null.");
+ }
+ return sessions.putIfAbsent(id, session);
}
protected Session doReadSession(Serializable sessionId) {
- return null; //should never execute because this implementation relies on parent class to access cache, which
- //is where all sessions reside - it is the cache implementation that determines if the
- //cache is memory only or disk-persistent, etc.
+ return sessions.get(sessionId);
}
- protected void doUpdate(Session session) {
- //does nothing - parent class persists to cache.
+ public void update(Session session) throws UnknownSessionException {
+ storeSession(session.getId(), session);
}
- protected void doDelete(Session session) {
- //does nothing - parent class removes from cache.
+ public void delete(Session session) {
+ if (session == null) {
+ throw new NullPointerException("session argument cannot be null.");
+ }
+ Serializable id = session.getId();
+ if (id != null) {
+ sessions.remove(id);
+ }
}
+
+ public Collection<Session> getActiveSessions() {
+ Collection<Session> values = sessions.values();
+ if (CollectionUtils.isEmpty(values)) {
+ return Collections.emptySet();
+ } else {
+ return Collections.unmodifiableCollection(values);
+ }
+ }
+
}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.session.mgt.eis;
+
+import org.apache.shiro.session.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.Random;
+
+/**
+ * Generates session IDs by using a {@link Random} instance to generate random IDs. The default {@code Random}
+ * implementation is a {@link java.security.SecureRandom SecureRandom} with the {@code SHA1PRNG} algorithm.
+ *
+ * @since 1.0
+ */
+public class RandomSessionIdGenerator implements SessionIdGenerator {
+
+ private static final Logger log = LoggerFactory.getLogger(RandomSessionIdGenerator.class);
+
+ private static final String RANDOM_NUM_GENERATOR_ALGORITHM_NAME = "SHA1PRNG";
+ private Random random;
+
+ public RandomSessionIdGenerator() {
+ try {
+ this.random = java.security.SecureRandom.getInstance(RANDOM_NUM_GENERATOR_ALGORITHM_NAME);
+ } catch (java.security.NoSuchAlgorithmException e) {
+ log.debug("The SecureRandom SHA1PRNG algorithm is not available on the current platform. Using the " +
+ "platform's default SecureRandom algorithm.", e);
+ this.random = new java.security.SecureRandom();
+ }
+ }
+
+ public Random getRandom() {
+ return this.random;
+ }
+
+ public void setRandom(Random random) {
+ this.random = random;
+ }
+
+ /**
+ * Returns the String value of the configured {@link Random}'s {@link Random#nextLong() nextLong()} invocation.
+ *
+ * @param session the {@link Session} instance to which the ID will be applied.
+ * @return the String value of the configured {@link Random}'s {@link Random#nextLong()} invocation.
+ */
+ public Serializable generateId(Session session) {
+ //ignore the argument - just call the Random:
+ return Long.toString(getRandom().nextLong());
+ }
+}
Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionIdGenerator.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionIdGenerator.java?rev=927664&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionIdGenerator.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionIdGenerator.java Fri Mar 26 01:41:04 2010
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.session.mgt.eis;
+
+import org.apache.shiro.session.Session;
+
+import java.io.Serializable;
+
+/**
+ * Interface allowing pluggable session ID generation strategies to be used with various {@link SessionDAO}
+ * implementations.
+ * <h2>Usage</h2>
+ * SessionIdGenerators are usually only used when ID generation is separate from creating the
+ * Session record in the EIS data store. Some EIS data stores, such as relational databases, can generate the id
+ * at the same time the record is created, such as when using auto-generated primary keys. In these cases, a
+ * SessionIdGenerator does not need to be configured.
+ * <p/>
+ * However, if you want to customize how session IDs are created before persisting the Session record into the data
+ * store, you can implement this interface and typically inject it into an {@link AbstractSessionDAO} instance.
+ *
+ * @see org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator JavaUuidSessionIdGenerator
+ * @see org.apache.shiro.session.mgt.eis.RandomSessionIdGenerator RandomSessionIdGenerator
+ * @since 1.0
+ */
+public interface SessionIdGenerator {
+
+ /**
+ * Generates a new ID to be applied to the specified {@code Session} instance.
+ *
+ * @param session the {@link Session} instance to which the ID will be applied.
+ * @return the id to assign to the specified {@link Session} instance before adding a record to the EIS data store.
+ */
+ Serializable generateId(Session session);
+
+}
Modified: incubator/shiro/trunk/samples/spring-client/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/spring-client/pom.xml?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/spring-client/pom.xml (original)
+++ incubator/shiro/trunk/samples/spring-client/pom.xml Fri Mar 26 01:41:04 2010
@@ -1,153 +1,154 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ 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.
- -->
+ ~ 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.
+ -->
<!--suppress osmorcNonOsgiMavenDependency -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <parent>
- <groupId>org.apache.shiro.samples</groupId>
- <artifactId>shiro-samples</artifactId>
- <version>1.0-incubating-SNAPSHOT</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <artifactId>samples-spring-client</artifactId>
- <name>Apache Shiro :: Samples :: Spring Client</name>
- <description>A webstart application used to demonstrate Apache Shiro session and security management.</description>
- <packaging>jar</packaging>
-
- <properties>
- <shiro.session.id>${sessionId}</shiro.session.id>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-core</artifactId>
- <exclusions>
- <exclusion>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>2.5.6</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>2.5.6</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>2.5.6</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.5.6</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.5.6</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.5.6</version>
- <scope>compile</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo.webstart</groupId>
- <artifactId>webstart-maven-plugin</artifactId>
- <version>1.0-alpha-2</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>jnlp-inline</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <!-- JNLP generation -->
- <jnlp>
- <!-- default values -->
- <!--inputTemplateResourcePath>${project.basedir}</inputTemplateResourcePath-->
- <!--inputTemplate>src/main/jnlp/template.vm</inputTemplate--> <!-- relative to inputTemplateResourcePath -->
- <outputFile>shiro.jnlp.jsp</outputFile> <!-- defaults to launch.jnlp -->
-
- <mainClass>org.apache.shiro.samples.spring.ui.WebStartDriver</mainClass>
- </jnlp>
-
-
- <sign>
- <keystore>jsecurity-sample.jks</keystore>
- <storepass>jsecurity</storepass>
- <alias>jsecurity</alias>
- <verify>false</verify>
- </sign>
-
- <!-- BUILDING PROCESS -->
- <pack200>true</pack200>
- <verbose>false</verbose>
-
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <parent>
+ <groupId>org.apache.shiro.samples</groupId>
+ <artifactId>shiro-samples</artifactId>
+ <version>1.0-incubating-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>samples-spring-client</artifactId>
+ <name>Apache Shiro :: Samples :: Spring Client</name>
+ <description>A webstart application used to demonstrate Apache Shiro session and security management.</description>
+ <packaging>jar</packaging>
+
+ <properties>
+ <shiro.session.id>${sessionId}</shiro.session.id>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-core</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>2.5.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>2.5.6</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>2.5.6</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.5.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.5.6</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo.webstart</groupId>
+ <artifactId>webstart-maven-plugin</artifactId>
+ <version>1.0-alpha-2</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>jnlp-inline</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <!-- JNLP generation -->
+ <jnlp>
+ <!-- default values -->
+ <!--inputTemplateResourcePath>${project.basedir}</inputTemplateResourcePath-->
+ <!--inputTemplate>src/main/jnlp/template.vm</inputTemplate--> <!-- relative to inputTemplateResourcePath -->
+ <outputFile>shiro.jnlp.jsp</outputFile>
+ <!-- defaults to launch.jnlp -->
+
+ <mainClass>org.apache.shiro.samples.spring.ui.WebStartDriver</mainClass>
+ </jnlp>
+
+
+ <sign>
+ <keystore>jsecurity-sample.jks</keystore>
+ <storepass>jsecurity</storepass>
+ <alias>jsecurity</alias>
+ <verify>false</verify>
+ </sign>
+
+ <!-- BUILDING PROCESS -->
+ <pack200>true</pack200>
+ <verbose>false</verbose>
+
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
Modified: incubator/shiro/trunk/samples/spring/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/spring/pom.xml?rev=927664&r1=927663&r2=927664&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/spring/pom.xml (original)
+++ incubator/shiro/trunk/samples/spring/pom.xml Fri Mar 26 01:41:04 2010
@@ -1,172 +1,170 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ 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.
- -->
+ ~ 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.
+ -->
<!--suppress osmorcNonOsgiMavenDependency -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <parent>
- <groupId>org.apache.shiro.samples</groupId>
- <artifactId>shiro-samples</artifactId>
- <version>1.0-incubating-SNAPSHOT</version>
- </parent>
+ <parent>
+ <groupId>org.apache.shiro.samples</groupId>
+ <artifactId>shiro-samples</artifactId>
+ <version>1.0-incubating-SNAPSHOT</version>
+ </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>samples-spring</artifactId>
- <name>Apache Shiro :: Samples :: Spring</name>
- <packaging>war</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>samples-spring</artifactId>
+ <name>Apache Shiro :: Samples :: Spring</name>
+ <packaging>war</packaging>
- <build>
- <plugins>
- <plugin>
- <!-- Note that you need to run mvn jetty:run-exploded to test the webstart application -->
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>maven-jetty-plugin</artifactId>
- <version>${jetty.version}</version>
- <configuration>
- <contextPath>/shiro</contextPath>
- <connectors>
- <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
- <port>9080</port>
- <maxIdleTime>60000</maxIdleTime>
- </connector>
- </connectors>
- <requestLog implementation="org.mortbay.jetty.NCSARequestLog">
- <filename>./target/yyyy_mm_dd.request.log</filename>
- <retainDays>90</retainDays>
- <append>true</append>
- <extended>false</extended>
- <logTimeZone>GMT</logTimeZone>
- </requestLog>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>hsqldb</groupId>
- <artifactId>hsqldb</artifactId>
- <version>${hsqldb.version}</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>dependency-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.shiro.samples</groupId>
- <artifactId>samples-spring-client</artifactId>
- <version>${project.version}</version>
- <type>zip</type>
- </artifactItem>
- </artifactItems>
- <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>replace-jnlp-file</id>
- <phase>process-resources</phase>
- <configuration>
- <tasks>
- <!-- move would be more appropriate but it would fail on repetitive executions of jetty:run for example,
- leaving the original in place doesn't hurt -->
- <copy
- file="${project.build.directory}/${project.build.finalName}/shiro.jnlp.jsp"
- todir="${project.build.directory}/${project.build.finalName}/WEB-INF/resources"
- />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- Note that you need to run mvn jetty:run-exploded to test the webstart application -->
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>${jetty.version}</version>
+ <configuration>
+ <contextPath>/shiro</contextPath>
+ <connectors>
+ <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+ <port>9080</port>
+ <maxIdleTime>60000</maxIdleTime>
+ </connector>
+ </connectors>
+ <requestLog implementation="org.mortbay.jetty.NCSARequestLog">
+ <filename>./target/yyyy_mm_dd.request.log</filename>
+ <retainDays>90</retainDays>
+ <append>true</append>
+ <extended>false</extended>
+ <logTimeZone>GMT</logTimeZone>
+ </requestLog>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>${hsqldb.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>dependency-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.shiro.samples</groupId>
+ <artifactId>samples-spring-client</artifactId>
+ <version>${project.version}</version>
+ <type>zip</type>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>replace-jnlp-file</id>
+ <phase>process-resources</phase>
+ <configuration>
+ <tasks>
+ <!-- move would be more appropriate but it would fail on repetitive executions of
+ jetty:run for example, leaving the original in place doesn't hurt -->
+ <copy file="${project.build.directory}/${project.build.finalName}/shiro.jnlp.jsp"
+ todir="${project.build.directory}/${project.build.finalName}/WEB-INF/resources"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
- <dependencies>
- <dependency>
- <groupId>org.apache.shiro.samples</groupId>
- <artifactId>samples-spring-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-web</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- </dependency>
- <dependency>
- <groupId>hsqldb</groupId>
- <artifactId>hsqldb</artifactId>
- <version>${hsqldb.version}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
- <scope>runtime</scope>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shiro.samples</groupId>
+ <artifactId>samples-spring-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>${hsqldb.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
</project>