Author: markt Date: Fri Dec 19 13:55:24 2014 New Revision: 1646721 URL: http://svn.apache.org/r1646721 Log: Refactor to replace reverse map with dedicated session listener that contains a reference to the SSO ID. This refactoring is in support of the fix for BZ 57338.
Added: tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnListener.java Modified: tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java tomcat/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java Modified: tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java?rev=1646721&r1=1646720&r2=1646721&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java Fri Dec 19 13:55:24 2014 @@ -31,7 +31,6 @@ import org.apache.catalina.LifecycleExce import org.apache.catalina.Manager; import org.apache.catalina.Realm; import org.apache.catalina.Session; -import org.apache.catalina.SessionEvent; import org.apache.catalina.SessionListener; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; @@ -57,7 +56,7 @@ import org.apache.tomcat.util.res.String * * @author Craig R. McClanahan */ -public class SingleSignOn extends ValveBase implements SessionListener { +public class SingleSignOn extends ValveBase { private static final StringManager sm = StringManager.getManager(SingleSignOn.class); @@ -90,13 +89,6 @@ public class SingleSignOn extends ValveB private boolean requireReauthentication = false; /** - * The cache of single sign on identifiers, keyed by the Session that is - * associated with them. - */ - protected Map<SingleSignOnSessionKey,String> reverse = new ConcurrentHashMap<>(); - - - /** * Optional SSO cookie domain. */ private String cookieDomain; @@ -196,55 +188,6 @@ public class SingleSignOn extends ValveB } - // ------------------------------------------------ SessionListener Methods - - /** - * Acknowledge the occurrence of the specified event. - * - * @param event SessionEvent that has occurred - */ - @Override - public void sessionEvent(SessionEvent event) { - - if (!getState().isAvailable()) { - return; - } - - // We only care about session destroyed events - if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())) { - return; - } - - // Look up the single session id associated with this session (if any) - Session session = event.getSession(); - if (containerLog.isDebugEnabled()) { - containerLog.debug("Process session destroyed on " + session); - } - - String ssoId = null; - ssoId = reverse.get(new SingleSignOnSessionKey(session)); - if (ssoId == null) { - return; - } - - // Was the session destroyed as the result of a timeout or context stop? - // If so, we'll just remove the expired session from the SSO. If the - // session was logged out, we'll log out of all session associated with - // the SSO. - if (((session.getMaxInactiveInterval() > 0) - && (System.currentTimeMillis() - session.getThisAccessedTimeInternal() >= - session.getMaxInactiveInterval() * 1000)) - || (!session.getManager().getContext().getState().isAvailable())) { - removeSession(ssoId, session); - } else { - // The session was logged out. - // Deregister this single session id, invalidating - // associated sessions - deregister(ssoId); - } - } - - // ---------------------------------------------------------- Valve Methods /** @@ -349,6 +292,43 @@ public class SingleSignOn extends ValveB // ------------------------------------------------------ Protected Methods /** + * Process a session destroyed event by removing references to that session + * from the caches and - if the session destruction is the result of a + * logout - destroy the associated SSO session. + * + * @param ssoId The ID of the SSO session which which the destroyed + * session was associated + * @param session The session that has been destroyed + */ + public void sessionDestroyed(String ssoId, Session session) { + + if (!getState().isAvailable()) { + return; + } + + if (containerLog.isDebugEnabled()) { + containerLog.debug("Process session destroyed on " + session); + } + + // Was the session destroyed as the result of a timeout or context stop? + // If so, we'll just remove the expired session from the SSO. If the + // session was logged out, we'll log out of all session associated with + // the SSO. + if (((session.getMaxInactiveInterval() > 0) + && (System.currentTimeMillis() - session.getThisAccessedTimeInternal() >= + session.getMaxInactiveInterval() * 1000)) + || (!session.getManager().getContext().getState().isAvailable())) { + removeSession(ssoId, session); + } else { + // The session was logged out. + // Deregister this single session id, invalidating + // associated sessions + deregister(ssoId); + } + } + + + /** * Associate the specified single sign on identifier with the * specified Session. * @@ -368,8 +348,7 @@ public class SingleSignOn extends ValveB if (sso == null) { return false; } else { - sso.addSession(this, session); - reverse.put(new SingleSignOnSessionKey(session), ssoId); + sso.addSession(this, ssoId, session); return true; } } @@ -399,8 +378,6 @@ public class SingleSignOn extends ValveB if (containerLog.isTraceEnabled()) { containerLog.trace(" Invalidating session " + ssoKey); } - // Remove from reverse cache first to avoid recursion - reverse.remove(ssoKey); // Invalidate this session expire(ssoKey); } @@ -586,9 +563,6 @@ public class SingleSignOn extends ValveB // Remove the inactive session from SingleSignOnEntry entry.removeSession(session); - // Remove the inactive session from the 'reverse' Map. - reverse.remove(new SingleSignOnSessionKey(session)); - // If there are not sessions left in the SingleSignOnEntry, // deregister the entry. if (entry.findSessions().size() == 0) { @@ -597,6 +571,11 @@ public class SingleSignOn extends ValveB } + protected SessionListener getSessionListener(String ssoId) { + return new SingleSignOnListener(ssoId); + } + + @Override protected synchronized void startInternal() throws LifecycleException { Container c = getContainer(); Modified: tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java?rev=1646721&r1=1646720&r2=1646721&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java Fri Dec 19 13:55:24 2014 @@ -87,12 +87,12 @@ public class SingleSignOnEntry implement * the SSO session. * @param session The <code>Session</code> being associated with the SSO. */ - public void addSession(SingleSignOn sso, Session session) { + public void addSession(SingleSignOn sso, String ssoId, Session session) { SingleSignOnSessionKey key = new SingleSignOnSessionKey(session); SingleSignOnSessionKey currentKey = sessionKeys.putIfAbsent(key, key); if (currentKey == null) { // Session not previously added - session.addSessionListener(sso); + session.addSessionListener(sso.getSessionListener(ssoId)); } } Added: tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnListener.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnListener.java?rev=1646721&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnListener.java (added) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnListener.java Fri Dec 19 13:55:24 2014 @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.authenticator; + +import java.io.Serializable; + +import org.apache.catalina.Authenticator; +import org.apache.catalina.Context; +import org.apache.catalina.Manager; +import org.apache.catalina.Session; +import org.apache.catalina.SessionEvent; +import org.apache.catalina.SessionListener; + +public class SingleSignOnListener implements SessionListener, Serializable { + + private static final long serialVersionUID = 1L; + + private final String ssoId; + + public SingleSignOnListener(String ssoId) { + this.ssoId = ssoId; + } + + + @Override + public void sessionEvent(SessionEvent event) { + if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())) { + return; + } + + Session session = event.getSession(); + Manager manager = session.getManager(); + if (manager == null) { + return; + } + Context context = manager.getContext(); + if (context == null) { + return; + } + Authenticator authenticator = context.getAuthenticator(); + if (!(authenticator instanceof AuthenticatorBase)) { + return; + } + SingleSignOn sso = ((AuthenticatorBase) authenticator).sso; + if (sso == null) { + return; + } + sso.sessionDestroyed(ssoId, session); + } +} Modified: tomcat/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java?rev=1646721&r1=1646720&r2=1646721&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java (original) +++ tomcat/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java Fri Dec 19 13:55:24 2014 @@ -24,7 +24,6 @@ import org.apache.catalina.LifecycleExce import org.apache.catalina.Session; import org.apache.catalina.authenticator.SingleSignOn; import org.apache.catalina.authenticator.SingleSignOnEntry; -import org.apache.catalina.authenticator.SingleSignOnSessionKey; import org.apache.catalina.ha.CatalinaCluster; import org.apache.catalina.ha.ClusterValve; import org.apache.catalina.tribes.Channel; @@ -157,12 +156,6 @@ public class ClusterSingleSignOn extends cls, terminateOnStartFailure); cache.setChannelSendOptions(mapSendOptions); this.cache = cache; - - ReplicatedMap<SingleSignOnSessionKey,String> reverse = new ReplicatedMap<>( - this, cluster.getChannel(), rpcTimeout, cluster.getClusterName() + "-SSO-reverse", - cls, terminateOnStartFailure); - reverse.setChannelSendOptions(mapSendOptions); - this.reverse = reverse; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); throw new LifecycleException( @@ -187,7 +180,6 @@ public class ClusterSingleSignOn extends if (getCluster() != null) { ((ReplicatedMap<?,?>) cache).breakdown(); - ((ReplicatedMap<?,?>) reverse).breakdown(); } } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org