下面列出了javax.servlet.http.HttpUpgradeHandler#org.apache.tomcat.InstanceManager 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void doTestConcurrency(InstanceManager im, int threadCount) throws Exception {
long start = System.nanoTime();
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(new InstanceManagerRunnable(im));
}
for (int i = 0; i < threadCount; i++) {
threads[i].start();
}
for (int i = 0; i < threadCount; i++) {
threads[i].join();
}
long duration = System.nanoTime() - start;
System.out.println(threadCount + " threads completed in " + duration + "ns");
}
private void fireEndpointOnClose(CloseReason closeReason) {
// Fire the onClose event
InstanceManager instanceManager = webSocketContainer.getInstanceManager();
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
t.setContextClassLoader(applicationClassLoader);
try {
localEndpoint.onClose(this, closeReason);
if (instanceManager != null) {
instanceManager.destroyInstance(localEndpoint);
}
} catch (Throwable throwable) {
ExceptionUtils.handleThrowable(throwable);
localEndpoint.onError(this, throwable);
} finally {
t.setContextClassLoader(cl);
}
}
/**
* Setups the web application context.
*
* @throws IOException
* @throws Exception
*/
protected void configureWebAppContext(final WebContextWithExtraConfigurations context) throws Exception {
context.setAttribute("javax.servlet.context.tempdir", getScratchDir());
// Set the ContainerIncludeJarPattern so that jetty examines these
// container-path jars for tlds, web-fragments etc.
// If you omit the jar that contains the jstl .tlds, the jsp engine will
// scan for them instead.
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
context.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers());
context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
context.addBean(new ServletContainerInitializersStarter(context), true);
// context.setClassLoader(getUrlClassLoader());
context.addServlet(jspServletHolder(), "*.jsp");
context.replaceConfiguration(WebInfConfiguration.class, WebInfConfigurationHomeUnpacked.class);
}
private WebAppContext createDeployedApplicationInstance(File workDirectory,
String deployedApplicationPath) {
WebAppContext deployedApplication = new WebAppContext();
deployedApplication.setContextPath(this.getContextPath());
deployedApplication.setWar(deployedApplicationPath);
deployedApplication.setAttribute("javax.servlet.context.tempdir",
workDirectory.getAbsolutePath());
deployedApplication
.setAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/.*taglibs.*\\.jar$");
deployedApplication.setAttribute(
"org.eclipse.jetty.containerInitializers", jspInitializers());
deployedApplication.setAttribute(InstanceManager.class.getName(),
new SimpleInstanceManager());
deployedApplication.addBean(new ServletContainerInitializersStarter(
deployedApplication), true);
// webapp.setClassLoader(new URLClassLoader(new
// URL[0],App.class.getClassLoader()));
deployedApplication.addServlet(jspServletHolder(), "*.jsp");
return deployedApplication;
}
/**
* Creates a Jetty context handler that can be used to expose the cross-domain functionality as implemented by
* {@link FlashCrossDomainServlet}.
*
* Note that an invocation of this method will not register the handler (and thus make the related functionality
* available to the end user). Instead, the created handler is returned by this method, and will need to be
* registered with the embedded Jetty webserver by the caller.
*
* @return A Jetty context handler (never null).
*/
protected Handler createCrossDomainHandler()
{
final ServletContextHandler context = new ServletContextHandler( null, "/crossdomain.xml", ServletContextHandler.SESSIONS );
// Ensure the JSP engine is initialized correctly (in order to be able to cope with Tomcat/Jasper precompiled JSPs).
final List<ContainerInitializer> initializers = new ArrayList<>();
initializers.add( new ContainerInitializer( new JasperInitializer(), null ) );
context.setAttribute( "org.eclipse.jetty.containerInitializers", initializers );
context.setAttribute( InstanceManager.class.getName(), new SimpleInstanceManager() );
// Generic configuration of the context.
context.setAllowNullPathInfo( true );
// Add the functionality-providers.
context.addServlet( new ServletHolder( new FlashCrossDomainServlet() ), "" );
return context;
}
/**
* {@inheritDoc}
*
* @since Servlet 3.1
*/
@SuppressWarnings("unchecked")
@Override
public <T extends HttpUpgradeHandler> T upgrade(
Class<T> httpUpgradeHandlerClass) throws java.io.IOException, ServletException {
T handler;
InstanceManager instanceManager = null;
try {
// Do not go through the instance manager for internal Tomcat classes since they don't
// need injection
if (InternalHttpUpgradeHandler.class.isAssignableFrom(httpUpgradeHandlerClass)) {
handler = httpUpgradeHandlerClass.getConstructor().newInstance();
} else {
instanceManager = getContext().getInstanceManager();
handler = (T) instanceManager.newInstance(httpUpgradeHandlerClass);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NamingException | IllegalArgumentException | NoSuchMethodException |
SecurityException e) {
throw new ServletException(e);
}
UpgradeToken upgradeToken = new UpgradeToken(handler,
getContext(), instanceManager);
coyoteRequest.action(ActionCode.UPGRADE, upgradeToken);
// Output required by RFC2616. Protocol specific headers should have
// already been set.
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
return handler;
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
private void fireEndpointOnClose(CloseReason closeReason) {
// Fire the onClose event
Throwable throwable = null;
InstanceManager instanceManager = webSocketContainer.getInstanceManager();
if (instanceManager == null) {
instanceManager = InstanceManagerBindings.get(applicationClassLoader);
}
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
t.setContextClassLoader(applicationClassLoader);
try {
localEndpoint.onClose(this, closeReason);
} catch (Throwable t1) {
ExceptionUtils.handleThrowable(t1);
throwable = t1;
} finally {
if (instanceManager != null) {
try {
instanceManager.destroyInstance(localEndpoint);
} catch (Throwable t2) {
ExceptionUtils.handleThrowable(t2);
if (throwable == null) {
throwable = t2;
}
}
}
t.setContextClassLoader(cl);
}
if (throwable != null) {
fireEndpointOnError(throwable);
}
}
WsServerContainer(ServletContext servletContext) {
this.servletContext = servletContext;
setInstanceManager((InstanceManager) servletContext.getAttribute(InstanceManager.class.getName()));
// Configure servlet context wide defaults
String value = servletContext.getInitParameter(
Constants.BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM);
if (value != null) {
setDefaultMaxBinaryMessageBufferSize(Integer.parseInt(value));
}
value = servletContext.getInitParameter(
Constants.TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM);
if (value != null) {
setDefaultMaxTextMessageBufferSize(Integer.parseInt(value));
}
value = servletContext.getInitParameter(
Constants.ENFORCE_NO_ADD_AFTER_HANDSHAKE_CONTEXT_INIT_PARAM);
if (value != null) {
setEnforceNoAddAfterHandshake(Boolean.parseBoolean(value));
}
FilterRegistration.Dynamic fr = servletContext.addFilter(
"Tomcat WebSocket (JSR356) Filter", new WsFilter());
fr.setAsyncSupported(true);
EnumSet<DispatcherType> types = EnumSet.of(DispatcherType.REQUEST,
DispatcherType.FORWARD);
fr.addMappingForUrlPatterns(types, true, "/*");
}
@Override
public void onStartup(Set<Class<?>> types, ServletContext context) throws ServletException {
if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage(MSG + ".onStartup", context.getServletContextName()));
}
// Setup a simple default Instance Manager
if (context.getAttribute(InstanceManager.class.getName())==null) {
context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
}
boolean validate = Boolean.parseBoolean(
context.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM));
String blockExternalString = context.getInitParameter(
Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
boolean blockExternal;
if (blockExternalString == null) {
blockExternal = true;
} else {
blockExternal = Boolean.parseBoolean(blockExternalString);
}
// scan the application for TLDs
TldScanner scanner = newTldScanner(context, true, validate, blockExternal);
try {
scanner.scan();
} catch (IOException | SAXException e) {
throw new ServletException(e);
}
// add any listeners defined in TLDs
for (String listener : scanner.getListeners()) {
context.addListener(listener);
}
context.setAttribute(TldCache.SERVLET_CONTEXT_ATTRIBUTE_NAME,
new TldCache(context, scanner.getUriTldResourcePathMap(),
scanner.getTldResourcePathTaglibXmlMap()));
}
public static InstanceManager getInstanceManager(ServletConfig config) {
InstanceManager instanceManager =
(InstanceManager) config.getServletContext().getAttribute(InstanceManager.class.getName());
if (instanceManager == null) {
throw new IllegalStateException("No org.apache.tomcat.InstanceManager set in ServletContext");
}
return instanceManager;
}
@Ignore
@Test
public void testConcurrency() throws Exception {
// Create a populated InstanceManager
Tomcat tomcat = getTomcatInstance();
Context ctx = tomcat.addContext(null, "", null);
tomcat.start();
InstanceManager im = ctx.getInstanceManager();
for (int i = 1; i < 9; i++) {
doTestConcurrency(im, i);
}
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
public void destroy() {
if (theServlet != null) {
theServlet.destroy();
InstanceManager instanceManager = InstanceManagerFactory.getInstanceManager(config);
try {
instanceManager.destroyInstance(theServlet);
} catch (Exception e) {
Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(t);
// Log any exception, since it can't be passed along
log.error(Localizer.getMessage("jsp.error.file.not.found",
e.getMessage()), t);
}
}
}
public static InstanceManager getInstanceManager(ServletConfig config) {
InstanceManager instanceManager =
(InstanceManager) config.getServletContext().getAttribute(InstanceManager.class.getName());
if (instanceManager == null) {
throw new IllegalStateException("No org.apache.tomcat.InstanceManager set in ServletContext");
}
return instanceManager;
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
private void fireEndpointOnClose(CloseReason closeReason) {
// Fire the onClose event
Throwable throwable = null;
InstanceManager instanceManager = webSocketContainer.getInstanceManager();
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
t.setContextClassLoader(applicationClassLoader);
try {
localEndpoint.onClose(this, closeReason);
} catch (Throwable t1) {
ExceptionUtils.handleThrowable(t1);
throwable = t1;
} finally {
if (instanceManager != null) {
try {
instanceManager.destroyInstance(localEndpoint);
} catch (Throwable t2) {
ExceptionUtils.handleThrowable(t2);
if (throwable == null) {
throwable = t2;
}
}
}
t.setContextClassLoader(cl);
}
if (throwable != null) {
fireEndpointOnError(throwable);
}
}
public static InstanceManager getInstanceManager(ServletConfig config) {
InstanceManager instanceManager =
(InstanceManager) config.getServletContext().getAttribute(InstanceManager.class.getName());
if (instanceManager == null) {
throw new IllegalStateException("No org.apache.tomcat.InstanceManager set in ServletContext");
}
return instanceManager;
}
/**
* Creates a Jetty context handler that can be used to expose BOSH (HTTP-Bind) functionality.
*
* Note that an invocation of this method will not register the handler (and thus make the related functionality
* available to the end user). Instead, the created handler is returned by this method, and will need to be
* registered with the embedded Jetty webserver by the caller.
*
* @return A Jetty context handler (never null).
*/
protected Handler createBoshHandler()
{
final int options;
if(isHttpCompressionEnabled()) {
options = ServletContextHandler.SESSIONS | ServletContextHandler.GZIP;
} else {
options = ServletContextHandler.SESSIONS;
}
final ServletContextHandler context = new ServletContextHandler( null, "/http-bind", options );
// Ensure the JSP engine is initialized correctly (in order to be able to cope with Tomcat/Jasper precompiled JSPs).
final List<ContainerInitializer> initializers = new ArrayList<>();
initializers.add( new ContainerInitializer( new JasperInitializer(), null ) );
context.setAttribute( "org.eclipse.jetty.containerInitializers", initializers );
context.setAttribute( InstanceManager.class.getName(), new SimpleInstanceManager() );
// Generic configuration of the context.
context.setAllowNullPathInfo( true );
// Add the functionality-providers.
context.addServlet( new ServletHolder( new HttpBindServlet() ), "/*" );
// Add compression filter when needed.
if (isHttpCompressionEnabled()) {
final GzipHandler gzipHandler = context.getGzipHandler();
gzipHandler.addIncludedPaths("/*");
gzipHandler.addIncludedMethods(HttpMethod.POST.asString());
}
return context;
}
@Override
public <T> T getEndpointInstance(final Class<T> clazz) throws InstantiationException {
final ClassLoader classLoader = clazz.getClassLoader();
InstanceManager instanceManager = instanceManagers.get(classLoader);
if (instanceManager == null) {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
if (tccl != null) {
instanceManager = instanceManagers.get(tccl);
}
}
// if we have a single app fallback otherwise we don't have enough contextual information here
if (instanceManager == null && instanceManagers.size() == 1) {
instanceManager = instanceManagers.values().iterator().next();
}
if (instanceManager == null) {
return super.getEndpointInstance(clazz);
}
try {
return clazz.cast(instanceManager.newInstance(clazz));
} catch (final Exception e) {
if (InstantiationException.class.isInstance(e)) {
throw InstantiationException.class.cast(e);
}
throw new InstantiationException(e.getMessage());
}
}
@Override
public InstanceManager getInstanceManager() { return null; }
@Override
public void setInstanceManager(InstanceManager instanceManager) { /* NO-OP */ }
public UpgradeToken(HttpUpgradeHandler httpUpgradeHandler,
ContextBind contextBind, InstanceManager instanceManager) {
this.contextBind = contextBind;
this.httpUpgradeHandler = httpUpgradeHandler;
this.instanceManager = instanceManager;
}
public final InstanceManager getInstanceManager() {
return instanceManager;
}
/**
* Creates a new WebSocket session for communication between the two
* provided end points. The result of {@link Thread#getContextClassLoader()}
* at the time this constructor is called will be used when calling
* {@link Endpoint#onClose(Session, CloseReason)}.
*
* @param localEndpoint The end point managed by this code
* @param wsRemoteEndpoint The other / remote endpoint
* @param wsWebSocketContainer The container that created this session
* @param requestUri The URI used to connect to this endpoint or
* <code>null</code> is this is a client session
* @param requestParameterMap The parameters associated with the request
* that initiated this session or
* <code>null</code> if this is a client session
* @param queryString The query string associated with the request
* that initiated this session or
* <code>null</code> if this is a client session
* @param userPrincipal The principal associated with the request
* that initiated this session or
* <code>null</code> if this is a client session
* @param httpSessionId The HTTP session ID associated with the
* request that initiated this session or
* <code>null</code> if this is a client session
* @param negotiatedExtensions The agreed extensions to use for this session
* @param subProtocol The agreed subprotocol to use for this
* session
* @param pathParameters The path parameters associated with the
* request that initiated this session or
* <code>null</code> if this is a client session
* @param secure Was this session initiated over a secure
* connection?
* @param endpointConfig The configuration information for the
* endpoint
* @throws DeploymentException if an invalid encode is specified
*/
public WsSession(Endpoint localEndpoint,
WsRemoteEndpointImplBase wsRemoteEndpoint,
WsWebSocketContainer wsWebSocketContainer,
URI requestUri, Map<String, List<String>> requestParameterMap,
String queryString, Principal userPrincipal, String httpSessionId,
List<Extension> negotiatedExtensions, String subProtocol, Map<String, String> pathParameters,
boolean secure, EndpointConfig endpointConfig) throws DeploymentException {
this.localEndpoint = localEndpoint;
this.wsRemoteEndpoint = wsRemoteEndpoint;
this.wsRemoteEndpoint.setSession(this);
this.remoteEndpointAsync = new WsRemoteEndpointAsync(wsRemoteEndpoint);
this.remoteEndpointBasic = new WsRemoteEndpointBasic(wsRemoteEndpoint);
this.webSocketContainer = wsWebSocketContainer;
applicationClassLoader = Thread.currentThread().getContextClassLoader();
wsRemoteEndpoint.setSendTimeout(wsWebSocketContainer.getDefaultAsyncSendTimeout());
this.maxBinaryMessageBufferSize = webSocketContainer.getDefaultMaxBinaryMessageBufferSize();
this.maxTextMessageBufferSize = webSocketContainer.getDefaultMaxTextMessageBufferSize();
this.maxIdleTimeout = webSocketContainer.getDefaultMaxSessionIdleTimeout();
this.requestUri = requestUri;
if (requestParameterMap == null) {
this.requestParameterMap = Collections.emptyMap();
} else {
this.requestParameterMap = requestParameterMap;
}
this.queryString = queryString;
this.userPrincipal = userPrincipal;
this.httpSessionId = httpSessionId;
this.negotiatedExtensions = negotiatedExtensions;
if (subProtocol == null) {
this.subProtocol = "";
} else {
this.subProtocol = subProtocol;
}
this.pathParameters = pathParameters;
this.secure = secure;
this.wsRemoteEndpoint.setEncoders(endpointConfig);
this.endpointConfig = endpointConfig;
this.userProperties.putAll(endpointConfig.getUserProperties());
this.id = Long.toHexString(ids.getAndIncrement());
InstanceManager instanceManager = webSocketContainer.getInstanceManager();
if (instanceManager == null) {
instanceManager = InstanceManagerBindings.get(applicationClassLoader);
}
if (instanceManager != null) {
try {
instanceManager.newInstance(localEndpoint);
} catch (Exception e) {
throw new DeploymentException(sm.getString("wsSession.instanceNew"), e);
}
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("wsSession.created", id));
}
}
InstanceManager getInstanceManager() {
return instanceManager;
}
protected void setInstanceManager(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}
public static void releaseTag(Tag tag, InstanceManager instanceManager, boolean reused) {
// Caller ensures pool is non-null if reuse is true
if (!reused) {
releaseTag(tag, instanceManager);
}
}