diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandlerMap.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandler.java similarity index 53% rename from runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandlerMap.java rename to runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandler.java index 38696f735..851b8b3d0 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandlerMap.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/AppVersionHandler.java @@ -20,24 +20,13 @@ import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.SessionStore; import com.google.apphosting.runtime.SessionStoreFactory; -import com.google.apphosting.runtime.jetty9.JettyConstants; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; + import java.util.Objects; import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.ee8.nested.Request; -import org.eclipse.jetty.ee8.nested.Handler; -import org.eclipse.jetty.server.Response; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.ee8.nested.AbstractHandlerContainer; +import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.handler.HotSwapHandler; import org.eclipse.jetty.session.SessionManager; -import org.eclipse.jetty.util.Callback; /** * {@code AppVersionHandlerMap} is a {@code HandlerContainer} that identifies each child {@code @@ -48,12 +37,12 @@ * {@code AppVersionKey} that should be used. * */ -public class AppVersionHandlerMap extends org.eclipse.jetty.server.Handler.Abstract { +public class AppVersionHandler extends HotSwapHandler { private final AppVersionHandlerFactory appVersionHandlerFactory; private AppVersion appVersion; private org.eclipse.jetty.server.Handler handler; - public AppVersionHandlerMap(AppVersionHandlerFactory appVersionHandlerFactory) { + public AppVersionHandler(AppVersionHandlerFactory appVersionHandlerFactory) { this.appVersionHandlerFactory = appVersionHandlerFactory; } @@ -83,68 +72,15 @@ public void setSessionStoreFactory(SessionStoreFactory factory) { /** * Returns the {@code Handler} that will handle requests for the specified application version. */ - public synchronized org.eclipse.jetty.server.Handler getHandler(AppVersionKey appVersionKey) throws ServletException { + public synchronized boolean ensureHandler(AppVersionKey appVersionKey) throws ServletException { if (!Objects.equals(appVersionKey, appVersion.getKey())) - return null; - - if (handler == null && appVersion != null) { - // TODO: use HotSwapHandler. - handler = appVersionHandlerFactory.createHandler(appVersion); - } - return handler; - } + return false; - /** - * Forward the specified request on to the {@link Handler} associated with its application - * version. - */ - @Override - public boolean handle(org.eclipse.jetty.server.Request request, Response response, Callback callback) throws Exception { - AppVersionKey appVersionKey = - (AppVersionKey) request.getAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR); - if (appVersionKey == null) { - throw new ServletException("Request did not provide an application version"); - } - - org.eclipse.jetty.server.Handler handler = getHandler(appVersionKey); + Handler handler = getHandler(); if (handler == null) { - // If we throw an exception here it'll get caught, logged, and - // turned into a 500, which is definitely not what we want. - // Instead, we check for this before calling handle(), so this - // should never happen. - throw new ServletException("Unknown application: " + appVersionKey); - } - - try { - return handler.handle(request, response, callback); - } catch (ServletException | IOException ex) { - throw ex; - } catch (Exception ex) { - throw new ServletException(ex); - } - } - - @Override - protected void doStart() throws Exception { - if (handler != null) { - handler.start(); - } - super.doStart(); - } - - @Override - protected void doStop() throws Exception { - super.doStop(); - if (handler != null) { - handler.stop(); - } - } - - @Override - public void setServer(Server server) { - super.setServer(server); - if (handler != null) { - handler.setServer(server); + handler = appVersionHandlerFactory.createHandler(appVersion); + setHandler(handler); } + return (handler != null); } } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/JettyServletEngineAdapter.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/JettyServletEngineAdapter.java index 116766d75..1b3cadc6f 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/JettyServletEngineAdapter.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/jetty94/JettyServletEngineAdapter.java @@ -29,7 +29,6 @@ import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; import com.google.common.flogger.GoogleLogger; -import org.eclipse.jetty.ee8.nested.ContextHandler; import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.server.HttpConfiguration; @@ -80,7 +79,7 @@ public class JettyServletEngineAdapter implements ServletEngineAdapter { private Server server; private DelegateConnector rpcConnector; - private AppVersionHandlerMap appVersionHandlerMap; + private AppVersionHandler appVersionHandler; private final WebAppContextFactory contextFactory; private final Optional appYaml; @@ -88,8 +87,7 @@ public JettyServletEngineAdapter() { this(Optional.empty(), Optional.empty()); } - public JettyServletEngineAdapter( - Optional contextFactory, Optional appYaml) { + public JettyServletEngineAdapter(Optional contextFactory, Optional appYaml) { this.contextFactory = contextFactory.orElseGet(AppEngineWebAppContextFactory::new); this.appYaml = appYaml; } @@ -110,7 +108,14 @@ private static AppYaml getAppYaml(ServletEngineAdapter.Config runtimeOptions) { @Override public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) { - server = new Server(new QueuedThreadPool(MAX_THREAD_POOL_THREADS, MIN_THREAD_POOL_THREADS)); + server = new Server(new QueuedThreadPool(MAX_THREAD_POOL_THREADS, MIN_THREAD_POOL_THREADS)) + { + @Override + public InvocationType getInvocationType() { + return InvocationType.BLOCKING; + } + }; + rpcConnector = new DelegateConnector(server, "RPC") { @Override public void run(Runnable runnable) { @@ -123,14 +128,14 @@ public void run(Runnable runnable) { server.addConnector(rpcConnector); AppVersionHandlerFactory appVersionHandlerFactory = new AppVersionHandlerFactory(server, serverInfo, contextFactory, /*useJettyErrorPageHandler=*/ false); - appVersionHandlerMap = new AppVersionHandlerMap(appVersionHandlerFactory); + appVersionHandler = new AppVersionHandler(appVersionHandlerFactory); if (!"java8".equals(System.getenv("GAE_RUNTIME"))) { CoreSizeLimitHandler sizeLimitHandler = new CoreSizeLimitHandler(-1, MAX_RESPONSE_SIZE); - sizeLimitHandler.setHandler(appVersionHandlerMap); + sizeLimitHandler.setHandler(appVersionHandler); server.setHandler(sizeLimitHandler); } else { - server.setHandler(appVersionHandlerMap); + server.setHandler(appVersionHandler); } if (runtimeOptions.useJettyHttpProxy()) { @@ -160,23 +165,22 @@ public void stop() { @Override public void addAppVersion(AppVersion appVersion) throws FileNotFoundException { - appVersionHandlerMap.addAppVersion(appVersion); + appVersionHandler.addAppVersion(appVersion); } @Override public void deleteAppVersion(AppVersion appVersion) { - appVersionHandlerMap.removeAppVersion(appVersion.getKey()); + appVersionHandler.removeAppVersion(appVersion.getKey()); } /** * Sets the {@link com.google.apphosting.runtime.SessionStoreFactory} that will be used to create * the list of {@link com.google.apphosting.runtime.SessionStore SessionStores} to which the HTTP - * Session will be stored, if sessions are enabled. This method must be invoked after {@link - * #start(String)}. + * Session will be stored, if sessions are enabled. This method must be invoked after {@link #start(String, Config)}. */ @Override public void setSessionStoreFactory(com.google.apphosting.runtime.SessionStoreFactory factory) { - appVersionHandlerMap.setSessionStoreFactory(factory); + appVersionHandler.setSessionStoreFactory(factory); } @Override @@ -203,7 +207,7 @@ public void serviceRequest(UPRequest upRequest, MutableUpResponse upResponse) } } else { - if (appVersionHandlerMap.getHandler(appVersionKey) == null) { + if (!appVersionHandler.ensureHandler(appVersionKey)) { upResponse.setError(UPResponse.ERROR.UNKNOWN_APP_VALUE); upResponse.setErrorMessage("Unknown app: " + appVersionKey); return;