bucket.gitbucket_2.13.4.41.0.source-code.JettyLauncher Maven / Gradle / Ivy
The newest version!
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.SecuredRedirectHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.session.DefaultSessionCache;
import org.eclipse.jetty.server.session.FileSessionDataStore;
import org.eclipse.jetty.server.session.SessionCache;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
import java.io.File;
import java.net.InetAddress;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toSet;
public class JettyLauncher {
private interface Defaults {
String CONNECTORS = "http";
String HOST = "0.0.0.0";
int HTTP_PORT = 8080;
int HTTPS_PORT = 8443;
boolean REDIRECT_HTTPS = false;
}
private interface Connectors {
String HTTP = "http";
String HTTPS = "https";
}
public static void main(String[] args) throws Exception {
System.setProperty("java.awt.headless", "true");
String connectors = getEnvironmentVariable("gitbucket.connectors");
String host = getEnvironmentVariable("gitbucket.host");
String port = getEnvironmentVariable("gitbucket.port");
String securePort = getEnvironmentVariable("gitbucket.securePort");
String keyStorePath = getEnvironmentVariable("gitbucket.keyStorePath");
String keyStorePassword = getEnvironmentVariable("gitbucket.keyStorePassword");
String keyManagerPassword = getEnvironmentVariable("gitbucket.keyManagerPassword");
String redirectHttps = getEnvironmentVariable("gitbucket.redirectHttps");
String contextPath = getEnvironmentVariable("gitbucket.prefix");
String tmpDirPath = getEnvironmentVariable("gitbucket.tempDir");
String jettyIdleTimeout = getEnvironmentVariable("gitbucket.jettyIdleTimeout");
boolean saveSessions = false;
for(String arg: args) {
if (arg.equals("--save_sessions")) {
saveSessions = true;
}
if (arg.equals("--disable_news_feed")) {
System.setProperty("gitbucket.disableNewsFeed", "true");
}
if (arg.equals("--disable_cache")) {
System.setProperty("gitbucket.disableCache", "true");
}
if(arg.startsWith("--") && arg.contains("=")) {
String[] dim = arg.split("=", 2);
if(dim.length == 2) {
switch (dim[0]) {
case "--connectors":
connectors = dim[1];
break;
case "--host":
host = dim[1];
break;
case "--port":
port = dim[1];
break;
case "--secure_port":
securePort = dim[1];
break;
case "--key_store_path":
keyStorePath = dim[1];
break;
case "--key_store_password":
keyStorePassword = dim[1];
break;
case "--key_manager_password":
keyManagerPassword = dim[1];
break;
case "--redirect_https":
redirectHttps = dim[1];
break;
case "--prefix":
contextPath = dim[1];
break;
case "--gitbucket.home":
System.setProperty("gitbucket.home", dim[1]);
break;
case "--temp_dir":
tmpDirPath = dim[1];
break;
case "--plugin_dir":
System.setProperty("gitbucket.pluginDir", dim[1]);
break;
case "--jetty_idle_timeout":
jettyIdleTimeout = dim[1];
break;
}
}
}
}
if (contextPath != null && !contextPath.startsWith("/")) {
contextPath = "/" + contextPath;
}
final String hostName = InetAddress.getByName(fallback(host, Defaults.HOST)).getHostName();
final Server server = new Server();
final Set connectorsSet = Stream.of(fallback(connectors, Defaults.CONNECTORS)
.toLowerCase().split(",")).map(String::trim).collect(toSet());
final List connectorInstances = new ArrayList<>();
final HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.setSendServerVersion(false);
if (connectorsSet.contains(Connectors.HTTPS)) {
httpConfig.setSecurePort(fallback(securePort, Defaults.HTTPS_PORT, Integer::parseInt));
}
if (jettyIdleTimeout != null && jettyIdleTimeout.trim().length() != 0) {
httpConfig.setIdleTimeout(Long.parseLong(jettyIdleTimeout.trim()));
} else {
httpConfig.setIdleTimeout(300000L); // default is 5min
}
if (connectorsSet.contains(Connectors.HTTP)) {
final ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
connector.setHost(hostName);
connector.setPort(fallback(port, Defaults.HTTP_PORT, Integer::parseInt));
connectorInstances.add(connector);
}
if (connectorsSet.contains(Connectors.HTTPS)) {
final SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(requireNonNull(keyStorePath,
"You must specify a path to an SSL keystore via the --key_store_path command line argument" +
" or GITBUCKET_KEYSTOREPATH environment variable."));
sslContextFactory.setKeyStorePassword(requireNonNull(keyStorePassword,
"You must specify a an SSL keystore password via the --key_store_password argument" +
" or GITBUCKET_KEYSTOREPASSWORD environment variable."));
sslContextFactory.setKeyManagerPassword(requireNonNull(keyManagerPassword,
"You must specify a key manager password via the --key_manager_password' argument" +
" or GITBUCKET_KEYMANAGERPASSWORD environment variable."));
final HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
final ServerConnector connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(httpsConfig));
connector.setHost(hostName);
connector.setPort(fallback(securePort, Defaults.HTTPS_PORT, Integer::parseInt));
connectorInstances.add(connector);
}
require(!connectorInstances.isEmpty(),
"No server connectors could be configured, please check your --connectors command line argument" +
" or GITBUCKET_CONNECTORS environment variable.");
server.setConnectors(connectorInstances.toArray(new ServerConnector[0]));
WebAppContext context = new WebAppContext();
if(saveSessions) {
File sessDir = new File(getGitBucketHome(), "sessions");
if(!sessDir.exists()){
mkdir(sessDir);
}
SessionHandler sessions = context.getSessionHandler();
SessionCache cache = new DefaultSessionCache(sessions);
FileSessionDataStore fsds = new FileSessionDataStore();
fsds.setStoreDir(sessDir);
cache.setSessionDataStore(fsds);
sessions.setSessionCache(cache);
}
File tmpDir;
if(tmpDirPath == null || tmpDirPath.equals("")){
tmpDir = new File(getGitBucketHome(), "tmp");
if(!tmpDir.exists()){
mkdir(tmpDir);
}
} else {
tmpDir = new File(tmpDirPath);
if(!tmpDir.exists()){
throw new java.io.FileNotFoundException(
String.format("temp_dir \"%s\" not found", tmpDirPath));
} else if(!tmpDir.isDirectory()) {
throw new IllegalArgumentException(
String.format("temp_dir \"%s\" is not a directory", tmpDirPath));
}
}
context.setTempDirectory(tmpDir);
// Disabling the directory listing feature.
context.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
ProtectionDomain domain = JettyLauncher.class.getProtectionDomain();
URL location = domain.getCodeSource().getLocation();
context.setContextPath(contextPath == null ? "" : contextPath);
context.setDescriptor(location.toExternalForm() + "/WEB-INF/web.xml");
context.setServer(server);
context.setWar(location.toExternalForm());
final HandlerList handlers = new HandlerList();
if (fallback(redirectHttps, Defaults.REDIRECT_HTTPS, Boolean::parseBoolean)) {
handlers.addHandler(new SecuredRedirectHandler());
}
handlers.addHandler(addStatisticsHandler(context));
server.setHandler(handlers);
server.setStopAtShutdown(true);
server.setStopTimeout(7_000);
server.start();
server.join();
}
private static File getGitBucketHome(){
String home = System.getProperty("gitbucket.home");
if(home != null && home.length() > 0){
return new File(home);
}
home = System.getenv("GITBUCKET_HOME");
if(home != null && home.length() > 0){
return new File(home);
}
return new File(System.getProperty("user.home"), ".gitbucket");
}
private static String getEnvironmentVariable(String key){
String value = System.getenv(key.toUpperCase().replace('.', '_'));
if (value != null && value.length() == 0){
return null;
} else {
return value;
}
}
private static T fallback(R value, T defaultValue, Function converter) {
return value == null ? defaultValue : converter.apply(value);
}
private static T fallback(T value, T defaultValue) {
return fallback(value, defaultValue, identity());
}
private static void require(boolean condition, String message) {
if (!condition) {
throw new IllegalArgumentException(message);
}
}
private static T requireNonNull(T value, String message) {
require(value != null, message);
return value;
}
private static void mkdir(File dir) {
if (!dir.mkdirs()) {
throw new RuntimeException("Unable to create directory: " + dir);
}
}
private static Handler addStatisticsHandler(Handler handler) {
// The graceful shutdown is implemented via the statistics handler.
// See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142
final StatisticsHandler statisticsHandler = new StatisticsHandler();
statisticsHandler.setHandler(handler);
return statisticsHandler;
}
}