diff --git a/README.adoc b/README.adoc index 02b7c67..c5f21c3 100644 --- a/README.adoc +++ b/README.adoc @@ -92,30 +92,12 @@ Add the following into your Tomcat `context.xml` (or the context block of the `s [source,xml] ---- - - - - - - - - - - - - - - - - - - - + + + + + + ---- Copy the following files into the `TOMCAT_BASE/lib` directory: diff --git a/pom.xml b/pom.xml index 247569a..9f67ea0 100644 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,7 @@ org.apache.tomcat tomcat-catalina - 9.0.54 + 9.0.64 provided @@ -206,13 +206,13 @@ redis.clients jedis - 3.6.3 + 4.2.3 provided org.springframework spring-test - 4.3.20.RELEASE + 4.3.30.RELEASE test @@ -230,7 +230,7 @@ com.hazelcast hazelcast - 5.0 + 5.1.2 diff --git a/src/main/java/HostName.java b/src/main/java/HostName.java new file mode 100644 index 0000000..486e47b --- /dev/null +++ b/src/main/java/HostName.java @@ -0,0 +1,7 @@ +public class HostName { + + public static void main(String[] args) throws java.net.UnknownHostException { + System.err.println(java.net.InetAddress.getLocalHost().getHostName()); + } + +} diff --git a/src/main/java/org/appng/tomcat/session/Constants.java b/src/main/java/org/appng/tomcat/session/Constants.java index 4d41e67..734b4dd 100644 --- a/src/main/java/org/appng/tomcat/session/Constants.java +++ b/src/main/java/org/appng/tomcat/session/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/SessionData.java b/src/main/java/org/appng/tomcat/session/SessionData.java index 00952b7..c283c32 100644 --- a/src/main/java/org/appng/tomcat/session/SessionData.java +++ b/src/main/java/org/appng/tomcat/session/SessionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/Utils.java b/src/main/java/org/appng/tomcat/session/Utils.java index 1f669bb..9254737 100644 --- a/src/main/java/org/appng/tomcat/session/Utils.java +++ b/src/main/java/org/appng/tomcat/session/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManager.java b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastManager.java similarity index 96% rename from src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManager.java rename to src/main/java/org/appng/tomcat/session/hazelcast/HazelcastManager.java index 7405e50..89beea2 100644 --- a/src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManager.java +++ b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.appng.tomcat.session.hazelcast.v2; +package org.appng.tomcat.session.hazelcast; import java.io.IOException; import java.util.Arrays; @@ -27,7 +27,6 @@ import org.apache.juli.logging.Log; import org.appng.tomcat.session.SessionData; import org.appng.tomcat.session.Utils; -import org.appng.tomcat.session.hazelcast.HazelcastSession; import com.hazelcast.config.ClasspathXmlConfig; import com.hazelcast.core.Hazelcast; @@ -38,7 +37,7 @@ public class HazelcastManager extends ManagerBase { private static final double NANOS_TO_MILLIS = 1000000d; private final Log log = Utils.getLog(HazelcastManager.class); - private String configFile = "WEB-INF/classes/hazelcast.xml"; + private String configFile = "hazelcast.xml"; private String mapName = "tomcat.sessions"; private HazelcastInstance instance; diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastPersistentManager.java b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastPersistentManager.java deleted file mode 100644 index 36b6839..0000000 --- a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastPersistentManager.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2015-2021 the original author or authors. - * - * 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.appng.tomcat.session.hazelcast; - -import java.io.IOException; - -import org.apache.catalina.Session; -import org.apache.catalina.session.PersistentManagerBase; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.appng.tomcat.session.Utils; - -public class HazelcastPersistentManager extends PersistentManagerBase { - - private static final Log log = LogFactory.getLog(HazelcastPersistentManager.class); - private String name; - - @Override - public void processExpires() { - // nothing to do here, we use an EntryExpiredListener! - } - - @Override - public int getActiveSessions() { - return getStore().getSize(); - } - - @Override - public HazelcastStore getStore() { - return (HazelcastStore) super.getStore(); - } - - @Override - public HazelcastSession createEmptySession() { - return new HazelcastSession(this); - } - - @Override - public void add(Session session) { - // do nothing, we don't want to use Map sessions! - } - - @Override - public void remove(Session session, boolean update) { - // avoid super.remove - removeSession(session.getId()); - } - - @Override - public HazelcastSession createSession(String sessionId) { - HazelcastSession session = (HazelcastSession) super.createSession(sessionId); - try { - getStore().save(session); - } catch (IOException e) { - log.warn(String.format("Error creating session: %s", session.getIdInternal())); - session = null; - } - return session; - } - - @Override - public Session findSession(String id) throws IOException { - // do not call super, instead load the session directly from the store - try { - return getStore().load(id); - } catch (ClassNotFoundException e) { - throw new IOException("error loading class for session " + id, e); - } - } - - @Override - public Session[] findSessions() { - try { - return Utils.findSessions(this, getStore().keys(), log); - } catch (IOException e) { - log.error("error finding sessions!", e); - } - return new Session[0]; - } - - @Override - public String getName() { - if (this.name == null) { - this.name = Utils.getContextName(getContext()).replace('/', '_'); - } - return this.name; - } - -} diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSession.java b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSession.java index 4736b19..6dab9c0 100644 --- a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSession.java +++ b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSessionTrackerValve.java b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSessionTrackerValve.java index 78abf4c..bc39ce3 100644 --- a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSessionTrackerValve.java +++ b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastSessionTrackerValve.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.appng.tomcat.session.hazelcast; import java.io.IOException; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import javax.servlet.ServletException; @@ -23,38 +25,61 @@ import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.PersistentValve; +import org.apache.catalina.valves.ValveBase; import org.apache.juli.logging.Log; import org.appng.tomcat.session.Utils; /** - * A {@link Valve} that uses {@link HazelcastPersistentManager} to store a {@link Session} + * A {@link Valve} that uses {@link HazelcastManager} to store a {@link Session} */ -public class HazelcastSessionTrackerValve extends PersistentValve { +public class HazelcastSessionTrackerValve extends ValveBase { private final Log log = Utils.getLog(HazelcastSessionTrackerValve.class); + protected Pattern filter = Pattern.compile("^(/template/.*)|((/health)(\\?.*)?)$"); + protected String siteNameHeader = "x-appng-site"; @Override public void invoke(Request request, Response response) throws IOException, ServletException { try { getNext().invoke(request, response); } finally { - long start = System.currentTimeMillis(); - HazelcastPersistentManager manager = (HazelcastPersistentManager) request.getContext().getManager(); Session session = request.getSessionInternal(false); - if (session != null) { - if (session.isValid()) { - log.trace(String.format("Request with session completed, saving session %s", session.getId())); - manager.getStore().save(session); - } else { - log.trace(String.format("HTTP Session has been invalidated, removing %s", session.getId())); - manager.remove(session); + if (commitRequired(request.getDecodedRequestURI()) && null != session) { + long start = System.currentTimeMillis(); + HazelcastManager manager = (HazelcastManager) request.getContext().getManager(); + boolean committed = manager.commit(session, request.getHeader(siteNameHeader)); + if (log.isDebugEnabled()) { + log.debug(String.format("Handling session %s for %s took %dms (committed: %s)", session.getId(), + request.getServletPath(), System.currentTimeMillis() - start, committed)); } } + } + } + + protected boolean commitRequired(String uri) { + return null == filter || !filter.matcher(uri).matches(); + } + + public String getSiteNameHeader() { + return siteNameHeader; + } + + public void setSiteNameHeader(String siteNameHeader) { + this.siteNameHeader = siteNameHeader; + } + + public String getFilter() { + return null == filter ? null : filter.toString(); + } - long duration = System.currentTimeMillis() - start; - if (log.isDebugEnabled() && duration > 0) { - log.debug(String.format("handling session for %s took %sms", request.getServletPath(), duration)); + public void setFilter(String filter) { + if (filter == null || filter.length() == 0) { + this.filter = null; + } else { + try { + this.filter = Pattern.compile(filter); + } catch (PatternSyntaxException pse) { + log.error("ivalid pattern", pse); } } } diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastStore.java b/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastStore.java deleted file mode 100644 index 711e849..0000000 --- a/src/main/java/org/appng/tomcat/session/hazelcast/HazelcastStore.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 2015-2021 the original author or authors. - * - * 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.appng.tomcat.session.hazelcast; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.concurrent.TimeUnit; - -import org.apache.catalina.Session; -import org.apache.catalina.Store; -import org.apache.catalina.session.StandardSession; -import org.apache.catalina.session.StoreBase; -import org.apache.juli.logging.Log; -import org.appng.tomcat.session.SessionData; -import org.appng.tomcat.session.Utils; - -import com.hazelcast.client.HazelcastClient; -import com.hazelcast.client.config.ClientConfig; -import com.hazelcast.config.ClasspathXmlConfig; -import com.hazelcast.config.Config; -import com.hazelcast.config.ManagementCenterConfig; -import com.hazelcast.config.MulticastConfig; -import com.hazelcast.config.NetworkConfig; -import com.hazelcast.config.TcpIpConfig; -import com.hazelcast.core.EntryEvent; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; -import com.hazelcast.map.IMap; -import com.hazelcast.map.listener.EntryExpiredListener; - -/** - * A {@link Store} using Hazelcast's {@link IMap} to store sessions. - *

- * Configuration parameters (defaults in brackets): - *

    - *
  • mapName ({@code tomcat.sessions})
    - * The name of the map used to store the sessions.
  • - *
  • mode ({@code multicast})
    - * The mode to use, one of {@code multicast}, {@code tcp}, {@code classpath}, {@code client}, {@code standalone}.
  • - *
  • group ({@code dev})
    - * The Hazelcast group to use.
  • - *
  • addresses ({@code localhost:5701})
    - * A comma separated list of server addresses to use, only applies to {@code client} mode.
  • - *
  • autoDetect ({@code false})
    - * Enable/disable auto-detection ({@code multicast} and {@code tcp} mode only).
  • - *
  • port ({@code 5701})
    - * The Hazelcast port to use.
  • - *
  • multicastGroup ({@code 224.2.2.3})
    - * The multicast group, only applies to {@code multicast} mode.
  • - *
  • multicastPort ({@code 54327})
    - * The multicast port, only applies to {@code multicast} mode.
  • - *
  • multicastTimeoutSeconds ({@code 2})
    - * The multicast timeout, only applies to {@code multicast} mode.
  • - *
  • multicastTimeToLive ({@code 32})
    - * The multicast ttl, only applies to {@code multicast} mode.
  • - *
  • tcpMembers (null)
    - * A comma separated list of members to connect to, only applies to {@code tcp} mode.
  • - *
  • clusterName ({@code appNG})
    - * The Hazelcast cluster name.
  • - *
  • instanceName ({@code dev})
    - * The Hazelcast instance name.
  • - *
- * - * @author Matthias Müller - */ -public class HazelcastStore extends StoreBase implements EntryExpiredListener { - - private final Log log = Utils.getLog(HazelcastStore.class); - private HazelcastInstance instance; - - private String mapName = "tomcat.sessions"; - private Mode mode = Mode.MULTICAST; - private String addresses = "localhost:5701"; - private int port = NetworkConfig.DEFAULT_PORT; - - private String multicastGroup = MulticastConfig.DEFAULT_MULTICAST_GROUP; - private int multicastPort = MulticastConfig.DEFAULT_MULTICAST_PORT; - private int multicastTimeoutSeconds = MulticastConfig.DEFAULT_MULTICAST_TIMEOUT_SECONDS; - private int multicastTimeToLive = MulticastConfig.DEFAULT_MULTICAST_TTL; - - private String tcpMembers; - private boolean managementCenterEnabled; - private String clusterName = "appNG"; - private String instanceName = "dev"; - private String configFile = "hazelcast.xml"; - private boolean lockOnSave = false; - private boolean autoDetect = false; - private boolean useDirtyMark = true; - - public enum Mode { - MULTICAST, TCP, CLIENT, STANDALONE, CLASSPATH; - } - - @Override - protected void initInternal() { - super.initInternal(); - Config config = getConfig(); - switch (mode) { - case CLIENT: - instance = HazelcastClient.getHazelcastClientByName(instanceName); - if (null == instance) { - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setInstanceName(instanceName); - String[] addressArr = addresses.split(","); - for (String address : addressArr) { - clientConfig.getNetworkConfig().addAddress(address.trim()); - } - instance = HazelcastClient.newHazelcastClient(clientConfig); - log.info(String.format("Using new client %s, connecting to %s", instanceName, - clientConfig.getNetworkConfig().getAddresses())); - } else { - log.info(String.format("Using existing client %s", instanceName)); - } - return; - - case TCP: - TcpIpConfig tcpIpConfig = config.getNetworkConfig().getJoin().getTcpIpConfig(); - tcpIpConfig.setEnabled(true); - if (null != tcpMembers) { - tcpIpConfig.addMember(tcpMembers); - log.info("Using TCP mode with members: " + tcpMembers); - } else { - log.warn("TCP mode is used, but tcpMembers is not set!"); - } - instance = Hazelcast.getOrCreateHazelcastInstance(config); - break; - - case MULTICAST: - MulticastConfig multicastConfig = config.getNetworkConfig().getJoin().getMulticastConfig(); - multicastConfig.setEnabled(true); - multicastConfig.setMulticastGroup(multicastGroup); - multicastConfig.setMulticastPort(multicastPort); - multicastConfig.setMulticastTimeoutSeconds(multicastTimeoutSeconds); - multicastConfig.setMulticastTimeToLive(multicastTimeToLive); - log.info("Using MULTICAST on " + multicastGroup + ":" + multicastPort); - instance = Hazelcast.getOrCreateHazelcastInstance(config); - break; - case CLASSPATH: - config = new ClasspathXmlConfig(configFile); - instance = Hazelcast.getOrCreateHazelcastInstance(config); - log.info("Using classpath config:" + getClass().getClassLoader().getResource(configFile)); - break; - default: - instance = Hazelcast.getOrCreateHazelcastInstance(config); - log.info("Using STANDALONE config"); - break; - } - log.info(String.format("Using instance %s", instance)); - getSessions().addEntryListener(this, true); - } - - public void entryExpired(EntryEvent event) { - SessionData expired = event.getOldValue(); - String siteName = expired.getSite(); - - try (ByteArrayInputStream in = new ByteArrayInputStream(expired.getData()); - ObjectInputStream ois = Utils.getObjectInputStream(in, siteName, getManager().getContext())) { - StandardSession session = new StandardSession(getManager()); - session.readObjectData(ois); - if (log.isDebugEnabled()) { - log.debug("expired: " + expired + " (accessed " - + ((float) (System.currentTimeMillis() - session.getLastAccessedTime()) / 1000) + "s ago, TTL: " - + session.getMaxInactiveInterval() + "s)"); - } - session.expire(true); - } catch (IOException | ClassNotFoundException e) { - log.error("Error expiring session " + event.getKey(), e); - } - } - - private Config getConfig() { - Config config = new Config(); - config.setClusterName(clusterName); - config.setInstanceName(instanceName); - config.getNetworkConfig().setPort(port); - if (managementCenterEnabled) { - config.setManagementCenterConfig(new ManagementCenterConfig()); - } - config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(false); - config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); - config.getNetworkConfig().getJoin().getAutoDetectionConfig().setEnabled(autoDetect); - return config; - } - - @Override - protected void destroyInternal() { - log.info(String.format("Shutting down instance %s", instance)); - instance.shutdown(); - } - - public void save(Session session) throws IOException { - if (lockOnSave) { - getSessions().lock(session.getId()); - } - - if (!useDirtyMark || ((HazelcastSession) session).isDirty()) { - try { - SessionData sessionData = ((HazelcastSession) session).serialize(); - getSessions().set(session.getId(), sessionData, session.getMaxInactiveInterval(), TimeUnit.SECONDS); - log.debug("saved: " + sessionData + " with TTL of " + session.getMaxInactiveInterval() + " seconds"); - } finally { - if (lockOnSave) { - getSessions().unlock(session.getId()); - } - } - } - } - - @Override - public HazelcastPersistentManager getManager() { - return (HazelcastPersistentManager) super.getManager(); - } - - // see - // https://github.com/hazelcast/hazelcast-tomcat-sessionmanager/blob/v2.2/tomcat9/src/main/java/com/hazelcast/session/HazelcastSessionManager.java#L176-L224 - public StandardSession load(String id) throws ClassNotFoundException, IOException { - StandardSession session = null; - - // the calls are performed in a pessimistic lock block to prevent concurrency problems whilst finding sessions - getSessions().lock(id); - try { - SessionData sessionData = getSessions().get(id); - if (null == sessionData) { - log.debug(String.format("Session %s not found in map %s", id, getMapNameInternal())); - } else { - try { - session = HazelcastSession.create(getManager(), sessionData); - log.debug("loaded: " + sessionData); - } catch (ClassNotFoundException e) { - log.error("Error loading session" + id, e); - } - } - } finally { - getSessions().unlock(id); - } - return session; - } - - public void remove(String id) throws IOException { - SessionData removed = getSessions().remove(id); - log.debug("removed: " + (null == removed ? id : removed)); - } - - public String[] keys() throws IOException { - return getSessions().keySet().toArray(new String[0]); - } - - public int getSize() { - return getSessions().size(); - } - - public void clear() throws IOException { - getSessions().clear(); - } - - private IMap getSessions() { - return instance.getMap(getMapNameInternal()); - } - - private String getMapNameInternal() { - return getManager().getName() + mapName; - } - - // setters - public void setMapName(String mapName) { - this.mapName = mapName; - } - - public void setMode(String mode) { - if (null != mode) { - this.mode = Mode.valueOf(mode.trim().toUpperCase()); - } - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public void setAddresses(String addresses) { - this.addresses = addresses; - } - - public void setPort(int port) { - this.port = port; - } - - public void setMulticastGroup(String multicastGroup) { - this.multicastGroup = multicastGroup; - } - - public void setMulticastPort(int multicastPort) { - this.multicastPort = multicastPort; - } - - public void setMulticastTimeoutSeconds(int multicastTimeoutSeconds) { - this.multicastTimeoutSeconds = multicastTimeoutSeconds; - } - - public void setMulticastTimeToLive(int multicastTimeToLive) { - this.multicastTimeToLive = multicastTimeToLive; - } - - public void setTcpMembers(String tcpMembers) { - this.tcpMembers = tcpMembers; - } - - public void setInstanceName(String instanceName) { - this.instanceName = instanceName; - } - - public void setManagementCenterEnabled(boolean managementCenterEnabled) { - this.managementCenterEnabled = managementCenterEnabled; - } - - public void setConfigFile(String configFile) { - this.configFile = configFile; - } - - public void setAutoDetect(boolean autoDetect) { - this.autoDetect = autoDetect; - } - - public void setLockOnSave(boolean lockOnSave) { - this.lockOnSave = lockOnSave; - } - - public void setUseDirtyMark(boolean useDirtyMark) { - this.useDirtyMark = useDirtyMark; - } -} diff --git a/src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastSessionTrackerValve.java b/src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastSessionTrackerValve.java deleted file mode 100644 index ccabff2..0000000 --- a/src/main/java/org/appng/tomcat/session/hazelcast/v2/HazelcastSessionTrackerValve.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2015-2021 the original author or authors. - * - * 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.appng.tomcat.session.hazelcast.v2; - -import java.io.IOException; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import javax.servlet.ServletException; - -import org.apache.catalina.Session; -import org.apache.catalina.Valve; -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.appng.tomcat.session.Utils; - -/** - * A {@link Valve} that uses {@link HazelcastManager} to store a {@link Session} - */ -public class HazelcastSessionTrackerValve extends ValveBase { - - private final Log log = Utils.getLog(HazelcastSessionTrackerValve.class); - protected Pattern filter = Pattern.compile("^(/template/.*)|((/health)(\\?.*)?)$"); - protected String siteNameHeader = "x-appng-site"; - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - getNext().invoke(request, response); - } finally { - Session session = request.getSessionInternal(false); - if (commitRequired(request.getDecodedRequestURI()) && null != session) { - long start = System.currentTimeMillis(); - HazelcastManager manager = (HazelcastManager) request.getContext().getManager(); - boolean committed = manager.commit(session, request.getHeader(siteNameHeader)); - if (log.isDebugEnabled()) { - log.debug(String.format("Handling session %s for %s took %dms (committed: %s)", session.getId(), - request.getServletPath(), System.currentTimeMillis() - start, committed)); - } - } - } - } - - protected boolean commitRequired(String uri) { - return null == filter || !filter.matcher(uri).matches(); - } - - public String getSiteNameHeader() { - return siteNameHeader; - } - - public void setSiteNameHeader(String siteNameHeader) { - this.siteNameHeader = siteNameHeader; - } - - public String getFilter() { - return null == filter ? null : filter.toString(); - } - - public void setFilter(String filter) { - if (filter == null || filter.length() == 0) { - this.filter = null; - } else { - try { - this.filter = Pattern.compile(filter); - } catch (PatternSyntaxException pse) { - log.error("ivalid pattern", pse); - } - } - } - -} diff --git a/src/main/java/org/appng/tomcat/session/jdbc/SiteAwareJdbcStore.java b/src/main/java/org/appng/tomcat/session/jdbc/SiteAwareJdbcStore.java index 9213bfa..2892195 100644 --- a/src/main/java/org/appng/tomcat/session/jdbc/SiteAwareJdbcStore.java +++ b/src/main/java/org/appng/tomcat/session/jdbc/SiteAwareJdbcStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/mongo/MongoPersistentManager.java b/src/main/java/org/appng/tomcat/session/mongo/MongoPersistentManager.java index c29fbca..c57fd37 100644 --- a/src/main/java/org/appng/tomcat/session/mongo/MongoPersistentManager.java +++ b/src/main/java/org/appng/tomcat/session/mongo/MongoPersistentManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/mongo/MongoSessionTrackerValve.java b/src/main/java/org/appng/tomcat/session/mongo/MongoSessionTrackerValve.java index 9080fcf..cf95591 100644 --- a/src/main/java/org/appng/tomcat/session/mongo/MongoSessionTrackerValve.java +++ b/src/main/java/org/appng/tomcat/session/mongo/MongoSessionTrackerValve.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/mongo/MongoStore.java b/src/main/java/org/appng/tomcat/session/mongo/MongoStore.java index ec78c23..b9abba2 100644 --- a/src/main/java/org/appng/tomcat/session/mongo/MongoStore.java +++ b/src/main/java/org/appng/tomcat/session/mongo/MongoStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/redis/JavaSerializer.java b/src/main/java/org/appng/tomcat/session/redis/JavaSerializer.java index 6145ed6..0b20d9d 100644 --- a/src/main/java/org/appng/tomcat/session/redis/JavaSerializer.java +++ b/src/main/java/org/appng/tomcat/session/redis/JavaSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/redis/RedisSession.java b/src/main/java/org/appng/tomcat/session/redis/RedisSession.java index 9ddbbd3..41201b2 100644 --- a/src/main/java/org/appng/tomcat/session/redis/RedisSession.java +++ b/src/main/java/org/appng/tomcat/session/redis/RedisSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/redis/RedisSessionHandlerValve.java b/src/main/java/org/appng/tomcat/session/redis/RedisSessionHandlerValve.java index 6af65c4..e49e978 100644 --- a/src/main/java/org/appng/tomcat/session/redis/RedisSessionHandlerValve.java +++ b/src/main/java/org/appng/tomcat/session/redis/RedisSessionHandlerValve.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/redis/RedisSessionManager.java b/src/main/java/org/appng/tomcat/session/redis/RedisSessionManager.java index 28ab77c..6a66c56 100644 --- a/src/main/java/org/appng/tomcat/session/redis/RedisSessionManager.java +++ b/src/main/java/org/appng/tomcat/session/redis/RedisSessionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -449,7 +449,7 @@ public int getSize() throws IOException { Boolean error = true; try { jedis = acquireConnection(); - int size = jedis.dbSize().intValue(); + int size = (int) jedis.dbSize(); error = false; return size; } finally { diff --git a/src/main/java/org/appng/tomcat/session/redis/Serializer.java b/src/main/java/org/appng/tomcat/session/redis/Serializer.java index 7861af5..0a95594 100644 --- a/src/main/java/org/appng/tomcat/session/redis/Serializer.java +++ b/src/main/java/org/appng/tomcat/session/redis/Serializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/appng/tomcat/session/redis/SessionSerializationMetadata.java b/src/main/java/org/appng/tomcat/session/redis/SessionSerializationMetadata.java index 9ff7501..dced690 100644 --- a/src/main/java/org/appng/tomcat/session/redis/SessionSerializationMetadata.java +++ b/src/main/java/org/appng/tomcat/session/redis/SessionSerializationMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/appng/tomcat/session/UtilsTest.java b/src/test/java/org/appng/tomcat/session/UtilsTest.java index 6216142..c9f683a 100644 --- a/src/test/java/org/appng/tomcat/session/UtilsTest.java +++ b/src/test/java/org/appng/tomcat/session/UtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/appng/tomcat/session/hazelcast/HazelStoreIT.java b/src/test/java/org/appng/tomcat/session/hazelcast/HazelStoreIT.java deleted file mode 100644 index dec6560..0000000 --- a/src/test/java/org/appng/tomcat/session/hazelcast/HazelStoreIT.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2015-2021 the original author or authors. - * - * 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.appng.tomcat.session.hazelcast; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; - -import org.apache.catalina.core.StandardContext; -import org.apache.catalina.core.StandardEngine; -import org.apache.catalina.core.StandardHost; -import org.apache.catalina.core.StandardService; -import org.apache.catalina.loader.WebappLoader; -import org.apache.catalina.session.StandardSession; -import org.appng.tomcat.session.hazelcast.HazelcastStore.Mode; -import org.junit.Assert; -import org.junit.Test; - -public class HazelStoreIT { - - @Test - public void testExpire() throws Exception { - StandardContext context = new StandardContext(); - context.setName("foo"); - WebappLoader loader = new WebappLoader() { - @Override - public ClassLoader getClassLoader() { - return WebappLoader.class.getClassLoader(); - } - }; - context.setLoader(loader); - StandardHost host = new StandardHost(); - StandardEngine engine = new StandardEngine(); - engine.setService(new StandardService()); - host.setParent(engine); - context.setParent(host); - - final AtomicBoolean created = new AtomicBoolean(false); - final AtomicBoolean destroyed = new AtomicBoolean(false); - context.addApplicationLifecycleListener(new HttpSessionListener() { - - public void sessionDestroyed(HttpSessionEvent se) { - destroyed.set(true); - } - - public void sessionCreated(HttpSessionEvent se) { - created.set(true); - } - }); - loader.setContext(context); - - HazelcastPersistentManager manager = new HazelcastPersistentManager(); - manager.setContext(context); - manager.init(); - - HazelcastStore store = new HazelcastStore(); - store.setMode(Mode.STANDALONE.name()); - store.setManager(manager); - store.start(); - manager.setStore(store); - - StandardSession session = manager.createSession("4711"); - session.setMaxInactiveInterval(3/* seconds */); - session.setAttribute("foo", "test"); - - Assert.assertTrue(session.isNew()); - store.save(session); - Assert.assertTrue(session.isNew()); - - TimeUnit.SECONDS.sleep(10); - - Assert.assertNull(store.load(session.getId())); - Assert.assertTrue(created.get()); - Assert.assertTrue(destroyed.get()); - } - - @Test - public void test() throws Exception { - StandardContext context = new StandardContext(); - context.setName("foo"); - WebappLoader loader = new WebappLoader() { - @Override - public ClassLoader getClassLoader() { - return WebappLoader.class.getClassLoader(); - } - }; - context.setLoader(loader); - StandardHost host = new StandardHost(); - StandardEngine engine = new StandardEngine(); - engine.setService(new StandardService()); - host.setParent(engine); - context.setParent(host); - loader.setContext(context); - - HazelcastPersistentManager manager = new HazelcastPersistentManager(); - manager.setContext(context); - manager.init(); - - HazelcastStore store = new HazelcastStore(); - store.setMode(Mode.STANDALONE.name()); - store.setManager(manager); - store.start(); - manager.setStore(store); - - StandardSession session = manager.createEmptySession(); - session.setId("4711"); - session.setNew(true); - session.setValid(true); - session.setCreationTime(System.currentTimeMillis()); - - session.setAttribute("foo", "test"); - - store.save(session); - - session = store.load(session.getId()); - Assert.assertEquals("test", session.getAttribute("foo")); - - session.setAttribute("he", "ho"); - store.save(session); - - Assert.assertEquals(1, store.getSize()); - Assert.assertArrayEquals(new String[] { "4711" }, store.keys()); - - store.remove(session.getId()); - } - -} diff --git a/src/test/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManagerIT.java b/src/test/java/org/appng/tomcat/session/hazelcast/HazelcastManagerIT.java similarity index 97% rename from src/test/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManagerIT.java rename to src/test/java/org/appng/tomcat/session/hazelcast/HazelcastManagerIT.java index ada61fb..00e97cc 100644 --- a/src/test/java/org/appng/tomcat/session/hazelcast/v2/HazelcastManagerIT.java +++ b/src/test/java/org/appng/tomcat/session/hazelcast/HazelcastManagerIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.appng.tomcat.session.hazelcast.v2; +package org.appng.tomcat.session.hazelcast; import java.io.Serializable; import java.util.HashMap; @@ -36,7 +36,6 @@ import org.apache.catalina.startup.Tomcat.FixContextListener; import org.apache.catalina.util.StandardSessionIdGenerator; import org.appng.tomcat.session.SessionData; -import org.appng.tomcat.session.hazelcast.HazelcastSession; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; diff --git a/src/test/java/org/appng/tomcat/session/mongo/MongoStoreIT.java b/src/test/java/org/appng/tomcat/session/mongo/MongoStoreIT.java index 24e3f65..89d34ae 100644 --- a/src/test/java/org/appng/tomcat/session/mongo/MongoStoreIT.java +++ b/src/test/java/org/appng/tomcat/session/mongo/MongoStoreIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/appng/tomcat/session/redis/RedisSessionMangagerIT.java b/src/test/java/org/appng/tomcat/session/redis/RedisSessionMangagerIT.java index 9b2e6eb..cb8efe7 100644 --- a/src/test/java/org/appng/tomcat/session/redis/RedisSessionMangagerIT.java +++ b/src/test/java/org/appng/tomcat/session/redis/RedisSessionMangagerIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.