package org.smartly.application.desktopgap.impl.app.server;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.smartly.Smartly;
import org.smartly.application.desktopgap.DesktopGap;
import org.smartly.application.desktopgap.impl.app.DesktopController;
import org.smartly.application.desktopgap.impl.app.IDesktopConstants;
import org.smartly.application.desktopgap.impl.app.applications.window.AppManifest;
import org.smartly.application.desktopgap.impl.app.server.handlers.EndPointServlet;
import org.smartly.application.desktopgap.impl.app.server.handlers.ResourceHandler;
import org.smartly.application.desktopgap.impl.app.utils.URLUtils;
import org.smartly.commons.util.PathUtils;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* Internal WebServer
*/
public final class WebServer {
private static int PORT = DesktopGap.getPort();
private final Server _jetty;
private final String _absoluteBaseResource;
private final Set<String> _servletExtensions; // resource's extensions managed from servlet (i.e. vhtml)
private final Set<String> _servletPaths;
private boolean _initialized;
private DesktopController _desktopController;
private WebServer() {
this(PORT);
}
private WebServer(final int port) {
PORT = port;
_absoluteBaseResource = Smartly.getAbsolutePath(IDesktopConstants.INSTALLED_DIR);
_jetty = new Server();
_servletExtensions = new HashSet<String>();
_servletPaths = new HashSet<String>();
_initialized = false;
}
public void setDesktop(final DesktopController desktopController) {
_desktopController = desktopController;
}
public String getRoot() {
return _absoluteBaseResource;
}
public void registerEndPoint(final String endPoint) {
if (endPoint.startsWith("*.")) {
final String ext = endPoint.substring(1);
_servletExtensions.add(ext);
} else {
final String path = endPoint.replace("*", "");
_servletPaths.add(path);
}
}
public Set<String> getServletExtensions() {
return _servletExtensions;
}
public Set<String> getServletPaths() {
return _servletPaths;
}
public void start() throws Exception {
if (null != _jetty) {
this.init();
_jetty.start();
}
}
public void stop() throws Exception {
if (null != _jetty) {
_jetty.stop();
}
}
public AppManifest getManifest(final String appId) {
if (null != _desktopController) {
return _desktopController.getApplicationManifest(appId);
}
return null;
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private void init() {
if (!_initialized) {
final Connector[] connectors = getConnectors(PORT);
final HandlerList handlers = getChainHandlers();
final ContextHandlerCollection endpoints = getContextHandlers();
handlers.addHandler(endpoints);
_jetty.setConnectors(connectors);
_jetty.setHandler(handlers);
_initialized = true;
}
}
private Connector[] getConnectors(final int port) {
final List<Connector> result = new LinkedList<Connector>();
// http configuration
final HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8112);
final ServerConnector http = new ServerConnector(_jetty, new HttpConnectionFactory(http_config));
http.setPort(port);
http.setIdleTimeout(30000);
result.add(http);
return result.toArray(new Connector[result.size()]);
}
private HandlerList getChainHandlers() {
final HandlerList result = new HandlerList();
final ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setServer(this);
resourceHandler.setResourceBase(this.getRoot());
resourceHandler.setWelcomeFiles(new String[]{"index.html", "index.htm"});
result.addHandler(resourceHandler);
return result;
}
private ContextHandlerCollection getContextHandlers() {
final ContextHandlerCollection result = new ContextHandlerCollection();
final ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
contextHandler.setContextPath("/");
// Main endpoint handler
final String servlet_endpoint = "/*";
final EndPointServlet servlet = new EndPointServlet();
servlet.setServer(this);
servlet.setResourceBase(this.getRoot());
contextHandler.addServlet(new ServletHolder(servlet), servlet_endpoint);
this.registerEndPoint(servlet_endpoint);
result.addHandler(contextHandler);
return result;
}
// --------------------------------------------------------------------
// S T A T I C
// --------------------------------------------------------------------
private static WebServer __instance;
public static WebServer getInstance() {
if (null == __instance) {
__instance = new WebServer();
}
return __instance;
}
public static WebServer getInstance(final boolean lookupPort) {
if (null == __instance) {
final int port = getAvailablePort();
__instance = new WebServer(port);
}
return __instance;
}
public static String getHttpRoot() {
return "http://localhost:" + PORT + "/";
}
public static String getHttpPath(final String path, final boolean isDesktopGap) {
if (PathUtils.isAbsolute(path)) {
return URLUtils.addPageParamToUrl(path, isDesktopGap);
}
return URLUtils.addPageParamToUrl(PathUtils.concat(getHttpRoot(), path), isDesktopGap);
}
public static String getHttpPath(final String path) {
return getHttpPath(path, true);
}
public static int getAvailablePort() {
int port = PORT;
while (true) {
try {
final Server jetty = new Server();
final ServerConnector http = new ServerConnector(jetty);
http.setPort(port);
http.setIdleTimeout(100);
jetty.setConnectors(new Connector[]{http});
jetty.start();
jetty.stop();
break;
} catch (Throwable t) {
port++;
}
}
return port;
}
}