7777public class ContextHandler extends Handler .Wrapper implements Attributes , AliasCheck , Deployable
7878{
7979 private static final Logger LOG = LoggerFactory .getLogger (ContextHandler .class );
80- private static final ThreadLocal <Context > __context = new ThreadLocal <>();
80+ private static final ThreadLocal <Context > CURRENT_CONTEXT = new ThreadLocal <>();
8181
8282 public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes" ;
8383
@@ -95,7 +95,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Alias
9595 */
9696 public static Context getCurrentContext ()
9797 {
98- return __context .get ();
98+ return CURRENT_CONTEXT .get ();
9999 }
100100
101101 /**
@@ -106,7 +106,7 @@ public static Context getCurrentContext()
106106 */
107107 public static Context getCurrentContext (Server server )
108108 {
109- Context context = __context .get ();
109+ Context context = CURRENT_CONTEXT .get ();
110110 return context == null ? (server == null ? null : server .getContext ()) : context ;
111111 }
112112
@@ -513,6 +513,11 @@ public ClassLoader getClassLoader()
513513 return _classLoader ;
514514 }
515515
516+ /**
517+ * The {@link ClassLoader} to set as the {@link Thread#setContextClassLoader(ClassLoader) thread's context classloader}
518+ * when the thread executing this handler enters the scope of this context.
519+ * @param contextLoader the {@link ClassLoader} or {@code null} to avoid changing the thread's context classloader.
520+ */
516521 public void setClassLoader (ClassLoader contextLoader )
517522 {
518523 if (isStarted ())
@@ -655,8 +660,8 @@ public boolean addEventListener(EventListener listener)
655660 if (listener instanceof ContextScopeListener contextScopeListener )
656661 {
657662 _contextListeners .add (contextScopeListener );
658- if (__context .get () != null )
659- contextScopeListener .enterScope (__context .get (), null );
663+ if (CURRENT_CONTEXT .get () != null )
664+ contextScopeListener .enterScope (CURRENT_CONTEXT .get (), null );
660665 }
661666 return true ;
662667 }
@@ -671,8 +676,8 @@ public boolean removeEventListener(EventListener listener)
671676 if (listener instanceof ContextScopeListener contextScopeListener )
672677 {
673678 _contextListeners .remove (contextScopeListener );
674- if (__context .get () != null )
675- contextScopeListener .exitScope (__context .get (), null );
679+ if (CURRENT_CONTEXT .get () != null )
680+ contextScopeListener .exitScope (CURRENT_CONTEXT .get (), null );
676681 }
677682 return true ;
678683 }
@@ -728,12 +733,31 @@ protected void initializeDefaultsComplete()
728733 {
729734 }
730735
736+ /**
737+ * <p>Enters the scope of the {@link Context}.</p>
738+ * <p> Attempts to set the {@link Thread#setContextClassLoader(ClassLoader) thread's context classloader}
739+ * to the {@link #getClassLoader() configured one} if a non-null one was set.</p>
740+ *
741+ * @param contextRequest the context's {@link Request}
742+ * @return the previous {@link Thread#getContextClassLoader() thread's context classloader}
743+ */
731744 protected ClassLoader enterScope (Request contextRequest )
732745 {
746+ CURRENT_CONTEXT .set (_context );
747+
733748 ClassLoader lastLoader = Thread .currentThread ().getContextClassLoader ();
734- __context .set (_context );
735- if (_classLoader != null )
736- Thread .currentThread ().setContextClassLoader (_classLoader );
749+ if (_classLoader != null && _classLoader != lastLoader )
750+ {
751+ try
752+ {
753+ Thread .currentThread ().setContextClassLoader (_classLoader );
754+ }
755+ catch (Throwable x )
756+ {
757+ if (LOG .isDebugEnabled ())
758+ LOG .debug ("error setting a context classloader on thread {}" , Thread .currentThread (), x );
759+ }
760+ }
737761 notifyEnterScope (contextRequest );
738762 return lastLoader ;
739763 }
@@ -756,11 +780,20 @@ protected void notifyEnterScope(Request request)
756780 }
757781 }
758782
759- protected void exitScope (Request request , Context lastContext , ClassLoader lastLoader )
783+ /**
784+ * <p>Exits the scope of the {@link Context}.</p>
785+ *
786+ * @param contextRequest the context's {@link Request}
787+ * @param lastContext the previous context to restore as the current one.
788+ * @param lastLoader the previous {@link Thread#getContextClassLoader() thread's context classloader} to restore
789+ */
790+ protected void exitScope (Request contextRequest , Context lastContext , ClassLoader lastLoader )
760791 {
761- notifyExitScope (request );
762- __context .set (lastContext );
763- Thread .currentThread ().setContextClassLoader (lastLoader );
792+ CURRENT_CONTEXT .set (lastContext );
793+
794+ notifyExitScope (contextRequest );
795+ if (Thread .currentThread ().getContextClassLoader () != lastLoader )
796+ Thread .currentThread ().setContextClassLoader (lastLoader );
764797 }
765798
766799 /**
@@ -1588,7 +1621,7 @@ public List<String> getVirtualHosts()
15881621
15891622 public void call (Invocable .Callable callable , Request request ) throws Exception
15901623 {
1591- Context lastContext = __context .get ();
1624+ Context lastContext = CURRENT_CONTEXT .get ();
15921625 if (lastContext == this )
15931626 callable .call ();
15941627 else
@@ -1607,7 +1640,7 @@ public void call(Invocable.Callable callable, Request request) throws Exception
16071640
16081641 public <T > boolean test (Predicate <T > predicate , T t , Request request )
16091642 {
1610- Context lastContext = __context .get ();
1643+ Context lastContext = CURRENT_CONTEXT .get ();
16111644 if (lastContext == this )
16121645 return predicate .test (t );
16131646
@@ -1624,7 +1657,7 @@ public <T> boolean test(Predicate<T> predicate, T t, Request request)
16241657
16251658 public void accept (Consumer <Throwable > consumer , Throwable t , Request request )
16261659 {
1627- Context lastContext = __context .get ();
1660+ Context lastContext = CURRENT_CONTEXT .get ();
16281661 if (lastContext == this )
16291662 consumer .accept (t );
16301663 else
@@ -1649,7 +1682,7 @@ public void run(Runnable runnable)
16491682
16501683 public void run (Runnable runnable , Request request )
16511684 {
1652- Context lastContext = __context .get ();
1685+ Context lastContext = CURRENT_CONTEXT .get ();
16531686 if (lastContext == this )
16541687 runnable .run ();
16551688 else
0 commit comments