package com.philemonworks.critter;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Names;
import com.philemonworks.critter.ui.AdminUIResource;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.server.impl.container.netty.NettyHandlerContainer;
import org.apache.commons.lang3.StringUtils;
import org.rendershark.http.HttpServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.philemonworks.critter.Constants.*;
import java.io.FileInputStream;
import java.util.Properties;
public class Launcher {
private static final String PROXY_PORT = "proxy.port";
private static final String TRAFFIC_PORT = "traffic.port";
private static final String PROXY_HOST = "proxy.host";
private static final String PROXY_WORKERS = "proxy.workers";
private static final String H2_ENABLED = "h2";
private static final int DEFAULT_NUMBER_OF_WORKERS = Runtime.getRuntime().availableProcessors() * 2;
private static final Logger LOG = LoggerFactory.getLogger(Launcher.class);
public static void main(String[] args) {
String propertiesFileName = null;
if (args.length == 1) {
propertiesFileName = args[0];
}
startWithConfiguration(loadProperties(propertiesFileName));
}
private static void startWithConfiguration(final Properties configProperties) {
java.util.logging.Logger jersey = java.util.logging.Logger.getLogger("com.sun.jersey");
jersey.setLevel(java.util.logging.Level.OFF);
final TrafficManager manager = new TrafficManager();
Module managerModule = new ManagerModule(new Properties(configProperties), manager);
LOG.info("Starting Proxy Server...");
LOG.info("using the following properties : " + configProperties.toString());
final HttpServer proxyServer = startProxyServer(new Properties(configProperties), managerModule);
Module proxyServerModule = new AbstractModule() {
protected void configure() {
this.bind(HttpServer.class)
.annotatedWith(Names.named("Proxy"))
.toInstance(proxyServer);
}
};
LOG.info("Starting Traffic Server...");
startTrafficServer(new Properties(configProperties), managerModule, proxyServerModule);
}
private static void startTrafficServer(Properties trafficProperties, Module managerModule, Module proxyServerModule) {
trafficProperties.put(ClassNamesResourceConfig.PROPERTY_CLASSNAMES,
TrafficResource.class.getName() + " " +
AdminUIResource.class.getName());
String trafficPort = trafficProperties.getProperty(TRAFFIC_PORT);
startUpServerWith(trafficPort, HttpServer.createPropertiesModule(trafficProperties), managerModule, proxyServerModule, new TrafficModule());
}
private static HttpServer startProxyServer(Properties proxyProperties, Module managerModule) {
proxyProperties.put(ClassNamesResourceConfig.PROPERTY_CLASSNAMES, ProxyResource.class.getName());
proxyProperties.put(ClassNamesResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, ProxyFilter.class.getName());
String proxyPort = proxyProperties.getProperty(PROXY_PORT);
String numberOfWorkers = proxyProperties.getProperty(PROXY_WORKERS);
proxyProperties.put(NettyHandlerContainer.PROPERTY_BASE_URI, "http://" + proxyProperties.getProperty(PROXY_HOST) + ":" + proxyPort + "/");
return startUpServerWith(proxyPort, (StringUtils.isNotBlank(numberOfWorkers) ? Integer.parseInt(numberOfWorkers) : DEFAULT_NUMBER_OF_WORKERS),
HttpServer.createPropertiesModule(proxyProperties),
managerModule,
new ProxyModule());
}
private static HttpServer startUpServerWith(String portString, Module... modules) {
return startUpServerWith(portString, DEFAULT_NUMBER_OF_WORKERS, modules);
}
private static HttpServer startUpServerWith(String portString, int numberOfWorkers, Module... modules) {
int port = Integer.parseInt(portString);
Injector injector = Guice.createInjector(modules);
HttpServer server = injector.getInstance(HttpServer.class);
server.setNumberOfWorkers(numberOfWorkers);
server.init(injector, port);
server.startUp();
return server;
}
public static Properties loadProperties(String propertiesFileName) {
Properties p = new Properties();
p.putAll(getDefaultProperties());
p.putAll(getPropertiesFromFile(propertiesFileName));
p.putAll(getPropertiesFromEnvironment());
return p;
}
private static Properties getDefaultProperties() {
Properties properties = new Properties();
properties.setProperty(PROXY_HOST, "localhost");
properties.setProperty(PROXY_PORT, "8888");
properties.setProperty(TRAFFIC_PORT, "8877");
properties.setProperty("rule.database.h2.enabled", "false");
properties.setProperty(FORWARD_NO_PROXY, "");
properties.setProperty(FORWARD_HTTPS_PROXY, "");
properties.setProperty(FORWARD_HTTP_PROXY, "");
return properties;
}
public static Properties getPropertiesFromFile(String location) {
final Properties properties = new Properties();
if (StringUtils.isNotBlank(location)) {
try {
properties.load(new FileInputStream(location));
} catch (Exception ex) {
LOG.warn("Unable to load properties from;" + location, ex);
}
}
return properties;
}
public static Properties getPropertiesFromEnvironment() {
final Properties properties = new Properties();
setAvailableSystemProperty(properties, PROXY_HOST, "proxyHost");
setAvailableSystemProperty(properties, PROXY_PORT, "proxyPort");
setAvailableSystemProperty(properties, TRAFFIC_PORT, "traffic");
setAvailableSystemProperty(properties, H2_ENABLED, "h2");
setAvailableSystemProperty(properties, PROXY_WORKERS, "proxyWorkers");
setAvailableSystemProperty(properties, FORWARD_NO_PROXY, "forwardNoProxy", "no_proxy");
setAvailableSystemProperty(properties, FORWARD_HTTPS_PROXY, "forwardHttpsProxy", "https_proxy");
setAvailableSystemProperty(properties, FORWARD_HTTP_PROXY, "forwardHttpProxy", "http_proxy");
return properties;
}
private static void setAvailableSystemProperty(Properties properties, String key, String... systemPropKeys) {
for (String systemPropKey : systemPropKeys) {
String value = System.getenv(systemPropKey);
if (StringUtils.isNotEmpty(value)) {
LOG.info("Setting property with key [{}] to [{}]", value);
properties.setProperty(key, value);
return;
}
}
}
}