diff --git a/.gitignore b/.gitignore index 982a41f6..faea3c33 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ example-app/.gradle/* .rspec *.iml .idea/* +gradle* \ No newline at end of file diff --git a/build.gradle b/build.gradle index 2bd0db6a..e095fdb1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,13 @@ apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'signing' group = 'com.orangefunction' -version = '2.0.0' +version = '2.1.1' repositories { + mavenLocal() + maven { + url "https://maven.aliyun.com/nexus/content/groups/public" + } mavenCentral() } @@ -15,10 +17,9 @@ compileJava { } dependencies { - compile group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '7.0.27' + compile group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '8.5.31' compile group: 'redis.clients', name: 'jedis', version: '2.5.2' compile group: 'org.apache.commons', name: 'commons-pool2', version: '2.2' - //compile group: 'commons-codec', name: 'commons-codec', version: '1.9' testCompile group: 'junit', name: 'junit', version: '4.+' testCompile 'org.hamcrest:hamcrest-core:1.3' @@ -27,73 +28,3 @@ dependencies { testCompile group: 'org.apache.tomcat', name: 'tomcat-coyote', version: '7.0.27' } -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from 'build/docs/javadoc' -} - -task sourcesJar(type: Jar) { - from sourceSets.main.allSource - classifier = 'sources' -} - -artifacts { - archives jar - - archives javadocJar - archives sourcesJar -} - -signing { - sign configurations.archives -} - -uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - //repository(url: "https://oss.sonatype.org/content/repositories/snapshots") { - // authentication(userName: sonatypeUsername, password: sonatypePassword) - //} - - pom.project { - name 'tomcat-redis-session-manager' - packaging 'jar' - description 'Tomcat Redis Session Manager is a Tomcat extension to store sessions in Redis' - url 'https://github.com/jcoleman/tomcat-redis-session-manager' - - issueManagement { - url 'https://github.com:jcoleman/tomcat-redis-session-manager/issues' - system 'GitHub Issues' - } - - scm { - url 'https://github.com:jcoleman/tomcat-redis-session-manager' - connection 'scm:git:git://github.com/jcoleman/tomcat-redis-session-manager.git' - developerConnection 'scm:git:git@github.com:jcoleman/tomcat-redis-session-manager.git' - } - - licenses { - license { - name 'MIT' - url 'http://opensource.org/licenses/MIT' - distribution 'repo' - } - } - - developers { - developer { - id 'jcoleman' - name 'James Coleman' - email 'jtc331@gmail.com' - url 'https://github.com/jcoleman' - } - } - } - } - } -} diff --git a/example-app/build.gradle b/example-app/build.gradle index 6f6690cb..ee653bf7 100644 --- a/example-app/build.gradle +++ b/example-app/build.gradle @@ -4,6 +4,10 @@ apply plugin: 'war' version = '0.1' repositories { + mavenLocal() + maven { + url "https://maven.aliyun.com/nexus/content/groups/public" + } mavenCentral() } diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/JavaSerializer.java b/src/main/java/com/orangefunction/tomcat/redissessions/JavaSerializer.java index 4cfedff4..4c816547 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/JavaSerializer.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/JavaSerializer.java @@ -1,81 +1,89 @@ package com.orangefunction.tomcat.redissessions; import org.apache.catalina.util.CustomObjectInputStream; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; -import javax.servlet.http.HttpSession; - -import java.util.Enumeration; -import java.util.HashMap; import java.io.*; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Enumeration; +import java.util.HashMap; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - +/** + *

Title: Godfather1103's Github

+ *

Copyright: Copyright (c) 2020

+ *

Company: https://github.com/godfather1103

+ * + * @author 作者: Jack Chu E-mail: chuchuanbao@gmail.com + * 创建时间:2020-07-01 17:20 + * @version 1.0 + * @since 1.0 + */ public class JavaSerializer implements Serializer { - private ClassLoader loader; + private ClassLoader loader; - private final Log log = LogFactory.getLog(JavaSerializer.class); + private final Log log = LogFactory.getLog(JavaSerializer.class); - @Override - public void setClassLoader(ClassLoader loader) { - this.loader = loader; - } - - public byte[] attributesHashFrom(RedisSession session) throws IOException { - HashMap attributes = new HashMap(); - for (Enumeration enumerator = session.getAttributeNames(); enumerator.hasMoreElements();) { - String key = enumerator.nextElement(); - attributes.put(key, session.getAttribute(key)); + @Override + public void setClassLoader(ClassLoader loader) { + this.loader = loader; } - byte[] serialized = null; + @Override + public byte[] attributesHashFrom(RedisSession session) throws IOException { + HashMap attributes = new HashMap(); + for (Enumeration enumerator = session.getAttributeNames(); enumerator.hasMoreElements(); ) { + String key = enumerator.nextElement(); + attributes.put(key, session.getAttribute(key)); + } - try ( - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(bos)); - ) { - oos.writeUnshared(attributes); - oos.flush(); - serialized = bos.toByteArray(); - } + byte[] serialized = null; - MessageDigest digester = null; - try { - digester = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - log.error("Unable to get MessageDigest instance for MD5"); + try ( + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(bos)); + ) { + oos.writeUnshared(attributes); + oos.flush(); + serialized = bos.toByteArray(); + } + + MessageDigest digester = null; + try { + digester = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + log.error("Unable to get MessageDigest instance for MD5"); + } + return digester.digest(serialized); } - return digester.digest(serialized); - } - @Override - public byte[] serializeFrom(RedisSession session, SessionSerializationMetadata metadata) throws IOException { - byte[] serialized = null; + @Override + public byte[] serializeFrom(RedisSession session, SessionSerializationMetadata metadata) throws IOException { + byte[] serialized = null; - try ( - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(bos)); - ) { - oos.writeObject(metadata); - session.writeObjectData(oos); - oos.flush(); - serialized = bos.toByteArray(); - } + try ( + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(bos)); + ) { + oos.writeObject(metadata); + session.writeObjectData(oos); + oos.flush(); + serialized = bos.toByteArray(); + } - return serialized; - } + return serialized; + } - @Override - public void deserializeInto(byte[] data, RedisSession session, SessionSerializationMetadata metadata) throws IOException, ClassNotFoundException { - try( - BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(data)); - ObjectInputStream ois = new CustomObjectInputStream(bis, loader); - ) { - SessionSerializationMetadata serializedMetadata = (SessionSerializationMetadata)ois.readObject(); - metadata.copyFieldsFrom(serializedMetadata); - session.readObjectData(ois); + @Override + public void deserializeInto(byte[] data, RedisSession session, SessionSerializationMetadata metadata) throws IOException, ClassNotFoundException { + try ( + BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(data)); + ObjectInputStream ois = new CustomObjectInputStream(bis, loader); + ) { + SessionSerializationMetadata serializedMetadata = (SessionSerializationMetadata) ois.readObject(); + metadata.copyFieldsFrom(serializedMetadata); + session.readObjectData(ois); + } } - } } diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSession.java b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSession.java index 0fa742d8..8ec6bbbf 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSession.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSession.java @@ -1,14 +1,14 @@ package com.orangefunction.tomcat.redissessions; -import java.security.Principal; import org.apache.catalina.Manager; import org.apache.catalina.session.StandardSession; -import java.util.HashMap; -import java.io.IOException; - import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import java.io.IOException; +import java.security.Principal; +import java.util.HashMap; + public class RedisSession extends StandardSession { diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionHandlerValve.java b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionHandlerValve.java index 13da6765..31be292a 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionHandlerValve.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionHandlerValve.java @@ -1,16 +1,14 @@ package com.orangefunction.tomcat.redissessions; -import org.apache.catalina.Session; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; import javax.servlet.ServletException; import java.io.IOException; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - public class RedisSessionHandlerValve extends ValveBase { private final Log log = LogFactory.getLog(RedisSessionManager.class); diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionManager.java b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionManager.java index 2b58a261..a297d98c 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionManager.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/RedisSessionManager.java @@ -1,358 +1,403 @@ package com.orangefunction.tomcat.redissessions; -import org.apache.catalina.Lifecycle; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.LifecycleListener; -import org.apache.catalina.util.LifecycleSupport; -import org.apache.catalina.LifecycleState; -import org.apache.catalina.Loader; -import org.apache.catalina.Valve; -import org.apache.catalina.Session; +import org.apache.catalina.*; import org.apache.catalina.session.ManagerBase; - -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import org.apache.commons.pool2.impl.BaseObjectPoolConfig; - +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.ExceptionUtils; +import redis.clients.jedis.*; import redis.clients.util.Pool; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisSentinelPool; -import redis.clients.jedis.JedisPoolConfig; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.Protocol; +import java.beans.PropertyChangeSupport; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Set; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Iterator; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; +import java.util.*; public class RedisSessionManager extends ManagerBase implements Lifecycle { - enum SessionPersistPolicy { - DEFAULT, - SAVE_ON_CHANGE, - ALWAYS_SAVE_AFTER_REQUEST; + enum SessionPersistPolicy { + DEFAULT, + SAVE_ON_CHANGE, + ALWAYS_SAVE_AFTER_REQUEST; + + static SessionPersistPolicy fromName(String name) { + for (SessionPersistPolicy policy : SessionPersistPolicy.values()) { + if (policy.name().equalsIgnoreCase(name)) { + return policy; + } + } + throw new IllegalArgumentException("Invalid session persist policy [" + name + "]. Must be one of " + Arrays.asList(SessionPersistPolicy.values()) + "."); + } + } + + protected byte[] NULL_SESSION = "null".getBytes(); + + private final Log log = LogFactory.getLog(RedisSessionManager.class); + + protected String host = "localhost"; + protected int port = 6379; + protected int database = 0; + protected String password = null; + protected int timeout = Protocol.DEFAULT_TIMEOUT; + protected String sentinelMaster = null; + Set sentinelSet = null; + + protected Pool connectionPool; + protected JedisPoolConfig connectionPoolConfig = new JedisPoolConfig(); + + protected RedisSessionHandlerValve handlerValve; + protected ThreadLocal currentSession = new ThreadLocal<>(); + protected ThreadLocal currentSessionSerializationMetadata = new ThreadLocal<>(); + protected ThreadLocal currentSessionId = new ThreadLocal<>(); + protected ThreadLocal currentSessionIsPersisted = new ThreadLocal<>(); + protected Serializer serializer; + + protected static String name = "RedisSessionManager"; + + protected String serializationStrategyClass = "com.orangefunction.tomcat.redissessions.JavaSerializer"; + + protected EnumSet sessionPersistPoliciesSet = EnumSet.of(SessionPersistPolicy.DEFAULT); + + protected String maxInactiveInterval; + + public void setMaxInactiveInterval(String maxInactiveInterval) { + this.maxInactiveInterval = maxInactiveInterval; + } + + /** + * The lifecycle event support for this component. + */ + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } - static SessionPersistPolicy fromName(String name) { - for (SessionPersistPolicy policy : SessionPersistPolicy.values()) { - if (policy.name().equalsIgnoreCase(name)) { - return policy; + public int getDatabase() { + return database; + } + + public void setDatabase(int database) { + this.database = database; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setSerializationStrategyClass(String strategy) { + this.serializationStrategyClass = strategy; + } + + public String getSessionPersistPolicies() { + StringBuilder policies = new StringBuilder(); + for (Iterator iter = this.sessionPersistPoliciesSet.iterator(); iter.hasNext(); ) { + SessionPersistPolicy policy = iter.next(); + policies.append(policy.name()); + if (iter.hasNext()) { + policies.append(","); + } } - } - throw new IllegalArgumentException("Invalid session persist policy [" + name + "]. Must be one of " + Arrays.asList(SessionPersistPolicy.values())+ "."); + return policies.toString(); } - } - protected byte[] NULL_SESSION = "null".getBytes(); + public void setSessionPersistPolicies(String sessionPersistPolicies) { + String[] policyArray = sessionPersistPolicies.split(","); + EnumSet policySet = EnumSet.of(SessionPersistPolicy.DEFAULT); + for (String policyName : policyArray) { + SessionPersistPolicy policy = SessionPersistPolicy.fromName(policyName); + policySet.add(policy); + } + this.sessionPersistPoliciesSet = policySet; + } - private final Log log = LogFactory.getLog(RedisSessionManager.class); + public boolean getSaveOnChange() { + return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.SAVE_ON_CHANGE); + } - protected String host = "localhost"; - protected int port = 6379; - protected int database = 0; - protected String password = null; - protected int timeout = Protocol.DEFAULT_TIMEOUT; - protected String sentinelMaster = null; - Set sentinelSet = null; - - protected Pool connectionPool; - protected JedisPoolConfig connectionPoolConfig = new JedisPoolConfig(); + public boolean getAlwaysSaveAfterRequest() { + return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.ALWAYS_SAVE_AFTER_REQUEST); + } - protected RedisSessionHandlerValve handlerValve; - protected ThreadLocal currentSession = new ThreadLocal<>(); - protected ThreadLocal currentSessionSerializationMetadata = new ThreadLocal<>(); - protected ThreadLocal currentSessionId = new ThreadLocal<>(); - protected ThreadLocal currentSessionIsPersisted = new ThreadLocal<>(); - protected Serializer serializer; + public String getSentinels() { + StringBuilder sentinels = new StringBuilder(); + for (Iterator iter = this.sentinelSet.iterator(); iter.hasNext(); ) { + sentinels.append(iter.next()); + if (iter.hasNext()) { + sentinels.append(","); + } + } + return sentinels.toString(); + } - protected static String name = "RedisSessionManager"; + public void setSentinels(String sentinels) { + if (null == sentinels) { + sentinels = ""; + } - protected String serializationStrategyClass = "com.orangefunction.tomcat.redissessions.JavaSerializer"; + String[] sentinelArray = sentinels.split(","); + this.sentinelSet = new HashSet(Arrays.asList(sentinelArray)); + } - protected EnumSet sessionPersistPoliciesSet = EnumSet.of(SessionPersistPolicy.DEFAULT); + public Set getSentinelSet() { + return this.sentinelSet; + } - /** - * The lifecycle event support for this component. - */ - protected LifecycleSupport lifecycle = new LifecycleSupport(this); + public String getSentinelMaster() { + return this.sentinelMaster; + } - public String getHost() { - return host; - } + public void setSentinelMaster(String master) { + this.sentinelMaster = master; + } - public void setHost(String host) { - this.host = host; - } + @Override + public int getRejectedSessions() { + // Essentially do nothing. + return 0; + } - public int getPort() { - return port; - } + public void setRejectedSessions(int i) { + // Do nothing. + } - public void setPort(int port) { - this.port = port; - } + protected Jedis acquireConnection() { + Jedis jedis = connectionPool.getResource(); - public int getDatabase() { - return database; - } + if (getDatabase() != 0) { + jedis.select(getDatabase()); + } - public void setDatabase(int database) { - this.database = database; - } + return jedis; + } - public int getTimeout() { - return timeout; - } + protected void returnConnection(Jedis jedis, Boolean error) { + if (error) { + connectionPool.returnBrokenResource(jedis); + } else { + connectionPool.returnResource(jedis); + } + } - public void setTimeout(int timeout) { - this.timeout = timeout; - } + protected void returnConnection(Jedis jedis) { + returnConnection(jedis, false); + } - public String getPassword() { - return password; - } + @Override + public void load() throws ClassNotFoundException, IOException { - public void setPassword(String password) { - this.password = password; - } + } - public void setSerializationStrategyClass(String strategy) { - this.serializationStrategyClass = strategy; - } + @Override + public void unload() throws IOException { - public String getSessionPersistPolicies() { - StringBuilder policies = new StringBuilder(); - for (Iterator iter = this.sessionPersistPoliciesSet.iterator(); iter.hasNext();) { - SessionPersistPolicy policy = iter.next(); - policies.append(policy.name()); - if (iter.hasNext()) { - policies.append(","); - } } - return policies.toString(); - } - public void setSessionPersistPolicies(String sessionPersistPolicies) { - String[] policyArray = sessionPersistPolicies.split(","); - EnumSet policySet = EnumSet.of(SessionPersistPolicy.DEFAULT); - for (String policyName : policyArray) { - SessionPersistPolicy policy = SessionPersistPolicy.fromName(policyName); - policySet.add(policy); + protected final PropertyChangeSupport support = + new PropertyChangeSupport(this); + + private LifecycleListener listeners[] = new LifecycleListener[0]; + + private final Object listenersLock = new Object(); // Lock object for changes to listeners + + /** + * Add a lifecycle event listener to this component. + * + * @param listener The listener to add + */ + @Override + public void addLifecycleListener(LifecycleListener listener) { + synchronized (listenersLock) { + LifecycleListener results[] = + new LifecycleListener[listeners.length + 1]; + for (int i = 0; i < listeners.length; i++) { + results[i] = listeners[i]; + } + results[listeners.length] = listener; + listeners = results; + } + } + + /** + * Get the lifecycle listeners associated with this lifecycle. If this + * Lifecycle has no listeners registered, a zero-length array is returned. + */ + @Override + public LifecycleListener[] findLifecycleListeners() { + return listeners; + } + + + /** + * Remove a lifecycle event listener from this component. + * + * @param listener The listener to remove + */ + @Override + public void removeLifecycleListener(LifecycleListener listener) { + synchronized (listenersLock) { + int n = -1; + for (int i = 0; i < listeners.length; i++) { + if (listeners[i] == listener) { + n = i; + break; + } + } + if (n < 0) { + return; + } + LifecycleListener results[] = + new LifecycleListener[listeners.length - 1]; + int j = 0; + for (int i = 0; i < listeners.length; i++) { + if (i != n) { + results[j++] = listeners[i]; + } + } + listeners = results; + } } - this.sessionPersistPoliciesSet = policySet; - } - - public boolean getSaveOnChange() { - return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.SAVE_ON_CHANGE); - } - - public boolean getAlwaysSaveAfterRequest() { - return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.ALWAYS_SAVE_AFTER_REQUEST); - } - - public String getSentinels() { - StringBuilder sentinels = new StringBuilder(); - for (Iterator iter = this.sentinelSet.iterator(); iter.hasNext();) { - sentinels.append(iter.next()); - if (iter.hasNext()) { - sentinels.append(","); - } - } - return sentinels.toString(); - } - - public void setSentinels(String sentinels) { - if (null == sentinels) { - sentinels = ""; - } - - String[] sentinelArray = sentinels.split(","); - this.sentinelSet = new HashSet(Arrays.asList(sentinelArray)); - } - - public Set getSentinelSet() { - return this.sentinelSet; - } - - public String getSentinelMaster() { - return this.sentinelMaster; - } - - public void setSentinelMaster(String master) { - this.sentinelMaster = master; - } - - @Override - public int getRejectedSessions() { - // Essentially do nothing. - return 0; - } - - public void setRejectedSessions(int i) { - // Do nothing. - } - - protected Jedis acquireConnection() { - Jedis jedis = connectionPool.getResource(); - - if (getDatabase() != 0) { - jedis.select(getDatabase()); - } - - return jedis; - } - - protected void returnConnection(Jedis jedis, Boolean error) { - if (error) { - connectionPool.returnBrokenResource(jedis); - } else { - connectionPool.returnResource(jedis); - } - } - - protected void returnConnection(Jedis jedis) { - returnConnection(jedis, false); - } - - @Override - public void load() throws ClassNotFoundException, IOException { - - } - - @Override - public void unload() throws IOException { - - } - - /** - * Add a lifecycle event listener to this component. - * - * @param listener The listener to add - */ - @Override - public void addLifecycleListener(LifecycleListener listener) { - lifecycle.addLifecycleListener(listener); - } - - /** - * Get the lifecycle listeners associated with this lifecycle. If this - * Lifecycle has no listeners registered, a zero-length array is returned. - */ - @Override - public LifecycleListener[] findLifecycleListeners() { - return lifecycle.findLifecycleListeners(); - } - - - /** - * Remove a lifecycle event listener from this component. - * - * @param listener The listener to remove - */ - @Override - public void removeLifecycleListener(LifecycleListener listener) { - lifecycle.removeLifecycleListener(listener); - } - - /** - * Start this component and implement the requirements - * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. - * - * @exception LifecycleException if this component detects a fatal error - * that prevents this component from being used - */ - @Override - protected synchronized void startInternal() throws LifecycleException { - super.startInternal(); - setState(LifecycleState.STARTING); - - Boolean attachedToValve = false; - for (Valve valve : getContainer().getPipeline().getValves()) { - if (valve instanceof RedisSessionHandlerValve) { - this.handlerValve = (RedisSessionHandlerValve) valve; - this.handlerValve.setRedisSessionManager(this); - log.info("Attached to RedisSessionHandlerValve"); - attachedToValve = true; - break; - } - } - - if (!attachedToValve) { - String error = "Unable to attach to session handling valve; sessions cannot be saved after the request without the valve starting properly."; - log.fatal(error); - throw new LifecycleException(error); - } - - try { - initializeSerializer(); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { - log.fatal("Unable to load serializer", e); - throw new LifecycleException(e); - } - - log.info("Will expire sessions after " + getMaxInactiveInterval() + " seconds"); - - initializeDatabaseConnection(); - - setDistributable(true); - } - - - /** - * Stop this component and implement the requirements - * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. - * - * @exception LifecycleException if this component detects a fatal error - * that prevents this component from being used - */ - @Override - protected synchronized void stopInternal() throws LifecycleException { - if (log.isDebugEnabled()) { - log.debug("Stopping"); - } - - setState(LifecycleState.STOPPING); - - try { - connectionPool.destroy(); - } catch(Exception e) { - // Do nothing. - } - - // Require a new random number generator if we are restarted - super.stopInternal(); - } - - @Override - public Session createSession(String requestedSessionId) { - RedisSession session = null; - String sessionId = null; - String jvmRoute = getJvmRoute(); - - Boolean error = true; - Jedis jedis = null; - try { - jedis = acquireConnection(); - - // Ensure generation of a unique session identifier. - if (null != requestedSessionId) { - sessionId = sessionIdWithJvmRoute(requestedSessionId, jvmRoute); - if (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L) { - sessionId = null; - } - } else { - do { - sessionId = sessionIdWithJvmRoute(generateSessionId(), jvmRoute); - } while (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L); // 1 = key set; 0 = key already existed - } + /** + * Start this component and implement the requirements + * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. + * + * @throws LifecycleException if this component detects a fatal error + * that prevents this component from being used + */ + @Override + protected synchronized void startInternal() throws LifecycleException { + super.startInternal(); + + setState(LifecycleState.STARTING); + + Boolean attachedToValve = false; + for (Valve valve : getContext().getPipeline().getValves()) { + if (valve instanceof RedisSessionHandlerValve) { + this.handlerValve = (RedisSessionHandlerValve) valve; + this.handlerValve.setRedisSessionManager(this); + log.info("Attached to RedisSessionHandlerValve"); + attachedToValve = true; + break; + } + } + + if (!attachedToValve) { + String error = "Unable to attach to session handling valve; sessions cannot be saved after the request without the valve starting properly."; + log.fatal(error); + throw new LifecycleException(error); + } + + try { + initializeSerializer(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + log.fatal("Unable to load serializer", e); + throw new LifecycleException(e); + } + + log.info("Will expire sessions after " + getMaxInactiveInterval() + " seconds"); + + initializeDatabaseConnection(); + getContext().setDistributable(true); + } + + + @Override + public void expireSession(String sessionId) { + try { + Session session = findSession(sessionId); + if (session != null) { + session.expire(); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + /** + * Stop this component and implement the requirements + * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. + * + * @throws LifecycleException if this component detects a fatal error + * that prevents this component from being used + */ + @Override + protected synchronized void stopInternal() throws LifecycleException { + if (log.isDebugEnabled()) { + log.debug("Stopping"); + } + + setState(LifecycleState.STOPPING); + // Expire all active sessions + Session sessions[] = findSessions(); + for (int i = 0; i < sessions.length; i++) { + Session session = sessions[i]; + try { + if (session.isValid()) { + session.expire(); + } + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + } finally { + // Measure against memory leaking if references to the session + // object are kept in a shared field somewhere + session.recycle(); + } + } + try { + connectionPool.destroy(); + } catch (Exception e) { + // Do nothing. + } + // Require a new random number generator if we are restarted + super.stopInternal(); + } + + @Override + public Session createSession(String requestedSessionId) { + RedisSession session = null; + String sessionId = null; + String jvmRoute = getJvmRoute(); + + Boolean error = true; + Jedis jedis = null; + try { + jedis = acquireConnection(); + + // Ensure generation of a unique session identifier. + if (null != requestedSessionId) { + sessionId = sessionIdWithJvmRoute(requestedSessionId, jvmRoute); + if (jedis.hsetnx(getClassName().getBytes(), sessionId.getBytes(), NULL_SESSION) == 0L) { + sessionId = null; + } + } else { + do { + sessionId = sessionIdWithJvmRoute(generateSessionId(), jvmRoute); + } while (jedis.hsetnx(getClassName().getBytes(), sessionId.getBytes(), NULL_SESSION) == 0L); // 1 = key set; 0 = key already existed + } /* Even though the key is set in Redis, we are not going to flag the current thread as having had the session persisted since @@ -360,526 +405,555 @@ public Session createSession(String requestedSessionId) { This ensures that the save(session) at the end of the request will serialize the session into Redis with 'set' instead of 'setnx'. */ - error = false; + error = false; + + if (null != sessionId) { + session = (RedisSession) super.createSession(sessionId); + session.setNew(true); + session.setValid(true); + session.setCreationTime(System.currentTimeMillis()); + session.setMaxInactiveInterval(getMaxInactiveInterval()); + session.setId(sessionId); + session.tellNew(); + } + + currentSession.set(session); + currentSessionId.set(sessionId); + currentSessionIsPersisted.set(false); + currentSessionSerializationMetadata.set(new SessionSerializationMetadata()); + + if (null != session) { + try { + error = saveInternal(jedis, session, true); + sessions.put(sessionId, session); + } catch (IOException ex) { + log.error("Error saving newly created session: " + ex.getMessage()); + currentSession.set(null); + currentSessionId.set(null); + session = null; + } + } + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } + } - if (null != sessionId) { - session = (RedisSession)createEmptySession(); - session.setNew(true); - session.setValid(true); - session.setCreationTime(System.currentTimeMillis()); - session.setMaxInactiveInterval(getMaxInactiveInterval()); - session.setId(sessionId); - session.tellNew(); - } + return session; + } - currentSession.set(session); - currentSessionId.set(sessionId); - currentSessionIsPersisted.set(false); - currentSessionSerializationMetadata.set(new SessionSerializationMetadata()); + private String sessionIdWithJvmRoute(String sessionId, String jvmRoute) { + if (jvmRoute != null) { + String jvmRoutePrefix = '.' + jvmRoute; + return sessionId.endsWith(jvmRoutePrefix) ? sessionId : sessionId + jvmRoutePrefix; + } + return sessionId; + } - if (null != session) { + @Override + public Session createEmptySession() { + return new RedisSession(this); + } + + @Override + public void add(Session session) { + super.add(session); try { - error = saveInternal(jedis, session, true); + save(session); } catch (IOException ex) { - log.error("Error saving newly created session: " + ex.getMessage()); - currentSession.set(null); - currentSessionId.set(null); - session = null; - } - } - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - - return session; - } - - private String sessionIdWithJvmRoute(String sessionId, String jvmRoute) { - if (jvmRoute != null) { - String jvmRoutePrefix = '.' + jvmRoute; - return sessionId.endsWith(jvmRoutePrefix) ? sessionId : sessionId + jvmRoutePrefix; - } - return sessionId; - } - - @Override - public Session createEmptySession() { - return new RedisSession(this); - } - - @Override - public void add(Session session) { - try { - save(session); - } catch (IOException ex) { - log.warn("Unable to add to session manager store: " + ex.getMessage()); - throw new RuntimeException("Unable to add to session manager store.", ex); - } - } - - @Override - public Session findSession(String id) throws IOException { - RedisSession session = null; - - if (null == id) { - currentSessionIsPersisted.set(false); - currentSession.set(null); - currentSessionSerializationMetadata.set(null); - currentSessionId.set(null); - } else if (id.equals(currentSessionId.get())) { - session = currentSession.get(); - } else { - byte[] data = loadSessionDataFromRedis(id); - if (data != null) { - DeserializedSessionContainer container = sessionFromSerializedData(id, data); - session = container.session; - currentSession.set(session); - currentSessionSerializationMetadata.set(container.metadata); - currentSessionIsPersisted.set(true); - currentSessionId.set(id); - } else { - currentSessionIsPersisted.set(false); - currentSession.set(null); - currentSessionSerializationMetadata.set(null); - currentSessionId.set(null); - } - } - - return session; - } - - public void clear() { - Jedis jedis = null; - Boolean error = true; - try { - jedis = acquireConnection(); - jedis.flushDB(); - error = false; - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - } - - public int getSize() throws IOException { - Jedis jedis = null; - Boolean error = true; - try { - jedis = acquireConnection(); - int size = jedis.dbSize().intValue(); - error = false; - return size; - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - } - - public String[] keys() throws IOException { - Jedis jedis = null; - Boolean error = true; - try { - jedis = acquireConnection(); - Set keySet = jedis.keys("*"); - error = false; - return keySet.toArray(new String[keySet.size()]); - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - } - - public byte[] loadSessionDataFromRedis(String id) throws IOException { - Jedis jedis = null; - Boolean error = true; - - try { - log.trace("Attempting to load session " + id + " from Redis"); - - jedis = acquireConnection(); - byte[] data = jedis.get(id.getBytes()); - error = false; - - if (data == null) { - log.trace("Session " + id + " not found in Redis"); - } - - return data; - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - } - - public DeserializedSessionContainer sessionFromSerializedData(String id, byte[] data) throws IOException { - log.trace("Deserializing session " + id + " from Redis"); - - if (Arrays.equals(NULL_SESSION, data)) { - log.error("Encountered serialized session " + id + " with data equal to NULL_SESSION. This is a bug."); - throw new IOException("Serialized session data was equal to NULL_SESSION"); - } - - RedisSession session = null; - SessionSerializationMetadata metadata = new SessionSerializationMetadata(); - - try { - session = (RedisSession)createEmptySession(); - - serializer.deserializeInto(data, session, metadata); - - session.setId(id); - session.setNew(false); - session.setMaxInactiveInterval(getMaxInactiveInterval()); - session.access(); - session.setValid(true); - session.resetDirtyTracking(); - - if (log.isTraceEnabled()) { - log.trace("Session Contents [" + id + "]:"); - Enumeration en = session.getAttributeNames(); - while(en.hasMoreElements()) { - log.trace(" " + en.nextElement()); - } - } - } catch (ClassNotFoundException ex) { - log.fatal("Unable to deserialize into session", ex); - throw new IOException("Unable to deserialize into session", ex); - } - - return new DeserializedSessionContainer(session, metadata); - } - - public void save(Session session) throws IOException { - save(session, false); - } - - public void save(Session session, boolean forceSave) throws IOException { - Jedis jedis = null; - Boolean error = true; - - try { - jedis = acquireConnection(); - error = saveInternal(jedis, session, forceSave); - } catch (IOException e) { - throw e; - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } - } - } + log.warn("Unable to add to session manager store: " + ex.getMessage()); + throw new RuntimeException("Unable to add to session manager store.", ex); + } + } - protected boolean saveInternal(Jedis jedis, Session session, boolean forceSave) throws IOException { - Boolean error = true; + @Override + public Session findSession(String id) throws IOException { + RedisSession session = null; + + if (null == id) { + currentSessionIsPersisted.set(false); + currentSession.set(null); + currentSessionSerializationMetadata.set(null); + currentSessionId.set(null); + } else if (id.equals(currentSessionId.get())) { + session = currentSession.get(); + } else { + byte[] data = loadSessionDataFromRedis(id); + if (data != null) { + DeserializedSessionContainer container = sessionFromSerializedData(id, data); + session = container.session; + currentSession.set(session); + currentSessionSerializationMetadata.set(container.metadata); + currentSessionIsPersisted.set(true); + currentSessionId.set(id); + } else { + currentSessionIsPersisted.set(false); + currentSession.set(null); + currentSessionSerializationMetadata.set(null); + currentSessionId.set(null); + } + } - try { - log.trace("Saving session " + session + " into Redis"); - - RedisSession redisSession = (RedisSession)session; + return session; + } - if (log.isTraceEnabled()) { - log.trace("Session Contents [" + redisSession.getId() + "]:"); - Enumeration en = redisSession.getAttributeNames(); - while(en.hasMoreElements()) { - log.trace(" " + en.nextElement()); + public void clear() { + Jedis jedis = null; + Boolean error = true; + try { + jedis = acquireConnection(); + jedis.flushDB(); + error = false; + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } } - } + } + + public int getSize() throws IOException { + Jedis jedis = null; + Boolean error = true; + try { + jedis = acquireConnection(); + int size = jedis.dbSize().intValue(); + error = false; + return size; + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } + } + } - byte[] binaryId = redisSession.getId().getBytes(); +// @Override +// public Session[] findSessions() { +// Jedis jedis = null; +// Boolean error = true; +// List sessions = new ArrayList<>(); +// try { +// log.trace("Attempting to load sessions from Redis"); +// jedis = acquireConnection(); +// Map datas = jedis.hgetAll(getClassName().getBytes()); +// Set keys = datas.keySet(); +// for (byte[] key : keys) { +// byte[] data = datas.get(key); +// if (data != null) { +// String id = new String(key); +// try { +// DeserializedSessionContainer container = sessionFromSerializedData(id, data); +// RedisSession session = container.session; +// if (session != null) { +// sessions.add(session); +// } +// } catch (IOException ex) { +// log.fatal("Session " + id + " Unable to deserialize into session", ex); +// } +// } +// } +// error = false; +// } finally { +// if (jedis != null) { +// returnConnection(jedis, error); +// } +// } +// return sessions.toArray(new Session[0]); +// } + + public byte[] loadSessionDataFromRedis(String id) throws IOException { + Jedis jedis = null; + Boolean error = true; - Boolean isCurrentSessionPersisted; - SessionSerializationMetadata sessionSerializationMetadata = currentSessionSerializationMetadata.get(); - byte[] originalSessionAttributesHash = sessionSerializationMetadata.getSessionAttributesHash(); - byte[] sessionAttributesHash = null; - if ( - forceSave - || redisSession.isDirty() - || null == (isCurrentSessionPersisted = this.currentSessionIsPersisted.get()) - || !isCurrentSessionPersisted - || !Arrays.equals(originalSessionAttributesHash, (sessionAttributesHash = serializer.attributesHashFrom(redisSession))) - ) { + try { + log.trace("Attempting to load session " + id + " from Redis"); - log.trace("Save was determined to be necessary"); + jedis = acquireConnection(); + byte[] data = jedis.hget(getClassName().getBytes(), id.getBytes()); + error = false; - if (null == sessionAttributesHash) { - sessionAttributesHash = serializer.attributesHashFrom(redisSession); + if (data == null) { + log.trace("Session " + id + " not found in Redis"); + } + + return data; + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } } + } - SessionSerializationMetadata updatedSerializationMetadata = new SessionSerializationMetadata(); - updatedSerializationMetadata.setSessionAttributesHash(sessionAttributesHash); + public int getMaxInactiveInterval() { + if (maxInactiveInterval == null || maxInactiveInterval.trim().length() == 0) { + return getContext().getSessionTimeout() * 60; + } else { + return Integer.valueOf(maxInactiveInterval) * 60; + } + } - jedis.set(binaryId, serializer.serializeFrom(redisSession, updatedSerializationMetadata)); + public DeserializedSessionContainer sessionFromSerializedData(String id, byte[] data) throws IOException { + log.trace("Deserializing session " + id + " from Redis"); - redisSession.resetDirtyTracking(); - currentSessionSerializationMetadata.set(updatedSerializationMetadata); - currentSessionIsPersisted.set(true); - } else { - log.trace("Save was determined to be unnecessary"); - } + if (Arrays.equals(NULL_SESSION, data)) { + log.error("Encountered serialized session " + id + " with data equal to NULL_SESSION. This is a bug."); + throw new IOException("Serialized session data was equal to NULL_SESSION"); + } - log.trace("Setting expire timeout on session [" + redisSession.getId() + "] to " + getMaxInactiveInterval()); - jedis.expire(binaryId, getMaxInactiveInterval()); + RedisSession session = null; + SessionSerializationMetadata metadata = new SessionSerializationMetadata(); - error = false; + try { + session = (RedisSession) createEmptySession(); + + serializer.deserializeInto(data, session, metadata); + + session.setId(id); + session.setNew(false); + session.access(); + session.setValid(true); + session.resetDirtyTracking(); + + if (log.isTraceEnabled()) { + log.trace("Session Contents [" + id + "]:"); + Enumeration en = session.getAttributeNames(); + while (en.hasMoreElements()) { + log.trace(" " + en.nextElement()); + } + } + } catch (ClassNotFoundException ex) { + log.fatal("Unable to deserialize into session", ex); + throw new IOException("Unable to deserialize into session", ex); + } - return error; - } catch (IOException e) { - log.error(e.getMessage()); - - throw e; - } finally { - return error; - } - } + return new DeserializedSessionContainer(session, metadata); + } - @Override - public void remove(Session session) { - remove(session, false); - } + public void save(Session session) throws IOException { + save(session, false); + } - @Override - public void remove(Session session, boolean update) { - Jedis jedis = null; - Boolean error = true; + public void save(Session session, boolean forceSave) throws IOException { + Jedis jedis = null; + Boolean error = true; - log.trace("Removing session ID : " + session.getId()); + try { + jedis = acquireConnection(); + error = saveInternal(jedis, session, forceSave); + } catch (IOException e) { + throw e; + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } + } + } + + protected boolean saveInternal(Jedis jedis, Session session, boolean forceSave) throws IOException { + Boolean error = true; - try { - jedis = acquireConnection(); - jedis.del(session.getId()); - error = false; - } finally { - if (jedis != null) { - returnConnection(jedis, error); - } + try { + log.trace("Saving session " + session + " into Redis"); + + RedisSession redisSession = (RedisSession) session; + + if (log.isTraceEnabled()) { + log.trace("Session Contents [" + redisSession.getId() + "]:"); + Enumeration en = redisSession.getAttributeNames(); + while (en.hasMoreElements()) { + log.trace(" " + en.nextElement()); + } + } + + byte[] binaryId = redisSession.getId().getBytes(); + + Boolean isCurrentSessionPersisted; + SessionSerializationMetadata sessionSerializationMetadata = currentSessionSerializationMetadata.get(); + byte[] originalSessionAttributesHash = sessionSerializationMetadata.getSessionAttributesHash(); + byte[] sessionAttributesHash = null; + if ( + forceSave + || redisSession.isDirty() + || null == (isCurrentSessionPersisted = this.currentSessionIsPersisted.get()) + || !isCurrentSessionPersisted + || !Arrays.equals(originalSessionAttributesHash, (sessionAttributesHash = serializer.attributesHashFrom(redisSession))) + ) { + + log.trace("Save was determined to be necessary"); + + if (null == sessionAttributesHash) { + sessionAttributesHash = serializer.attributesHashFrom(redisSession); + } + + SessionSerializationMetadata updatedSerializationMetadata = new SessionSerializationMetadata(); + updatedSerializationMetadata.setSessionAttributesHash(sessionAttributesHash); + + jedis.hset(getClassName().getBytes(), binaryId, serializer.serializeFrom(redisSession, updatedSerializationMetadata)); + + redisSession.resetDirtyTracking(); + currentSessionSerializationMetadata.set(updatedSerializationMetadata); + currentSessionIsPersisted.set(true); + } else { + log.trace("Save was determined to be unnecessary"); + } + error = false; + return error; + } catch (IOException e) { + log.error(e.getMessage()); + + throw e; + } finally { + return error; + } } - } - - public void afterRequest() { - RedisSession redisSession = currentSession.get(); - if (redisSession != null) { - try { - if (redisSession.isValid()) { - log.trace("Request with session completed, saving session " + redisSession.getId()); - save(redisSession, getAlwaysSaveAfterRequest()); - } else { - log.trace("HTTP Session has been invalidated, removing :" + redisSession.getId()); - remove(redisSession); - } - } catch (Exception e) { - log.error("Error storing/removing session", e); - } finally { - currentSession.remove(); - currentSessionId.remove(); - currentSessionIsPersisted.remove(); - log.trace("Session removed from ThreadLocal :" + redisSession.getIdInternal()); - } - } - } - - @Override - public void processExpires() { - // We are going to use Redis's ability to expire keys for session expiration. - - // Do nothing. - } - - private void initializeDatabaseConnection() throws LifecycleException { - try { - if (getSentinelMaster() != null) { - Set sentinelSet = getSentinelSet(); - if (sentinelSet != null && sentinelSet.size() > 0) { - connectionPool = new JedisSentinelPool(getSentinelMaster(), sentinelSet, this.connectionPoolConfig, getTimeout(), getPassword()); - } else { - throw new LifecycleException("Error configuring Redis Sentinel connection pool: expected both `sentinelMaster` and `sentiels` to be configured"); + + @Override + public void remove(Session session) { + remove(session, false); + } + + @Override + public void remove(Session session, boolean update) { + super.remove(session, update); + Jedis jedis = null; + Boolean error = true; + + log.trace("Removing session ID : " + session.getId()); + currentSessionSerializationMetadata.remove(); + try { + jedis = acquireConnection(); + jedis.hdel(getClassName(), session.getId()); + error = false; + } finally { + if (jedis != null) { + returnConnection(jedis, error); + } + } + } + + public void afterRequest() { + RedisSession redisSession = currentSession.get(); + if (redisSession != null) { + try { + if (redisSession.isValid()) { + log.trace("Request with session completed, saving session " + redisSession.getId()); + save(redisSession, getAlwaysSaveAfterRequest()); + } else { + log.trace("HTTP Session has been invalidated, removing :" + redisSession.getId()); + remove(redisSession); + } + } catch (Exception e) { + log.error("Error storing/removing session", e); + } finally { + currentSession.remove(); + currentSessionId.remove(); + currentSessionIsPersisted.remove(); + log.trace("Session removed from ThreadLocal :" + redisSession.getIdInternal()); + } + } + } + + @Override + public void processExpires() { + // We are going to use Redis's ability to expire keys for session expiration. + super.processExpires(); + // Do nothing. + } + + private void initializeDatabaseConnection() throws LifecycleException { + try { + if (getSentinelMaster() != null) { + Set sentinelSet = getSentinelSet(); + if (sentinelSet != null && sentinelSet.size() > 0) { + connectionPool = new JedisSentinelPool(getSentinelMaster(), sentinelSet, this.connectionPoolConfig, getTimeout(), getPassword()); + } else { + throw new LifecycleException("Error configuring Redis Sentinel connection pool: expected both `sentinelMaster` and `sentiels` to be configured"); + } + } else { + connectionPool = new JedisPool(this.connectionPoolConfig, getHost(), getPort(), getTimeout(), getPassword()); + } + } catch (Exception e) { + log.error("Error connecting to Redis", e); + throw new LifecycleException("Error connecting to Redis", e); + } + } + + private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException { + log.info("Attempting to use serializer :" + serializationStrategyClass); + serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance(); + + Loader loader = null; + + if (getContext() != null) { + loader = getContext().getLoader(); + } + + ClassLoader classLoader = null; + + if (loader != null) { + classLoader = loader.getClassLoader(); } - } else { - connectionPool = new JedisPool(this.connectionPoolConfig, getHost(), getPort(), getTimeout(), getPassword()); - } - } catch (Exception e) { - e.printStackTrace(); - throw new LifecycleException("Error connecting to Redis", e); + serializer.setClassLoader(classLoader); } - } - private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException { - log.info("Attempting to use serializer :" + serializationStrategyClass); - serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance(); - Loader loader = null; + // Connection Pool Config Accessors - if (getContainer() != null) { - loader = getContainer().getLoader(); + // - from org.apache.commons.pool2.impl.GenericObjectPoolConfig + + public int getConnectionPoolMaxTotal() { + return this.connectionPoolConfig.getMaxTotal(); } - ClassLoader classLoader = null; + public void setConnectionPoolMaxTotal(int connectionPoolMaxTotal) { + this.connectionPoolConfig.setMaxTotal(connectionPoolMaxTotal); + } - if (loader != null) { - classLoader = loader.getClassLoader(); + public int getConnectionPoolMaxIdle() { + return this.connectionPoolConfig.getMaxIdle(); } - serializer.setClassLoader(classLoader); - } + public void setConnectionPoolMaxIdle(int connectionPoolMaxIdle) { + this.connectionPoolConfig.setMaxIdle(connectionPoolMaxIdle); + } - // Connection Pool Config Accessors + public int getConnectionPoolMinIdle() { + return this.connectionPoolConfig.getMinIdle(); + } - // - from org.apache.commons.pool2.impl.GenericObjectPoolConfig + public void setConnectionPoolMinIdle(int connectionPoolMinIdle) { + this.connectionPoolConfig.setMinIdle(connectionPoolMinIdle); + } - public int getConnectionPoolMaxTotal() { - return this.connectionPoolConfig.getMaxTotal(); - } - public void setConnectionPoolMaxTotal(int connectionPoolMaxTotal) { - this.connectionPoolConfig.setMaxTotal(connectionPoolMaxTotal); - } + // - from org.apache.commons.pool2.impl.BaseObjectPoolConfig - public int getConnectionPoolMaxIdle() { - return this.connectionPoolConfig.getMaxIdle(); - } + public boolean getLifo() { + return this.connectionPoolConfig.getLifo(); + } - public void setConnectionPoolMaxIdle(int connectionPoolMaxIdle) { - this.connectionPoolConfig.setMaxIdle(connectionPoolMaxIdle); - } + public void setLifo(boolean lifo) { + this.connectionPoolConfig.setLifo(lifo); + } - public int getConnectionPoolMinIdle() { - return this.connectionPoolConfig.getMinIdle(); - } + public long getMaxWaitMillis() { + return this.connectionPoolConfig.getMaxWaitMillis(); + } - public void setConnectionPoolMinIdle(int connectionPoolMinIdle) { - this.connectionPoolConfig.setMinIdle(connectionPoolMinIdle); - } + public void setMaxWaitMillis(long maxWaitMillis) { + this.connectionPoolConfig.setMaxWaitMillis(maxWaitMillis); + } + public long getMinEvictableIdleTimeMillis() { + return this.connectionPoolConfig.getMinEvictableIdleTimeMillis(); + } - // - from org.apache.commons.pool2.impl.BaseObjectPoolConfig + public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { + this.connectionPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + } - public boolean getLifo() { - return this.connectionPoolConfig.getLifo(); - } - public void setLifo(boolean lifo) { - this.connectionPoolConfig.setLifo(lifo); - } - public long getMaxWaitMillis() { - return this.connectionPoolConfig.getMaxWaitMillis(); - } + public long getSoftMinEvictableIdleTimeMillis() { + return this.connectionPoolConfig.getSoftMinEvictableIdleTimeMillis(); + } - public void setMaxWaitMillis(long maxWaitMillis) { - this.connectionPoolConfig.setMaxWaitMillis(maxWaitMillis); - } + public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) { + this.connectionPoolConfig.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); + } - public long getMinEvictableIdleTimeMillis() { - return this.connectionPoolConfig.getMinEvictableIdleTimeMillis(); - } + public int getNumTestsPerEvictionRun() { + return this.connectionPoolConfig.getNumTestsPerEvictionRun(); + } - public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { - this.connectionPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); - } + public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { + this.connectionPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun); + } - public long getSoftMinEvictableIdleTimeMillis() { - return this.connectionPoolConfig.getSoftMinEvictableIdleTimeMillis(); - } + public boolean getTestOnCreate() { + return this.connectionPoolConfig.getTestOnCreate(); + } - public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) { - this.connectionPoolConfig.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); - } + public void setTestOnCreate(boolean testOnCreate) { + this.connectionPoolConfig.setTestOnCreate(testOnCreate); + } - public int getNumTestsPerEvictionRun() { - return this.connectionPoolConfig.getNumTestsPerEvictionRun(); - } + public boolean getTestOnBorrow() { + return this.connectionPoolConfig.getTestOnBorrow(); + } - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { - this.connectionPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun); - } + public void setTestOnBorrow(boolean testOnBorrow) { + this.connectionPoolConfig.setTestOnBorrow(testOnBorrow); + } - public boolean getTestOnCreate() { - return this.connectionPoolConfig.getTestOnCreate(); - } + public boolean getTestOnReturn() { + return this.connectionPoolConfig.getTestOnReturn(); + } - public void setTestOnCreate(boolean testOnCreate) { - this.connectionPoolConfig.setTestOnCreate(testOnCreate); - } + public void setTestOnReturn(boolean testOnReturn) { + this.connectionPoolConfig.setTestOnReturn(testOnReturn); + } - public boolean getTestOnBorrow() { - return this.connectionPoolConfig.getTestOnBorrow(); - } + public boolean getTestWhileIdle() { + return this.connectionPoolConfig.getTestWhileIdle(); + } + + public void setTestWhileIdle(boolean testWhileIdle) { + this.connectionPoolConfig.setTestWhileIdle(testWhileIdle); + } + + public long getTimeBetweenEvictionRunsMillis() { + return this.connectionPoolConfig.getTimeBetweenEvictionRunsMillis(); + } + + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + this.connectionPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + } + + public String getEvictionPolicyClassName() { + return this.connectionPoolConfig.getEvictionPolicyClassName(); + } + + public void setEvictionPolicyClassName(String evictionPolicyClassName) { + this.connectionPoolConfig.setEvictionPolicyClassName(evictionPolicyClassName); + } + + public boolean getBlockWhenExhausted() { + return this.connectionPoolConfig.getBlockWhenExhausted(); + } + + public void setBlockWhenExhausted(boolean blockWhenExhausted) { + this.connectionPoolConfig.setBlockWhenExhausted(blockWhenExhausted); + } - public void setTestOnBorrow(boolean testOnBorrow) { - this.connectionPoolConfig.setTestOnBorrow(testOnBorrow); - } + public boolean getJmxEnabled() { + return this.connectionPoolConfig.getJmxEnabled(); + } + + public void setJmxEnabled(boolean jmxEnabled) { + this.connectionPoolConfig.setJmxEnabled(jmxEnabled); + } - public boolean getTestOnReturn() { - return this.connectionPoolConfig.getTestOnReturn(); - } + public String getJmxNameBase() { + return this.connectionPoolConfig.getJmxNameBase(); + } - public void setTestOnReturn(boolean testOnReturn) { - this.connectionPoolConfig.setTestOnReturn(testOnReturn); - } + public void setJmxNameBase(String jmxNameBase) { + this.connectionPoolConfig.setJmxNameBase(jmxNameBase); + } - public boolean getTestWhileIdle() { - return this.connectionPoolConfig.getTestWhileIdle(); - } + public String getJmxNamePrefix() { + return this.connectionPoolConfig.getJmxNamePrefix(); + } - public void setTestWhileIdle(boolean testWhileIdle) { - this.connectionPoolConfig.setTestWhileIdle(testWhileIdle); - } - - public long getTimeBetweenEvictionRunsMillis() { - return this.connectionPoolConfig.getTimeBetweenEvictionRunsMillis(); - } - - public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { - this.connectionPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - } - - public String getEvictionPolicyClassName() { - return this.connectionPoolConfig.getEvictionPolicyClassName(); - } - - public void setEvictionPolicyClassName(String evictionPolicyClassName) { - this.connectionPoolConfig.setEvictionPolicyClassName(evictionPolicyClassName); - } - - public boolean getBlockWhenExhausted() { - return this.connectionPoolConfig.getBlockWhenExhausted(); - } - - public void setBlockWhenExhausted(boolean blockWhenExhausted) { - this.connectionPoolConfig.setBlockWhenExhausted(blockWhenExhausted); - } - - public boolean getJmxEnabled() { - return this.connectionPoolConfig.getJmxEnabled(); - } - - public void setJmxEnabled(boolean jmxEnabled) { - this.connectionPoolConfig.setJmxEnabled(jmxEnabled); - } - public String getJmxNameBase() { - return this.connectionPoolConfig.getJmxNameBase(); - } - public void setJmxNameBase(String jmxNameBase) { - this.connectionPoolConfig.setJmxNameBase(jmxNameBase); - } - - public String getJmxNamePrefix() { - return this.connectionPoolConfig.getJmxNamePrefix(); - } - - public void setJmxNamePrefix(String jmxNamePrefix) { - this.connectionPoolConfig.setJmxNamePrefix(jmxNamePrefix); - } + public void setJmxNamePrefix(String jmxNamePrefix) { + this.connectionPoolConfig.setJmxNamePrefix(jmxNamePrefix); + } } class DeserializedSessionContainer { - public final RedisSession session; - public final SessionSerializationMetadata metadata; - public DeserializedSessionContainer(RedisSession session, SessionSerializationMetadata metadata) { - this.session = session; - this.metadata = metadata; - } + public final RedisSession session; + public final SessionSerializationMetadata metadata; + + public DeserializedSessionContainer(RedisSession session, SessionSerializationMetadata metadata) { + this.session = session; + this.metadata = metadata; + } } diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/Serializer.java b/src/main/java/com/orangefunction/tomcat/redissessions/Serializer.java index b6d1161a..d9da63a7 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/Serializer.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/Serializer.java @@ -1,12 +1,23 @@ package com.orangefunction.tomcat.redissessions; -import javax.servlet.http.HttpSession; import java.io.IOException; +/** + *

Title: Godfather1103's Github

+ *

Copyright: Copyright (c) 2020

+ *

Company: https://github.com/godfather1103

+ * + * @author 作者: Jack Chu E-mail: chuchuanbao@gmail.com + * 创建时间:2020-07-01 17:20 + * @version 1.0 + * @since 1.0 + */ public interface Serializer { - void setClassLoader(ClassLoader loader); + void setClassLoader(ClassLoader loader); - byte[] attributesHashFrom(RedisSession session) throws IOException; - byte[] serializeFrom(RedisSession session, SessionSerializationMetadata metadata) throws IOException; - void deserializeInto(byte[] data, RedisSession session, SessionSerializationMetadata metadata) throws IOException, ClassNotFoundException; + byte[] attributesHashFrom(RedisSession session) throws IOException; + + byte[] serializeFrom(RedisSession session, SessionSerializationMetadata metadata) throws IOException; + + void deserializeInto(byte[] data, RedisSession session, SessionSerializationMetadata metadata) throws IOException, ClassNotFoundException; } diff --git a/src/main/java/com/orangefunction/tomcat/redissessions/SessionSerializationMetadata.java b/src/main/java/com/orangefunction/tomcat/redissessions/SessionSerializationMetadata.java index 7d3d9276..e88c966b 100644 --- a/src/main/java/com/orangefunction/tomcat/redissessions/SessionSerializationMetadata.java +++ b/src/main/java/com/orangefunction/tomcat/redissessions/SessionSerializationMetadata.java @@ -1,6 +1,8 @@ package com.orangefunction.tomcat.redissessions; -import java.io.*; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; public class SessionSerializationMetadata implements Serializable {