Author: remm
Date: Thu Jan 16 22:07:28 2014
New Revision: 1558930
URL: http://svn.apache.org/r1558930
Log:
- Add dedicated listener for framework and EE integration.
- Fix context classloader with SSO session expiration.
Added:
tomcat/trunk/java/org/apache/catalina/ThreadBindingListener.java
Modified:
tomcat/trunk/java/org/apache/catalina/Context.java
tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java
tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java
tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java
tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java
tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Thu Jan 16 22:07:28 2014
@@ -1069,6 +1069,18 @@ public interface Context extends Contain
/**
+ * Get the associated ThreadBindingListener.
+ */
+ public ThreadBindingListener getThreadBindingListener();
+
+
+ /**
+ * Get the associated ThreadBindingListener.
+ */
+ public void setThreadBindingListener(ThreadBindingListener
threadBindingListener);
+
+
+ /**
* Return the set of watched resources for this Context. If none are
* defined, a zero length array will be returned.
*/
Added: tomcat/trunk/java/org/apache/catalina/ThreadBindingListener.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/ThreadBindingListener.java?rev=1558930&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/ThreadBindingListener.java (added)
+++ tomcat/trunk/java/org/apache/catalina/ThreadBindingListener.java Thu Jan 16
22:07:28 2014
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+
+/**
+ * Callback for establishing naming association when entering the application
+ * scope. This corresponds to setting the context classloader.
+ */
+public interface ThreadBindingListener {
+
+ public void bind();
+ public void unbind();
+
+}
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=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java Thu
Jan 16 22:07:28 2014
@@ -20,17 +20,23 @@ package org.apache.catalina.authenticato
import java.io.IOException;
+import java.security.AccessController;
import java.security.Principal;
+import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
+import org.apache.catalina.Context;
+import org.apache.catalina.Globals;
+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.ThreadBindingListener;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
@@ -415,7 +421,15 @@ public class SingleSignOn extends ValveB
reverse.remove(sessions[i]);
}
// Invalidate this session
- sessions[i].expire();
+ ClassLoader oldContextClassLoader = null;
+ try {
+ oldContextClassLoader = bindThread(sessions[i]);
+ sessions[i].expire();
+ } finally {
+ if (oldContextClassLoader != null) {
+ unbindThread(sessions[i], oldContextClassLoader);
+ }
+ }
}
// NOTE: Clients may still possess the old single sign on cookie,
@@ -424,6 +438,94 @@ public class SingleSignOn extends ValveB
}
+ protected ClassLoader bindThread(Session session) {
+
+ Manager manager = session.getManager();
+ Context context = null;
+ ClassLoader contextClassLoader = null;
+ ThreadBindingListener threadBindingListener = null;
+ if (manager != null) {
+ context = manager.getContext();
+ }
+ if (context != null) {
+ if (context.getLoader() != null &&
context.getLoader().getClassLoader() != null) {
+ contextClassLoader = context.getLoader().getClassLoader();
+ }
+ threadBindingListener = context.getThreadBindingListener();
+ }
+ if (threadBindingListener == null || contextClassLoader == null) {
+ return null;
+ }
+
+ if (Globals.IS_SECURITY_ENABLED) {
+ return AccessController.doPrivileged(new
PrivilegedBind(contextClassLoader, threadBindingListener));
+ } else {
+ ClassLoader oldContextClassLoader =
+ Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(contextClassLoader);
+ threadBindingListener.bind();
+ return oldContextClassLoader;
+ }
+
+ }
+
+ protected class PrivilegedBind implements PrivilegedAction<ClassLoader> {
+ private ClassLoader contextClassLoader;
+ private ThreadBindingListener threadBindingListener;
+
+ PrivilegedBind(ClassLoader contextClassLoader, ThreadBindingListener
threadBindingListener) {
+ this.contextClassLoader = contextClassLoader;
+ this.threadBindingListener = threadBindingListener;
+ }
+
+ public ClassLoader run() {
+ ClassLoader oldContextClassLoader =
+ Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(contextClassLoader);
+ threadBindingListener.bind();
+ return oldContextClassLoader;
+ }
+ }
+
+ protected void unbindThread(Session session, ClassLoader
oldContextClassLoader) {
+
+ Manager manager = session.getManager();
+ Context context = null;
+ ThreadBindingListener threadBindingListener = null;
+ if (manager != null) {
+ context = manager.getContext();
+ }
+ if (context != null) {
+ threadBindingListener = context.getThreadBindingListener();
+ }
+ if (threadBindingListener == null) {
+ return;
+ }
+
+ if (Globals.IS_SECURITY_ENABLED) {
+ AccessController.doPrivileged(new
PrivilegedUnbind(oldContextClassLoader, threadBindingListener));
+ } else {
+ threadBindingListener.unbind();
+
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+ }
+
+ }
+
+ protected class PrivilegedUnbind implements PrivilegedAction<Void> {
+ private ClassLoader oldContextClassLoader;
+ private ThreadBindingListener threadBindingListener;
+
+ PrivilegedUnbind(ClassLoader oldContextClassLoader,
ThreadBindingListener threadBindingListener) {
+ this.oldContextClassLoader = oldContextClassLoader;
+ this.threadBindingListener = threadBindingListener;
+ }
+
+ public Void run() {
+ threadBindingListener.unbind();
+
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+ return null;
+ }
+ }
/**
* Attempts reauthentication to the given <code>Realm</code> using
Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java Thu
Jan 16 22:07:28 2014
@@ -670,6 +670,7 @@ final class ApplicationDispatcher implem
if (oldCCL != contextClassLoader) {
Thread.currentThread().setContextClassLoader(contextClassLoader);
+ context.getThreadBindingListener().bind();
} else {
oldCCL = null;
}
@@ -795,8 +796,10 @@ final class ApplicationDispatcher implem
}
// Reset the old context class loader
- if (oldCCL != null)
+ if (oldCCL != null) {
+ context.getThreadBindingListener().unbind();
Thread.currentThread().setContextClassLoader(oldCCL);
+ }
// Unwrap request/response if needed
// See Bugzilla 30949
Modified: tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java Thu Jan 16
22:07:28 2014
@@ -55,6 +55,7 @@ import org.apache.catalina.LifecycleStat
import org.apache.catalina.Loader;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
+import org.apache.catalina.ThreadBindingListener;
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
@@ -1354,6 +1355,10 @@ public abstract class ContainerBase exte
Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
loader.getClassLoader());
+ ThreadBindingListener tbl = ((Context)
container).getThreadBindingListener();
+ if (tbl != null) {
+ tbl.bind();
+ }
}
container.backgroundProcess();
Container[] children = container.findChildren();
@@ -1367,9 +1372,15 @@ public abstract class ContainerBase exte
log.error("Exception invoking periodic operation: ", t);
} finally {
if (originalClassLoader != null) {
+ if (container instanceof Context) {
+ ThreadBindingListener tbl = ((Context)
container).getThreadBindingListener();
+ if (tbl != null) {
+ tbl.unbind();
+ }
+ }
Thread.currentThread().setContextClassLoader(
originalClassLoader);
- }
+ }
}
}
}
Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Jan 16
22:07:28 2014
@@ -92,6 +92,7 @@ import org.apache.catalina.Loader;
import org.apache.catalina.Manager;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
+import org.apache.catalina.ThreadBindingListener;
import org.apache.catalina.Valve;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
@@ -807,6 +808,11 @@ public class StandardContext extends Con
private String containerSciFilter;
+ protected static final ThreadBindingListener DEFAULT_NAMING_LISTENER =
(new ThreadBindingListener() {
+ public void bind() {}
+ public void unbind() {}
+ });
+ protected ThreadBindingListener threadBindingListener =
DEFAULT_NAMING_LISTENER;
// ----------------------------------------------------- Context Properties
@@ -2386,6 +2392,17 @@ public class StandardContext extends Con
this.jspConfigDescriptor = descriptor;
}
+ @Override
+ public ThreadBindingListener getThreadBindingListener() {
+ return threadBindingListener;
+ }
+
+ @Override
+ public void setThreadBindingListener(ThreadBindingListener
threadBindingListener) {
+ this.threadBindingListener = threadBindingListener;
+ }
+
+
// ------------------------------------------------------ Public Properties
/**
@@ -5712,6 +5729,9 @@ public class StandardContext extends Con
Thread.currentThread().setContextClassLoader
(getLoader().getClassLoader());
}
+ if (getThreadBindingListener() != null) {
+ getThreadBindingListener().bind();
+ }
if (isUseNaming()) {
try {
@@ -5735,6 +5755,9 @@ public class StandardContext extends Con
ContextBindings.unbindThread(this, this);
}
+ if (getThreadBindingListener() != null) {
+ getThreadBindingListener().unbind();
+ }
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
}
Modified: tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java Thu Jan
16 22:07:28 2014
@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletRes
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
+import org.apache.catalina.ThreadBindingListener;
import org.apache.catalina.Wrapper;
import org.apache.catalina.comet.CometEvent;
import org.apache.catalina.connector.ClientAbortException;
@@ -130,11 +131,14 @@ final class StandardHostValve extends Va
// This should eventually move to Engine, it's generic.
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
- context.getLoader().getClassLoader());
+ context.getLoader().getClassLoader(),
+ context.getThreadBindingListener(),
+ true);
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
+ context.getThreadBindingListener().bind();
}
}
if (request.isAsyncSupported()) {
@@ -201,9 +205,11 @@ final class StandardHostValve extends Va
// Restore the context classloader
if (Globals.IS_SECURITY_ENABLED) {
- PrivilegedAction<Void> pa = new PrivilegedSetTccl(MY_CLASSLOADER);
+ PrivilegedAction<Void> pa = new PrivilegedSetTccl(MY_CLASSLOADER,
+ context.getThreadBindingListener(), false);
AccessController.doPrivileged(pa);
} else {
+ context.getThreadBindingListener().unbind();
Thread.currentThread().setContextClassLoader(MY_CLASSLOADER);
}
}
@@ -232,6 +238,7 @@ final class StandardHostValve extends Va
// This should eventually move to Engine, it's generic.
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
+ context.getThreadBindingListener().bind();
}
// Ask this Context to process this request
@@ -257,6 +264,7 @@ final class StandardHostValve extends Va
}
// Restore the context classloader
+ context.getThreadBindingListener().unbind();
Thread.currentThread().setContextClassLoader
(StandardHostValve.class.getClassLoader());
@@ -508,14 +516,23 @@ final class StandardHostValve extends Va
private static class PrivilegedSetTccl implements PrivilegedAction<Void> {
private final ClassLoader cl;
+ private final ThreadBindingListener tbl;
+ private final boolean bind;
- PrivilegedSetTccl(ClassLoader cl) {
+ PrivilegedSetTccl(ClassLoader cl, ThreadBindingListener tbl, boolean
bind) {
this.cl = cl;
+ this.bind = bind;
+ this.tbl = tbl;
}
@Override
public Void run() {
Thread.currentThread().setContextClassLoader(cl);
+ if (bind) {
+ tbl.bind();
+ } else {
+ tbl.unbind();
+ }
return null;
}
}
Modified: tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java Thu
Jan 16 22:07:28 2014
@@ -42,6 +42,7 @@ public final class SecurityClassLoad {
return;
}
+ loadAuthenticatorPackage(loader);
loadCorePackage(loader);
loadCoyotePackage(loader);
loadLoaderPackage(loader);
@@ -55,6 +56,18 @@ public final class SecurityClassLoad {
}
+ private static final void loadAuthenticatorPackage(ClassLoader loader)
+ throws Exception {
+ final String basePackage = "org.apache.catalina.authenticator.";
+ loader.loadClass
+ (basePackage +
+ "SingleSignOn$PrivilegedBind");
+ loader.loadClass
+ (basePackage +
+ "SingleSignOn$PrivilegedUnbind");
+ }
+
+
private static final void loadCorePackage(ClassLoader loader)
throws Exception {
final String basePackage = "org.apache.catalina.core.";
Modified: tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Thu Jan 16
22:07:28 2014
@@ -43,6 +43,7 @@ import org.apache.catalina.Loader;
import org.apache.catalina.Manager;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
+import org.apache.catalina.ThreadBindingListener;
import org.apache.catalina.Valve;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.Wrapper;
@@ -730,4 +731,11 @@ public class FailedContext extends Lifec
@Override
public String getContainerSciFilter() { return null; }
+
+ @Override
+ public ThreadBindingListener getThreadBindingListener() { return null; }
+
+ @Override
+ public void setThreadBindingListener(ThreadBindingListener
threadBindingListener) { /* NO-OP */ }
+
}
\ No newline at end of file
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1558930&r1=1558929&r2=1558930&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Jan 16 22:07:28 2014
@@ -196,6 +196,9 @@
grouped more logically in JConsole. Generally, components are now
grouped by Host and then by Context. (markt)
</fix>
+ <add>
+ Context listener to allow better EE and framework integration. (remm)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]