/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.web; import alluxio.AlluxioURI; import alluxio.Configuration; import alluxio.PropertyKey; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.webapp.WebAppContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import javax.annotation.concurrent.NotThreadSafe; /** * Class that bootstraps and starts a web server. */ @NotThreadSafe public abstract class WebServer { private static final Logger LOG = LoggerFactory.getLogger(WebServer.class); private final Server mServer; private final String mServiceName; private InetSocketAddress mAddress; private final ServerConnector mServerConnector; protected final WebAppContext mWebAppContext; /** * Creates a new instance of {@link WebServer}. It pairs URLs with servlets and sets the webapp * folder. * * @param serviceName name of the web service * @param address address of the server */ public WebServer(String serviceName, InetSocketAddress address) { Preconditions.checkNotNull(serviceName, "Service name cannot be null"); Preconditions.checkNotNull(address, "Server address cannot be null"); mAddress = address; mServiceName = serviceName; QueuedThreadPool threadPool = new QueuedThreadPool(); int webThreadCount = Configuration.getInt(PropertyKey.WEB_THREADS); // Jetty needs at least (1 + selectors + acceptors) threads. threadPool.setMinThreads(webThreadCount * 2 + 1); threadPool.setMaxThreads(webThreadCount * 2 + 100); mServer = new Server(threadPool); mServerConnector = new ServerConnector(mServer); mServerConnector.setPort(mAddress.getPort()); mServerConnector.setHost(mAddress.getAddress().getHostAddress()); mServer.addConnector(mServerConnector); // Open the connector here so we can resolve the port if we are selecting a free port. try { mServerConnector.open(); } catch (IOException e) { Throwables.propagate(e); } System.setProperty("org.apache.jasper.compiler.disablejsr199", "false"); mWebAppContext = new WebAppContext(); mWebAppContext.setContextPath(AlluxioURI.SEPARATOR); File warPath = new File(Configuration.get(PropertyKey.WEB_RESOURCES)); mWebAppContext.setWar(warPath.getAbsolutePath()); // 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. mWebAppContext.setAttribute( "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$" + "|.*/[^/]*taglibs.*\\.jar$"); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] {mWebAppContext, new DefaultHandler()}); mServer.setHandler(handlers); } /** * Adds a handler. * * @param handler the handler to add */ public void addHandler(AbstractHandler handler) { HandlerList handlers = new HandlerList(); handlers.addHandler(handler); for (Handler h : mServer.getHandlers()) { handlers.addHandler(h); } mServer.setHandler(handlers); } /** * @param handler to use */ public void setHandler(AbstractHandler handler) { mServer.setHandler(handler); } /** * @return the underlying Jetty server */ public Server getServer() { return mServer; } /** * Gets the actual bind hostname. * * @return the bind host */ public String getBindHost() { String bindHost = mServerConnector.getHost(); return bindHost == null ? "0.0.0.0" : bindHost; } /** * Gets the actual port that the web server is listening on. * * @return the local port */ public int getLocalPort() { return mServerConnector.getLocalPort(); } /** * Shuts down the web server. */ public void stop() throws Exception { // close all connectors and release all binding ports for (Connector connector : mServer.getConnectors()) { connector.stop(); } mServer.stop(); } /** * Starts the web server. */ public void start() { try { mServer.start(); LOG.info("{} started @ {}", mServiceName, mAddress); } catch (Exception e) { throw Throwables.propagate(e); } } }