diff --git a/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSession.java b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSession.java index f7a4f4ad9..35c1c4e89 100644 --- a/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSession.java +++ b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSession.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * Redisson Session object for Apache Tomcat @@ -64,8 +65,9 @@ public class RedissonSession extends StandardSession { private final ReadMode readMode; private final UpdateMode updateMode; + private final AtomicInteger usages = new AtomicInteger(); + private Map loadedAttributes = Collections.emptyMap(); private Set removedAttributes = Collections.emptySet(); - private Set updatedAttributes = Collections.emptySet(); private final boolean broadcastSessionEvents; @@ -79,7 +81,9 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); - updatedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); + } + if (readMode == ReadMode.REDIS) { + loadedAttributes = new ConcurrentHashMap<>(); } try { @@ -103,12 +107,19 @@ public class RedissonSession extends StandardSession { return null; } - if (updatedAttributes.contains(name) - || removedAttributes.contains(name)) { + if (removedAttributes.contains(name)) { return super.getAttribute(name); } - return map.get(name); + Object value = loadedAttributes.get(name); + if (value == null) { + value = map.get(name); + if (value != null) { + loadedAttributes.put(name, value); + } + } + + return value; } else { if (!loaded) { synchronized (this) { @@ -170,6 +181,7 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributesClearMessage(redissonManager.getNodeId(), getId())); } map = null; + loadedAttributes.clear(); } @Override @@ -310,9 +322,11 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.DEFAULT && map != null) { fastPut(name, value); } + if (readMode == ReadMode.REDIS) { + loadedAttributes.put(name, value); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.remove(name); - updatedAttributes.add(name); } } @@ -330,9 +344,11 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributeRemoveMessage(redissonManager.getNodeId(), getId(), new HashSet(Arrays.asList(name)))); } } + if (readMode == ReadMode.REDIS) { + loadedAttributes.remove(name); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.add(name); - updatedAttributes.remove(name); } } @@ -377,8 +393,8 @@ public class RedissonSession extends StandardSession { } } - updatedAttributes.clear(); removedAttributes.clear(); + loadedAttributes.clear(); expireSession(); } @@ -430,6 +446,16 @@ public class RedissonSession extends StandardSession { public void recycle() { super.recycle(); map = null; + loadedAttributes.clear(); + } + + public void startUsage() { + usages.incrementAndGet(); + } + + public void endUsage() { + if (usages.decrementAndGet() == 0) { + loadedAttributes.clear(); + } } - } diff --git a/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSessionManager.java b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSessionManager.java index 015b67f6a..3411bf660 100644 --- a/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSessionManager.java +++ b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/RedissonSessionManager.java @@ -17,28 +17,19 @@ package org.redisson.tomcat; import java.io.File; import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpSession; -import org.apache.catalina.Context; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.LifecycleState; -import org.apache.catalina.Pipeline; -import org.apache.catalina.Session; -import org.apache.catalina.SessionEvent; -import org.apache.catalina.SessionListener; +import org.apache.catalina.*; import org.apache.catalina.session.ManagerBase; +import org.apache.catalina.valves.ValveBase; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.redisson.Redisson; -import org.redisson.api.RMap; import org.redisson.api.RSet; +import org.redisson.api.RMap; import org.redisson.api.RTopic; import org.redisson.api.RedissonClient; import org.redisson.api.listener.MessageListener; @@ -71,7 +62,7 @@ public class RedissonSessionManager extends ManagerBase { private final String nodeId = UUID.randomUUID().toString(); - private static UpdateValve updateValve; + private static ValveBase updateValve; private static Set contextInUse = Collections.newSetFromMap(new ConcurrentHashMap()); @@ -151,7 +142,7 @@ public class RedissonSessionManager extends ManagerBase { } return session; } - + public RSet getNotifiedNodes(String sessionId) { String separator = keyPrefix == null || keyPrefix.isEmpty() ? "" : ":"; String name = keyPrefix + separator + "redisson:tomcat_notified_nodes:" + sessionId; @@ -186,7 +177,7 @@ public class RedissonSessionManager extends ManagerBase { log.error("Can't read session object by id: " + id, e); } - if (attrs.isEmpty() || (broadcastSessionEvents && getNotifiedNodes(id).contains(nodeId))) { + if (attrs.isEmpty() || (broadcastSessionEvents && getNotifiedNodes(id).contains(nodeId))) { log.info("Session " + id + " can't be found"); return null; } @@ -207,7 +198,6 @@ public class RedissonSessionManager extends ManagerBase { return result; } - @Override public Session createEmptySession() { @@ -219,7 +209,7 @@ public class RedissonSessionManager extends ManagerBase { super.add(session); ((RedissonSession)session).save(); } - + @Override public void remove(Session session, boolean update) { super.remove(session, update); @@ -228,7 +218,7 @@ public class RedissonSessionManager extends ManagerBase { ((RedissonSession)session).delete(); } } - + public RedissonClient getRedisson() { return redisson; } @@ -264,6 +254,11 @@ public class RedissonSessionManager extends ManagerBase { updateValve = new UpdateValve(); pipeline.addValve(updateValve); } + } else if (readMode == ReadMode.REDIS) { + if (updateValve == null) { + updateValve = new UsageValve(); + pipeline.addValve(updateValve); + } } } diff --git a/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/UsageValve.java b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/UsageValve.java new file mode 100644 index 000000000..5108bb0b1 --- /dev/null +++ b/redisson-tomcat/redisson-tomcat-7/src/main/java/org/redisson/tomcat/UsageValve.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2013-2020 Nikita Koksharov + * + * 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.redisson.tomcat; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +/** + * Redisson Valve object for Apache Tomcat + * + * @author Nikita Koksharov + * + */ +public class UsageValve extends ValveBase { + + private static final String ALREADY_FILTERED_NOTE = UsageValve.class.getName() + ".ALREADY_FILTERED_NOTE"; + + public UsageValve() { + super(true); + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + if (getNext() == null) { + return; + } + + //check if we already filtered/processed this request + if (request.getNote(ALREADY_FILTERED_NOTE) == null) { + request.setNote(ALREADY_FILTERED_NOTE, Boolean.TRUE); + RedissonSession s = null; + try { + HttpSession session = request.getSession(false); + if (session != null) { + s = (RedissonSession) request.getContext().getManager().findSession(session.getId()); + if (s != null) { + s.startUsage(); + } + } + + getNext().invoke(request, response); + } finally { + request.removeNote(ALREADY_FILTERED_NOTE); + if (s != null) { + s.endUsage(); + } + } + } else { + getNext().invoke(request, response); + } + } + +} diff --git a/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSession.java b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSession.java index f7a4f4ad9..35c1c4e89 100644 --- a/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSession.java +++ b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSession.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * Redisson Session object for Apache Tomcat @@ -64,8 +65,9 @@ public class RedissonSession extends StandardSession { private final ReadMode readMode; private final UpdateMode updateMode; + private final AtomicInteger usages = new AtomicInteger(); + private Map loadedAttributes = Collections.emptyMap(); private Set removedAttributes = Collections.emptySet(); - private Set updatedAttributes = Collections.emptySet(); private final boolean broadcastSessionEvents; @@ -79,7 +81,9 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); - updatedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); + } + if (readMode == ReadMode.REDIS) { + loadedAttributes = new ConcurrentHashMap<>(); } try { @@ -103,12 +107,19 @@ public class RedissonSession extends StandardSession { return null; } - if (updatedAttributes.contains(name) - || removedAttributes.contains(name)) { + if (removedAttributes.contains(name)) { return super.getAttribute(name); } - return map.get(name); + Object value = loadedAttributes.get(name); + if (value == null) { + value = map.get(name); + if (value != null) { + loadedAttributes.put(name, value); + } + } + + return value; } else { if (!loaded) { synchronized (this) { @@ -170,6 +181,7 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributesClearMessage(redissonManager.getNodeId(), getId())); } map = null; + loadedAttributes.clear(); } @Override @@ -310,9 +322,11 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.DEFAULT && map != null) { fastPut(name, value); } + if (readMode == ReadMode.REDIS) { + loadedAttributes.put(name, value); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.remove(name); - updatedAttributes.add(name); } } @@ -330,9 +344,11 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributeRemoveMessage(redissonManager.getNodeId(), getId(), new HashSet(Arrays.asList(name)))); } } + if (readMode == ReadMode.REDIS) { + loadedAttributes.remove(name); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.add(name); - updatedAttributes.remove(name); } } @@ -377,8 +393,8 @@ public class RedissonSession extends StandardSession { } } - updatedAttributes.clear(); removedAttributes.clear(); + loadedAttributes.clear(); expireSession(); } @@ -430,6 +446,16 @@ public class RedissonSession extends StandardSession { public void recycle() { super.recycle(); map = null; + loadedAttributes.clear(); + } + + public void startUsage() { + usages.incrementAndGet(); + } + + public void endUsage() { + if (usages.decrementAndGet() == 0) { + loadedAttributes.clear(); + } } - } diff --git a/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSessionManager.java b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSessionManager.java index e9ded2e6f..489da2016 100644 --- a/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSessionManager.java +++ b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/RedissonSessionManager.java @@ -17,11 +17,7 @@ package org.redisson.tomcat; import java.io.File; import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpSession; @@ -33,6 +29,7 @@ import org.apache.catalina.Session; import org.apache.catalina.SessionEvent; import org.apache.catalina.SessionListener; import org.apache.catalina.session.ManagerBase; +import org.apache.catalina.valves.ValveBase; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.redisson.Redisson; @@ -70,7 +67,7 @@ public class RedissonSessionManager extends ManagerBase { private final String nodeId = UUID.randomUUID().toString(); - private static UpdateValve updateValve; + private static ValveBase updateValve; private static Set contextInUse = Collections.newSetFromMap(new ConcurrentHashMap()); @@ -262,6 +259,11 @@ public class RedissonSessionManager extends ManagerBase { updateValve = new UpdateValve(); pipeline.addValve(updateValve); } + } else if (readMode == ReadMode.REDIS) { + if (updateValve == null) { + updateValve = new UsageValve(); + pipeline.addValve(updateValve); + } } } diff --git a/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/UsageValve.java b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/UsageValve.java new file mode 100644 index 000000000..5108bb0b1 --- /dev/null +++ b/redisson-tomcat/redisson-tomcat-8/src/main/java/org/redisson/tomcat/UsageValve.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2013-2020 Nikita Koksharov + * + * 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.redisson.tomcat; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +/** + * Redisson Valve object for Apache Tomcat + * + * @author Nikita Koksharov + * + */ +public class UsageValve extends ValveBase { + + private static final String ALREADY_FILTERED_NOTE = UsageValve.class.getName() + ".ALREADY_FILTERED_NOTE"; + + public UsageValve() { + super(true); + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + if (getNext() == null) { + return; + } + + //check if we already filtered/processed this request + if (request.getNote(ALREADY_FILTERED_NOTE) == null) { + request.setNote(ALREADY_FILTERED_NOTE, Boolean.TRUE); + RedissonSession s = null; + try { + HttpSession session = request.getSession(false); + if (session != null) { + s = (RedissonSession) request.getContext().getManager().findSession(session.getId()); + if (s != null) { + s.startUsage(); + } + } + + getNext().invoke(request, response); + } finally { + request.removeNote(ALREADY_FILTERED_NOTE); + if (s != null) { + s.endUsage(); + } + } + } else { + getNext().invoke(request, response); + } + } + +} diff --git a/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSession.java b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSession.java index f7a4f4ad9..35c1c4e89 100644 --- a/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSession.java +++ b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSession.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * Redisson Session object for Apache Tomcat @@ -64,8 +65,9 @@ public class RedissonSession extends StandardSession { private final ReadMode readMode; private final UpdateMode updateMode; + private final AtomicInteger usages = new AtomicInteger(); + private Map loadedAttributes = Collections.emptyMap(); private Set removedAttributes = Collections.emptySet(); - private Set updatedAttributes = Collections.emptySet(); private final boolean broadcastSessionEvents; @@ -79,7 +81,9 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); - updatedAttributes = Collections.newSetFromMap(new ConcurrentHashMap()); + } + if (readMode == ReadMode.REDIS) { + loadedAttributes = new ConcurrentHashMap<>(); } try { @@ -103,12 +107,19 @@ public class RedissonSession extends StandardSession { return null; } - if (updatedAttributes.contains(name) - || removedAttributes.contains(name)) { + if (removedAttributes.contains(name)) { return super.getAttribute(name); } - return map.get(name); + Object value = loadedAttributes.get(name); + if (value == null) { + value = map.get(name); + if (value != null) { + loadedAttributes.put(name, value); + } + } + + return value; } else { if (!loaded) { synchronized (this) { @@ -170,6 +181,7 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributesClearMessage(redissonManager.getNodeId(), getId())); } map = null; + loadedAttributes.clear(); } @Override @@ -310,9 +322,11 @@ public class RedissonSession extends StandardSession { if (updateMode == UpdateMode.DEFAULT && map != null) { fastPut(name, value); } + if (readMode == ReadMode.REDIS) { + loadedAttributes.put(name, value); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.remove(name); - updatedAttributes.add(name); } } @@ -330,9 +344,11 @@ public class RedissonSession extends StandardSession { topic.publish(new AttributeRemoveMessage(redissonManager.getNodeId(), getId(), new HashSet(Arrays.asList(name)))); } } + if (readMode == ReadMode.REDIS) { + loadedAttributes.remove(name); + } if (updateMode == UpdateMode.AFTER_REQUEST) { removedAttributes.add(name); - updatedAttributes.remove(name); } } @@ -377,8 +393,8 @@ public class RedissonSession extends StandardSession { } } - updatedAttributes.clear(); removedAttributes.clear(); + loadedAttributes.clear(); expireSession(); } @@ -430,6 +446,16 @@ public class RedissonSession extends StandardSession { public void recycle() { super.recycle(); map = null; + loadedAttributes.clear(); + } + + public void startUsage() { + usages.incrementAndGet(); + } + + public void endUsage() { + if (usages.decrementAndGet() == 0) { + loadedAttributes.clear(); + } } - } diff --git a/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSessionManager.java b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSessionManager.java index e9ded2e6f..489da2016 100644 --- a/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSessionManager.java +++ b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/RedissonSessionManager.java @@ -17,11 +17,7 @@ package org.redisson.tomcat; import java.io.File; import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpSession; @@ -33,6 +29,7 @@ import org.apache.catalina.Session; import org.apache.catalina.SessionEvent; import org.apache.catalina.SessionListener; import org.apache.catalina.session.ManagerBase; +import org.apache.catalina.valves.ValveBase; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.redisson.Redisson; @@ -70,7 +67,7 @@ public class RedissonSessionManager extends ManagerBase { private final String nodeId = UUID.randomUUID().toString(); - private static UpdateValve updateValve; + private static ValveBase updateValve; private static Set contextInUse = Collections.newSetFromMap(new ConcurrentHashMap()); @@ -262,6 +259,11 @@ public class RedissonSessionManager extends ManagerBase { updateValve = new UpdateValve(); pipeline.addValve(updateValve); } + } else if (readMode == ReadMode.REDIS) { + if (updateValve == null) { + updateValve = new UsageValve(); + pipeline.addValve(updateValve); + } } } diff --git a/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/UsageValve.java b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/UsageValve.java new file mode 100644 index 000000000..5108bb0b1 --- /dev/null +++ b/redisson-tomcat/redisson-tomcat-9/src/main/java/org/redisson/tomcat/UsageValve.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2013-2020 Nikita Koksharov + * + * 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.redisson.tomcat; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +/** + * Redisson Valve object for Apache Tomcat + * + * @author Nikita Koksharov + * + */ +public class UsageValve extends ValveBase { + + private static final String ALREADY_FILTERED_NOTE = UsageValve.class.getName() + ".ALREADY_FILTERED_NOTE"; + + public UsageValve() { + super(true); + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + if (getNext() == null) { + return; + } + + //check if we already filtered/processed this request + if (request.getNote(ALREADY_FILTERED_NOTE) == null) { + request.setNote(ALREADY_FILTERED_NOTE, Boolean.TRUE); + RedissonSession s = null; + try { + HttpSession session = request.getSession(false); + if (session != null) { + s = (RedissonSession) request.getContext().getManager().findSession(session.getId()); + if (s != null) { + s.startUsage(); + } + } + + getNext().invoke(request, response); + } finally { + request.removeNote(ALREADY_FILTERED_NOTE); + if (s != null) { + s.endUsage(); + } + } + } else { + getNext().invoke(request, response); + } + } + +}