blob: 801f15b371dc7c29117e55ac1f49789beb48be41 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.edgent.console.server;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import org.apache.edgent.console.servlets.ConsoleJobServlet;
import org.apache.edgent.console.servlets.ConsoleMetricsServlet;
import org.apache.edgent.console.servlets.ConsoleServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.util.List;
/**
* The "Edgent Console".
* <p>
* The Console's HTTP server starts with a random available port unless
* a port is specified via the {@code edgent.console.port} system property.
*/
public class HttpServer {
private static final Logger logger = LoggerFactory.getLogger(HttpServer.class);
/**
* The only constructor. A private no-argument constructor. Called only once from the static HttpServerHolder class.
*/
private HttpServer() {
}
/**
* The static class that creates the singleton HttpServer object.
*/
private static class HttpServerHolder {
private static String context = "/console";
private static int port = Integer.getInteger("edgent.console.port", 0);
// use port 0 if system prop not set, so we know the server will always start
private static Undertow SERVER;
private static final HttpServer INSTANCE = new HttpServer();
private static boolean INITIALIZED = false;
}
/**
* Gets the undertow server associated with this class
* @return the io.undertow.Undertow
*/
private static Undertow getUndertowServer() {
return HttpServerHolder.SERVER;
}
/**
* Initialization of the context path for the web application "/console" occurs in this method
* and the handler for the web application is set. This only occurs once.
* @return HttpServer: the singleton instance of this class
*/
public static HttpServer getInstance() throws Exception {
if (!HttpServerHolder.INITIALIZED) {
logger.info("initializing");
DeploymentInfo servletBuilder = Servlets.deployment()
.setClassLoader(HttpServer.class.getClassLoader())
.setContextPath("/console")
.setDeploymentName("console.war")
.addServlets(
Servlets.servlet(ConsoleServlet.class.getSimpleName(), ConsoleServlet.class)
.addMapping("/console/*"),
Servlets.servlet(ConsoleJobServlet.class.getSimpleName(), ConsoleJobServlet.class)
.addMapping("/console/jobs/*"),
Servlets.servlet(ConsoleMetricsServlet.class.getSimpleName(), ConsoleMetricsServlet.class)
.addMapping("/console/metrics/*")
);
DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
manager.deploy();
HttpHandler servletHandler = manager.start();
PathHandler path = Handlers.path(Handlers.redirect(HttpServerHolder.context))
.addPrefixPath(HttpServerHolder.context, servletHandler);
HttpServerHolder.SERVER = Undertow.builder()
.addHttpListener(HttpServerHolder.port, "localhost")
.setHandler(path)
.build();
HttpServerHolder.INITIALIZED = true;
}
return HttpServerHolder.INSTANCE;
}
/**
*
* @return a String containing the context path to the console web application
*/
public String getConsoleContextPath() {
return HttpServerHolder.context;
}
/**
* Starts the tomcat web server
*/
public void startServer() {
if(!isServerStarted()) {
getUndertowServer().start();
}
}
/**
* Stops the tomcat web server
* @throws Exception on failure
*/
@SuppressWarnings("unused")
private static void stopServer() {
getUndertowServer().stop();
}
/**
* Checks to see if the tomcat web server is started
* @return a boolean: true if the server is started, false if not
*/
public boolean isServerStarted() {
try {
HttpServerHolder.SERVER.getListenerInfo();
return true;
} catch(IllegalStateException e) {
if ("UT000138: Server not started".equals(e.getMessage())) {
return false;
} else {
throw e;
}
}
}
/**
* Checks to see if the server is in a "stopping" or "stopped" state
* @return a boolean: true if the server is stopping or stopped, false otherwise
*/
public boolean isServerStopped() {
return !isServerStarted();
}
/**
* Returns the port number the console is running on. Each time the console is started a different port number may be returned.
* @return an int: the port number the jetty server is listening on
*/
public int getConsolePortNumber() {
List<Undertow.ListenerInfo> listenerInfos = HttpServerHolder.SERVER.getListenerInfo();
if(!listenerInfos.isEmpty()) {
Undertow.ListenerInfo listenerInfo = listenerInfos.iterator().next();
if(listenerInfo.getAddress() instanceof InetSocketAddress) {
InetSocketAddress address = (InetSocketAddress) listenerInfo.getAddress();
return address.getPort();
}
}
return HttpServerHolder.port;
}
/**
* Returns the url for the web application at the "console" context path. Localhost is always assumed
* @return the url for the web application at the "console" context path.
*/
public String getConsoleUrl() {
return "http://localhost" + ":" + getConsolePortNumber() + getConsoleContextPath();
}
}