package codeine;
import codeine.jsons.info.CodeineRuntimeInfo;
import codeine.model.Constants;
import codeine.servlet.GeneralServletModule;
import codeine.stdout.StdoutRedirectToLog;
import com.google.common.collect.Lists;
import com.google.inject.*;
import com.google.inject.servlet.GuiceFilter;
import org.apache.log4j.Logger;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import javax.servlet.DispatcherType;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.EnumSet;
import java.util.List;
public abstract class AbstractCodeineBootstrap {
public AbstractCodeineBootstrap() {
}
public AbstractCodeineBootstrap(Injector injector) {
this.injector = injector;
}
protected static void boot(String component, Class<? extends AbstractCodeineBootstrap> clazz) {
new CodeineLogBootstrap().init(component, "codeine_" + component + ".log");
if (!CodeineLogBootstrap.logToStdout()) {
StdoutRedirectToLog.redirect();
}
Logger log = Logger.getLogger(AbstractCodeineBootstrap.class);
Thread.setDefaultUncaughtExceptionHandler(new CodeineUncaughtExceptionHandler());
try {
clazz.newInstance().execute1(component);
} catch (Exception e) {
e.printStackTrace();
log.error("error - exiting", e);
System.exit(1);
}
log.info("boot sequence finished");
}
final Logger log = Logger.getLogger(AbstractCodeineBootstrap.class);
private Injector injector;
protected void execute1(String component) throws Exception {
System.out.println("Starting codeine "+component+" at version " + CodeineVersion.get());
injector = Guice.createInjector(getModules(component));
FilterHolder guiceFilter = new FilterHolder(injector.getInstance(GuiceFilter.class));
ServletContextHandler handler = createServletContextHandler();
handler.setContextPath("/");
FilterHolder crossHolder = new FilterHolder(new CrossOriginFilter());
crossHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET, POST, PUT, DELETE");
crossHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Origin,Content-Type,Accept,api_token");
handler.addFilter(crossHolder, "/api/*", EnumSet.allOf(DispatcherType.class));
handler.addFilter(crossHolder, "/api-with-token/*", EnumSet.allOf(DispatcherType.class));
handler.addFilter(guiceFilter, "/*", EnumSet.allOf(DispatcherType.class));
createAdditionalServlets(handler);
ContextHandlerCollection contexts = createFileServerContexts();
contexts.addHandler(handler);
int port = startServer(contexts);
log.info("jetty started on port " + port);
injector.getInstance(CodeineRuntimeInfo.class).setPort(port);
execute();
}
protected int startServer(ContextHandlerCollection contexts) throws Exception {
return startServer(contexts, injector.getInstance(Server.class));
}
protected int startServer(ContextHandlerCollection contexts, Server jettyServer) throws Exception {
jettyServer.getConnectors()[0].setRequestHeaderSize(30000);
jettyServer.setHandler(contexts);
jettyServer.start();
int port = jettyServer.getConnectors()[0].getLocalPort();
return port;
}
protected void createAdditionalServlets(ServletContextHandler handler) {
handler.addServlet(InvalidRequestServlet.class, "/*");
}
protected ServletContextHandler createServletContextHandler() {
return new ServletContextHandler();
}
// returns a collection of contexts (Context per node)
private ContextHandlerCollection createFileServerContexts(){
ContextHandlerCollection contexts = new ContextHandlerCollection();
addHandler(Constants.RESOURCESS_CONTEXT, Constants.getResourcesDir(), contexts);
contexts.addHandler(createStaticContextHandler("/favicon.ico", Constants.getAngularDir() + "/favicon.ico"));
specificCreateFileServer(contexts);
return contexts;
}
protected void specificCreateFileServer(ContextHandlerCollection contexts) {
}
protected void addHandler(String contextPath, String filesPath, ContextHandlerCollection contexts) {
createFileSystem(filesPath);
contexts.addHandler(createStaticContextHandler(contextPath, filesPath));
log.info("context " + contextPath + " is serving " + filesPath);
}
// create the directory structure under "path" if does not already exists:
private void createFileSystem(String path)
{
log.debug("Will try to create directory structure: " + path);
File f = new File(path);
if (f.exists())
{
return;
}
if (f.mkdirs() == false)
{
log.fatal("Failed to create directory structure: " + path);
throw new RuntimeException("no write permission to create dir " + path);
}
}
private int getPid() {
String name = ManagementFactory.getRuntimeMXBean().getName();
if (name.contains("@")){
name = name.substring(0, name.indexOf('@'));
}
return Integer.valueOf(name);
}
private ContextHandler createStaticContextHandler(String contextPath, String fsPath)
{
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(true);
resourceHandler.setWelcomeFiles(new String[] {
"index.htm", "index.html"
});
resourceHandler.setResourceBase(fsPath);
ContextHandler ch = new ContextHandler();
ch.setContextPath(contextPath);
ch.setHandler(resourceHandler);
return ch;
}
private Module[] getModules(final String component) {
List<Module> $ = Lists.<Module>newArrayList(new GeneralServletModule(), new CodeineGeneralModule() , new BaseModule(component));
$.addAll(getGuiceModules());
return $.toArray(new Module[]{});
}
private final class BaseModule extends AbstractModule {
private final String component;
private BaseModule(String component) {
this.component = component;
}
@Override
protected void configure() {
// binder().requireExplicitBindings();
bind(CodeineRuntimeInfo.class).toInstance(new CodeineRuntimeInfo(CodeineVersion.get(), component, getPid()));
bind(GuiceFilter.class);
bind(Server.class).toProvider(new ServerProvider()).in(Scopes.SINGLETON);
}
}
public class ServerProvider implements Provider<Server> {
@Override
public Server get() {
int port = getHttpPort();
return new Server(port);
}
}
protected abstract List<Module> getGuiceModules();
public abstract int getHttpPort() ;
protected abstract void execute() throws Exception ;
protected Injector injector() {
return injector;
}
}