package com.constellio.app.start;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.TagLibConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import com.constellio.model.conf.FoldersLocator;
public class ApplicationStarter {
private static int REQUEST_HEADER_SIZE = 32 * 1024;
private static Server server;
private static WebAppContext handler;
private static Map<String, List<Servlet>> servletMappings = new HashMap<>();
private static Map<String, List<Filter>> filterMappings = new HashMap<>();
private ApplicationStarter() {
}
public static void startApplication(boolean joinServerThread, File webContentDir, int port) {
startApplication(new ApplicationStarterParams().setJoinServerThread(joinServerThread).setWebContentDir(webContentDir)
.setPort(port));
}
public static void startApplication(boolean joinServerThread, File webContentDir, int port, String sslPassword) {
startApplication(new ApplicationStarterParams().setJoinServerThread(joinServerThread).setWebContentDir(webContentDir)
.setPort(port).setSSLWithKeystorePassword(sslPassword));
}
public static void startApplication(ApplicationStarterParams params) {
List<String> resources = new ArrayList<String>();
resources.add(params.getWebContentDir().getAbsolutePath());
server = newServer(params);
// Static file handler
handler = new WebAppContext();
handler.setConfigurations(new Configuration[] { new WebXmlConfiguration(), new WebInfConfiguration(),
new TagLibConfiguration(), new MetaInfConfiguration(), new FragmentConfiguration() });
handler.setContextPath("/constellio");
handler.setBaseResource(new ResourceCollection(resources.toArray(new String[0])));
handler.setParentLoaderPriority(true);
handler.setClassLoader(Thread.currentThread().getContextClassLoader());
server.setHandler(handler);
try {
server.start();
for (String pathSpec : filterMappings.keySet()) {
List<Filter> filters = filterMappings.get(pathSpec);
for (Filter filter : filters) {
handler.addFilter(new FilterHolder(filter), pathSpec, EnumSet.allOf(DispatcherType.class));
}
}
for (String pathSpec : servletMappings.keySet()) {
List<Servlet> servlets = servletMappings.get(pathSpec);
for (Servlet servlet : servlets) {
handler.addServlet(new ServletHolder(servlet), pathSpec);
}
}
} catch (Exception e) {
throw new ApplicationStarterRuntimeException(e);
}
if (params.isJoinServerThread()) {
try {
server.join();
} catch (InterruptedException e) {
throw new ApplicationStarterRuntimeException(e);
}
}
}
private static Server newServer(ApplicationStarterParams params) {
if (params.isSSL()) {
return getSslServer(params);
} else {
SocketConnector connector = new SocketConnector();
connector.setPort(params.getPort());
connector.setRequestHeaderSize(REQUEST_HEADER_SIZE);
Server server = new Server();
server.setConnectors(new Connector[] { connector });
return server;
}
}
public static void stopApplication() {
filterMappings.clear();
servletMappings.clear();
handler = null;
try {
server.stop();
} catch (Exception e) {
throw new ApplicationStarterRuntimeException(e);
}
}
private static Server getSslServer(ApplicationStarterParams params) {
Server sslServer = new Server();
String keystorePath = new FoldersLocator().getKeystoreFile().getAbsolutePath();
SslContextFactory sslContextFactory = new SslContextFactory(keystorePath);
sslContextFactory.setKeyStorePassword(params.getKeystorePassword());
sslContextFactory.addExcludeProtocols("SSLv3", "SSLv2", "SSLv2Hello");
sslContextFactory.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"
);
SslSocketConnector connector = new SslSocketConnector(sslContextFactory);
connector.setPort(params.getPort());
connector.setRequestHeaderSize(REQUEST_HEADER_SIZE);
sslServer.setConnectors(new Connector[] { connector });
return sslServer;
}
public static void registerServlet(String pathRelativeToConstellioContext, Servlet servlet) {
if (handler == null) {
if (!servletMappings.containsKey(pathRelativeToConstellioContext)) {
servletMappings.put(pathRelativeToConstellioContext, new ArrayList<Servlet>());
}
servletMappings.get(pathRelativeToConstellioContext).add(servlet);
} else {
handler.addServlet(new ServletHolder(servlet), pathRelativeToConstellioContext);
}
}
public static void registerFilter(String pathRelativeToConstellioContext, Filter filter) {
if (handler == null) {
if (!filterMappings.containsKey(pathRelativeToConstellioContext)) {
filterMappings.put(pathRelativeToConstellioContext, new ArrayList<Filter>());
}
filterMappings.get(pathRelativeToConstellioContext).add(filter);
} else {
handler.addFilter(new FilterHolder(filter), pathRelativeToConstellioContext, EnumSet.allOf(DispatcherType.class));
}
}
public static void resetServlets() {
servletMappings.clear();
}
public static void resetFilters() {
filterMappings.clear();
}
}