blob: 5c8b1f8df4fd73cb50f82df1a0625c2c9152c0c4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.minifi.c2.jetty;
import org.apache.nifi.minifi.c2.api.properties.C2Properties;
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.HandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class JettyServer {
private static final Logger logger = LoggerFactory.getLogger(JettyServer.class);
private static String C2_SERVER_HOME = System.getenv("C2_SERVER_HOME");
private static final String WEB_DEFAULTS_XML = "webdefault.xml";
public static void main(String[] args) throws Exception {
C2Properties properties = C2Properties.getInstance();
final HandlerCollection handlers = new HandlerCollection();
for (Path path : Files.list(Paths.get(C2_SERVER_HOME, "webapps")).collect(Collectors.toList())) {
handlers.addHandler(loadWar(path.toFile(), "/c2", JettyServer.class.getClassLoader()));
}
Server server;
int port = Integer.parseInt(properties.getProperty("minifi.c2.server.port", "10080"));
SslContextFactory sslContextFactory = properties.getSslContextFactory();
if (sslContextFactory == null) {
server = new Server(port);
} else {
HttpConfiguration config = new HttpConfiguration();
config.setSecureScheme("https");
config.setSecurePort(port);
config.addCustomizer(new SecureRequestCustomizer());
server = new Server();
ServerConnector serverConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(config));
serverConnector.setPort(port);
server.addConnector(serverConnector);
}
server.setHandler(handlers);
server.start();
// ensure everything started successfully
for (Handler handler : server.getChildHandlers()) {
// see if the handler is a web app
if (handler instanceof WebAppContext) {
WebAppContext context = (WebAppContext) handler;
// see if this webapp had any exceptions that would
// cause it to be unavailable
if (context.getUnavailableException() != null) {
System.err.println("Failed to start web server: " + context.getUnavailableException().getMessage());
System.err.println("Shutting down...");
logger.warn("Failed to start web server... shutting down.", context.getUnavailableException());
server.stop();
System.exit(1);
}
}
}
server.dumpStdErr();
server.join();
}
private static WebAppContext loadWar(final File warFile, final String contextPath, final ClassLoader parentClassLoader) throws IOException {
final WebAppContext webappContext = new WebAppContext(warFile.getPath(), contextPath);
webappContext.setContextPath(contextPath);
webappContext.setDisplayName(contextPath);
// instruction jetty to examine these jars for tlds, web-fragments, etc
webappContext.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\\\.jar$|.*/[^/]*taglibs.*\\.jar$" );
// remove slf4j server class to allow WAR files to have slf4j dependencies in WEB-INF/lib
List<String> serverClasses = new ArrayList<>(Arrays.asList(webappContext.getServerClasses()));
serverClasses.remove("org.slf4j.");
webappContext.setServerClasses(serverClasses.toArray(new String[0]));
webappContext.setDefaultsDescriptor(WEB_DEFAULTS_XML);
// get the temp directory for this webapp
File tempDir = Paths.get(C2_SERVER_HOME, "tmp", warFile.getName()).toFile();
if (tempDir.exists() && !tempDir.isDirectory()) {
throw new RuntimeException(tempDir.getAbsolutePath() + " is not a directory");
} else if (!tempDir.exists()) {
final boolean made = tempDir.mkdirs();
if (!made) {
throw new RuntimeException(tempDir.getAbsolutePath() + " could not be created");
}
}
if (!(tempDir.canRead() && tempDir.canWrite())) {
throw new RuntimeException(tempDir.getAbsolutePath() + " directory does not have read/write privilege");
}
// configure the temp dir
webappContext.setTempDirectory(tempDir);
// configure the max form size (3x the default)
webappContext.setMaxFormContentSize(600000);
webappContext.setClassLoader(new WebAppClassLoader(parentClassLoader, webappContext));
logger.info("Loading WAR: " + warFile.getAbsolutePath() + " with context path set to " + contextPath);
return webappContext;
}
}