You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/01/23 13:15:19 UTC

svn commit: r1560653 - in /tomcat/trunk: java/org/apache/catalina/Context.java java/org/apache/catalina/core/StandardContext.java java/org/apache/catalina/startup/FailedContext.java test/org/apache/catalina/core/TesterContext.java

Author: markt
Date: Thu Jan 23 12:15:19 2014
New Revision: 1560653

URL: http://svn.apache.org/r1560653
Log:
Add bind()/unbind() to Context

Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
    tomcat/trunk/test/org/apache/catalina/core/TesterContext.java

Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1560653&r1=1560652&r2=1560653&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Thu Jan 23 12:15:19 2014
@@ -1594,4 +1594,43 @@ public interface Context extends Contain
      *         method names.
      */
     public Map<String, String> findPreDestroyMethods();
+
+    /**
+     * Change the current thread context class loader to the web application
+     * class loader. If no web application class loader is defined, or if the
+     * current thread is already using the web application class loader then no
+     * change will be made. If the class loader is changed and a
+     * {@link ThreadBindingListener} is configured then
+     * {@link ThreadBindingListener#bind()} will be called after the change has
+     * been made.
+     *
+     * @param usePrivilegedAction
+     *          Should a {@link java.security.PrivilegedAction} be used when
+     *          obtaining the current thread context class loader and setting
+     *          the new one?
+     * @param originalClassLoader
+     *          The current class loader if known to save this method having to
+     *          look it up
+     *
+     * @return If the class loader has been changed by the method it will return
+     *         the thread context class loader in use when the method was
+     *         called. If no change was made then this method returns null.
+     */
+    public ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader);
+
+    /**
+     * Restore the current thread context class loader to the original class
+     * loader in used before {@link #bind(boolean, ClassLoader)} was called. If
+     * no original class loader is passed to this method then no change will be
+     * made. If the class loader is changed and a {@link ThreadBindingListener}
+     * is configured then {@link ThreadBindingListener#unbind()} will be called
+     * before the change is made.
+     *
+     * @param usePrivilegedAction
+     *          Should a {@link java.security.PrivilegedAction} be used when
+     *          setting the current thread context class loader?
+     * @param originalClassLoader
+     *          The class loader to restore as the thread context class loader
+     */
+    public void unbind(boolean usePrivilegedAction, ClassLoader 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=1560653&r1=1560652&r2=1560653&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Jan 23 12:15:19 2014
@@ -23,6 +23,8 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -5707,16 +5709,7 @@ public class StandardContext extends Con
      */
     protected ClassLoader bindThread() {
 
-        ClassLoader oldContextClassLoader =
-            Thread.currentThread().getContextClassLoader();
-
-        if (getLoader() != null && getLoader().getClassLoader() != null) {
-            Thread.currentThread().setContextClassLoader
-                (getLoader().getClassLoader());
-        }
-        if (getThreadBindingListener() != null) {
-            getThreadBindingListener().bind();
-        }
+        ClassLoader oldContextClassLoader = bind(false, null);
 
         if (isUseNaming()) {
             try {
@@ -5740,10 +5733,102 @@ public class StandardContext extends Con
             ContextBindings.unbindThread(this, this);
         }
 
-        if (getThreadBindingListener() != null) {
-            getThreadBindingListener().unbind();
+        unbind(false, oldContextClassLoader);
+    }
+
+
+    @Override
+    public ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        Loader loader = getLoader();
+        ClassLoader webApplicationClassLoader = null;
+        if (loader != null) {
+            webApplicationClassLoader = loader.getClassLoader();
+        }
+
+        if (originalClassLoader == null) {
+            if (usePrivilegedAction) {
+                PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl();
+                originalClassLoader = AccessController.doPrivileged(pa);
+            } else {
+                originalClassLoader = Thread.currentThread().getContextClassLoader();
+            }
+        }
+
+        if (webApplicationClassLoader == null ||
+                webApplicationClassLoader == originalClassLoader) {
+            // Not possible or not necessary to switch class loaders. Return
+            // null to indicate this.
+            return null;
+        }
+
+        ThreadBindingListener threadBindingListener = getThreadBindingListener();
+
+        if (usePrivilegedAction) {
+            PrivilegedAction<Void> pa = new PrivilegedSetTccl(webApplicationClassLoader);
+            AccessController.doPrivileged(pa);
+        } else {
+            Thread.currentThread().setContextClassLoader(webApplicationClassLoader);
+        }
+        if (threadBindingListener != null) {
+            try {
+                threadBindingListener.bind();
+            } catch (Throwable t) {
+                ExceptionUtils.handleThrowable(t);
+                log.error(sm.getString(
+                        "standardContext.threadBindingListenerError", getName()), t);
+            }
+        }
+
+        return originalClassLoader;
+    }
+
+
+    @Override
+    public void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        if (originalClassLoader == null) {
+            return;
+        }
+
+        if (threadBindingListener != null) {
+            try {
+                threadBindingListener.unbind();
+            } catch (Throwable t) {
+                ExceptionUtils.handleThrowable(t);
+                log.error(sm.getString(
+                        "standardContext.threadBindingListenerError", getName()), t);
+            }
+        }
+
+        if (usePrivilegedAction) {
+            PrivilegedAction<Void> pa = new PrivilegedSetTccl(originalClassLoader);
+            AccessController.doPrivileged(pa);
+        } else {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+    }
+
+
+    private static class PrivilegedSetTccl implements PrivilegedAction<Void> {
+
+        private ClassLoader cl;
+
+        PrivilegedSetTccl(ClassLoader cl) {
+            this.cl = cl;
+        }
+
+        @Override
+        public Void run() {
+            Thread.currentThread().setContextClassLoader(cl);
+            return null;
+        }
+    }
+
+
+    private static class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {
+        @Override
+        public ClassLoader run() {
+            return Thread.currentThread().getContextClassLoader();
         }
-        Thread.currentThread().setContextClassLoader(oldContextClassLoader);
     }
 
 

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=1560653&r1=1560652&r2=1560653&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Thu Jan 23 12:15:19 2014
@@ -736,6 +736,17 @@ public class FailedContext extends Lifec
     public ThreadBindingListener getThreadBindingListener() { return null; }
 
     @Override
-    public void setThreadBindingListener(ThreadBindingListener threadBindingListener) { /* NO-OP */ }
+    public void setThreadBindingListener(ThreadBindingListener threadBindingListener) {
+        // NO-OP
+    }
 
+    @Override
+    public ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        return null;
+    }
+
+    @Override
+    public void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        // NO-OP
+    }
 }
\ No newline at end of file

Modified: tomcat/trunk/test/org/apache/catalina/core/TesterContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TesterContext.java?rev=1560653&r1=1560652&r2=1560653&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/core/TesterContext.java (original)
+++ tomcat/trunk/test/org/apache/catalina/core/TesterContext.java Thu Jan 23 12:15:19 2014
@@ -1203,4 +1203,14 @@ public class TesterContext implements Co
     @Override
     public void setThreadBindingListener(ThreadBindingListener threadBindingListener) { /* NO-OP */ }
 
+    @Override
+    public ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        return null;
+    }
+
+    @Override
+    public void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader) {
+        // NO-OP
+    }
+
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org