442495 - Bad Context ClassLoader in JSR356 WebSocket onOpen

+ Fixing onOpen context classloader to be that of the context
  that started the WebSocketUpgradeFilter (which will be the
  same as the WebAppContext in most cases)
This commit is contained in:
Joakim Erdfelt 2014-09-22 14:37:00 -07:00
parent d6082b2d65
commit 0dca1b0794
4 changed files with 114 additions and 85 deletions

View File

@ -131,6 +131,11 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
ServletContextHandler jettyContext = (ServletContextHandler)handler;
ClassLoader old = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(context.getClassLoader());
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = configureContext(context,jettyContext);
@ -231,6 +236,9 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
throw new ServletException(e);
}
}
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
@SuppressWarnings("unchecked")

View File

@ -61,6 +61,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
private final LogicalConnection connection;
private final SessionListener[] sessionListeners;
private final Executor executor;
private ClassLoader classLoader;
private ExtensionFactory extensionFactory;
private String protocolVersion;
private Map<String, String[]> parameterMap = new HashMap<>();
@ -78,6 +79,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
throw new RuntimeException("Request URI cannot be null");
}
this.classLoader = Thread.currentThread().getContextClassLoader();
this.requestURI = requestURI;
this.websocket = websocket;
this.connection = connection;
@ -183,6 +185,11 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
return this.connection.getBufferPool();
}
public ClassLoader getClassLoader()
{
return this.getClass().getClassLoader();
}
public LogicalConnection getConnection()
{
return connection;
@ -394,14 +401,16 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
return;
}
ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(classLoader);
// Upgrade success
connection.getIOState().onConnected();
// Connect remote
remote = new WebSocketRemoteEndpoint(connection,outgoingHandler,getBatchMode());
try
{
// Open WebSocket
websocket.openSession(this);
@ -425,6 +434,10 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
close(statusCode,t.getMessage());
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
public void setExtensionFactory(ExtensionFactory extensionFactory)
@ -506,4 +519,5 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
builder.append("]");
return builder.toString();
}
}

View File

@ -30,6 +30,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -70,6 +71,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class);
private final ClassLoader contextClassloader;
private final Map<Integer, WebSocketHandshake> handshakes = new HashMap<>();
/**
* Have the factory maintain 1 and only 1 scheduler. All connections share this scheduler.
@ -107,6 +109,8 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
addBean(scheduler);
addBean(bufferPool);
this.contextClassloader = Thread.currentThread().getContextClassLoader();
this.registeredSocketClasses = new ArrayList<>();
this.defaultPolicy = policy;
@ -151,8 +155,10 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
@Override
public boolean acceptWebSocket(WebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException
{
ClassLoader old = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(contextClassloader);
ServletUpgradeRequest sockreq = new ServletUpgradeRequest(request);
ServletUpgradeResponse sockresp = new ServletUpgradeResponse(response);
@ -182,6 +188,10 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
throw new IOException("Unable to accept websocket due to mangled URI", e);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
public void addSessionFactory(SessionFactory sessionFactory)

View File

@ -91,10 +91,7 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
String pathSpec = "/*";
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
boolean isMatchAfter = false;
String urlPatterns[] =
{
pathSpec
};
String urlPatterns[] = { pathSpec };
FilterRegistration.Dynamic dyn = context.addFilter(name,filter);
dyn.addMappingForUrlPatterns(dispatcherTypes,isMatchAfter,urlPatterns);