Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/HttpServerManager.java')
-rw-r--r--bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/HttpServerManager.java331
1 files changed, 331 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/HttpServerManager.java b/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/HttpServerManager.java
new file mode 100644
index 000000000..8929003b4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/HttpServerManager.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Red Hat, Inc. - Jetty 9 adoption.
+ * Raymond Augé - bug fixes and enhancements
+ *******************************************************************************/
+
+package org.eclipse.equinox.http.jetty.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import javax.servlet.*;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionIdListener;
+import org.eclipse.equinox.http.jetty.JettyConstants;
+import org.eclipse.equinox.http.jetty.JettyCustomizer;
+import org.eclipse.equinox.http.servlet.HttpServiceServlet;
+import org.eclipse.jetty.server.*;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+public class HttpServerManager implements ManagedServiceFactory {
+
+ private static final int DEFAULT_IDLE_TIMEOUT = 30000;
+ private static final String CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; //$NON-NLS-1$
+ private static final String DIR_PREFIX = "pid_"; //$NON-NLS-1$
+ private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader"; //$NON-NLS-1$
+
+ private Map<String, Server> servers = new HashMap<String, Server>();
+ private File workDir;
+
+ public HttpServerManager(File workDir) {
+ this.workDir = workDir;
+ }
+
+ public synchronized void deleted(String pid) {
+ Server server = servers.remove(pid);
+ if (server != null) {
+ try {
+ server.stop();
+ } catch (Exception e) {
+ // TODO: consider logging this, but we should still continue cleaning up
+ e.printStackTrace();
+ }
+ File contextWorkDir = new File(workDir, DIR_PREFIX + pid.hashCode());
+ deleteDirectory(contextWorkDir);
+ }
+ }
+
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void updated(String pid, @SuppressWarnings("rawtypes") Dictionary dictionary) throws ConfigurationException {
+ deleted(pid);
+ Server server = new Server(new QueuedThreadPool(Details.getInt(dictionary, JettyConstants.HTTP_MAXTHREADS, 200), Details.getInt(dictionary, JettyConstants.HTTP_MINTHREADS, 8)));
+
+ JettyCustomizer customizer = createJettyCustomizer(dictionary);
+
+ /**
+ * May be modified by createHttp(s)Connector.
+ */
+ HttpConfiguration http_config = new HttpConfiguration();
+
+ ServerConnector httpConnector = createHttpConnector(dictionary, server, http_config);
+
+ ServerConnector httpsConnector = createHttpsConnector(dictionary, server, http_config);
+
+ if (null != customizer)
+ httpConnector = (ServerConnector) customizer.customizeHttpConnector(httpConnector, dictionary);
+
+ if (httpConnector != null) {
+ try {
+ httpConnector.open();
+ } catch (IOException e) {
+ throw new ConfigurationException(pid, e.getMessage(), e);
+ }
+ server.addConnector(httpConnector);
+ }
+
+ if (null != customizer)
+ httpsConnector = (ServerConnector) customizer.customizeHttpsConnector(httpsConnector, dictionary);
+
+ if (httpsConnector != null) {
+ try {
+ httpsConnector.open();
+ } catch (IOException e) {
+ throw new ConfigurationException(pid, e.getMessage(), e);
+ }
+ server.addConnector(httpsConnector);
+ }
+
+ ServletHolder holder = new ServletHolder(new InternalHttpServiceServlet());
+ holder.setInitOrder(0);
+ holder.setInitParameter(Constants.SERVICE_VENDOR, "Eclipse.org"); //$NON-NLS-1$
+ holder.setInitParameter(Constants.SERVICE_DESCRIPTION, "Equinox Jetty-based Http Service"); //$NON-NLS-1$
+
+ String multipartServletName = "Equinox Jetty-based Http Service - Multipart Servlet"; //$NON-NLS-1$
+
+ holder.setInitParameter("multipart.servlet.name", multipartServletName); //$NON-NLS-1$
+
+ if (httpConnector != null) {
+ int port = httpConnector.getLocalPort();
+ if (port == -1)
+ port = httpConnector.getPort();
+ holder.setInitParameter(JettyConstants.HTTP_PORT, Integer.toString(port));
+ }
+ if (httpsConnector != null) {
+ int port = httpsConnector.getLocalPort();
+ if (port == -1)
+ port = httpsConnector.getPort();
+ holder.setInitParameter(JettyConstants.HTTPS_PORT, Integer.toString(port));
+ }
+ String otherInfo = Details.getString(dictionary, JettyConstants.OTHER_INFO, null);
+ if (otherInfo != null)
+ holder.setInitParameter(JettyConstants.OTHER_INFO, otherInfo);
+
+ ServletContextHandler httpContext = createHttpContext(dictionary);
+ httpContext.addServlet(holder, "/*"); //$NON-NLS-1$
+ server.setHandler(httpContext);
+
+ if (null != customizer)
+ httpContext = (ServletContextHandler) customizer.customizeContext(httpContext, dictionary);
+
+ SessionHandler sessionManager = httpContext.getSessionHandler();
+ try {
+ sessionManager.addEventListener((HttpSessionIdListener) holder.getServlet());
+ } catch (ServletException e) {
+ throw new ConfigurationException(pid, e.getMessage(), e);
+ }
+
+ try {
+ server.start();
+ } catch (Exception e) {
+ throw new ConfigurationException(pid, e.getMessage(), e);
+ }
+ servers.put(pid, server);
+ }
+
+ private ServerConnector createHttpsConnector(@SuppressWarnings("rawtypes") Dictionary dictionary, Server server, HttpConfiguration http_config) {
+ ServerConnector httpsConnector = null;
+ if (Details.getBoolean(dictionary, JettyConstants.HTTPS_ENABLED, false)) {
+ // SSL Context Factory for HTTPS and SPDY
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ //sslContextFactory.setKeyStore(KeyS)
+
+ //Not sure if the next tree are properly migrated from jetty 8...
+ sslContextFactory.setKeyStorePath(Details.getString(dictionary, JettyConstants.SSL_KEYSTORE, null));
+ sslContextFactory.setKeyStorePassword(Details.getString(dictionary, JettyConstants.SSL_PASSWORD, null));
+ sslContextFactory.setKeyManagerPassword(Details.getString(dictionary, JettyConstants.SSL_KEYPASSWORD, null));
+ sslContextFactory.setKeyStoreType(Details.getString(dictionary, JettyConstants.SSL_KEYSTORETYPE, "JKS")); //$NON-NLS-1$
+ sslContextFactory.setProtocol(Details.getString(dictionary, JettyConstants.SSL_PROTOCOL, "TLS")); //$NON-NLS-1$
+ sslContextFactory.setWantClientAuth(Details.getBoolean(dictionary, JettyConstants.SSL_WANTCLIENTAUTH, false));
+ sslContextFactory.setNeedClientAuth(Details.getBoolean(dictionary, JettyConstants.SSL_NEEDCLIENTAUTH, false));
+
+ // HTTPS Configuration
+ HttpConfiguration https_config = new HttpConfiguration(http_config);
+ https_config.addCustomizer(new SecureRequestCustomizer());
+
+ // HTTPS connector
+ httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(https_config)); //$NON-NLS-1$
+ httpsConnector.setPort(Details.getInt(dictionary, JettyConstants.HTTPS_PORT, 443));
+ }
+ return httpsConnector;
+ }
+
+ private ServerConnector createHttpConnector(@SuppressWarnings("rawtypes") Dictionary dictionary, Server server, HttpConfiguration http_config) {
+ ServerConnector httpConnector = null;
+ if (Details.getBoolean(dictionary, JettyConstants.HTTP_ENABLED, true)) {
+ // HTTP Configuration
+ if (Details.getBoolean(dictionary, JettyConstants.HTTPS_ENABLED, false)) {
+ http_config.setSecureScheme("https"); //$NON-NLS-1$
+ http_config.setSecurePort(Details.getInt(dictionary, JettyConstants.HTTPS_PORT, 443));
+ }
+ // HTTP connector
+ httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config));
+ httpConnector.setPort(Details.getInt(dictionary, JettyConstants.HTTP_PORT, 80));
+ httpConnector.setHost(Details.getString(dictionary, JettyConstants.HTTP_HOST, null));
+ httpConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
+ }
+ return httpConnector;
+ }
+
+ public synchronized void shutdown() throws Exception {
+ for (Iterator<Server> it = servers.values().iterator(); it.hasNext();) {
+ Server server = it.next();
+ server.stop();
+ }
+ servers.clear();
+ }
+
+ private ServletContextHandler createHttpContext(@SuppressWarnings("rawtypes") Dictionary dictionary) {
+ ServletContextHandler httpContext = new ServletContextHandler();
+ // hack in the mime type for xsd until jetty fixes it (bug 393218)
+ httpContext.getMimeTypes().addMimeMapping("xsd", "application/xml"); //$NON-NLS-1$ //$NON-NLS-2$
+ httpContext.setAttribute(INTERNAL_CONTEXT_CLASSLOADER, Thread.currentThread().getContextClassLoader());
+ httpContext.setClassLoader(this.getClass().getClassLoader());
+ httpContext.setContextPath(Details.getString(dictionary, JettyConstants.CONTEXT_PATH, "/")); //$NON-NLS-1$
+
+ File contextWorkDir = new File(workDir, DIR_PREFIX + dictionary.get(Constants.SERVICE_PID).hashCode());
+ contextWorkDir.mkdir();
+ httpContext.setAttribute(CONTEXT_TEMPDIR, contextWorkDir);
+ SessionHandler handler = new SessionHandler();
+ handler.setMaxInactiveInterval(Details.getInt(dictionary, JettyConstants.CONTEXT_SESSIONINACTIVEINTERVAL, -1));
+ httpContext.setSessionHandler(handler);
+
+ return httpContext;
+ }
+
+ private JettyCustomizer createJettyCustomizer(@SuppressWarnings("rawtypes") Dictionary dictionary) {
+ String customizerClass = (String) dictionary.get(JettyConstants.CUSTOMIZER_CLASS);
+ if (null == customizerClass)
+ return null;
+
+ try {
+ return (JettyCustomizer) Class.forName(customizerClass).newInstance();
+ } catch (Exception e) {
+ // TODO: consider logging this, but we should still continue
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static class InternalHttpServiceServlet implements HttpSessionIdListener, Servlet {
+ // private static final long serialVersionUID = 7477982882399972088L;
+ private Servlet httpServiceServlet = new HttpServiceServlet();
+ private ClassLoader contextLoader;
+ private Method method;
+
+ public void init(ServletConfig config) throws ServletException {
+ ServletContext context = config.getServletContext();
+ contextLoader = (ClassLoader) context.getAttribute(INTERNAL_CONTEXT_CLASSLOADER);
+
+ Class<?> clazz = httpServiceServlet.getClass();
+ try {
+ method = clazz.getMethod("sessionIdChanged", new Class<?>[] {String.class}); //$NON-NLS-1$
+ } catch (Exception e) {
+ throw new ServletException(e);
+ }
+
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.init(config);
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+
+ public void destroy() {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.destroy();
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ contextLoader = null;
+ }
+
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.service(req, res);
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+
+ public ServletConfig getServletConfig() {
+ return httpServiceServlet.getServletConfig();
+ }
+
+ public String getServletInfo() {
+ return httpServiceServlet.getServletInfo();
+ }
+
+ public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ method.invoke(httpServiceServlet, oldSessionId);
+ } catch (IllegalAccessException e) {
+ // not likely
+ } catch (IllegalArgumentException e) {
+ // not likely
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+ }
+
+ // deleteDirectory is a convenience method to recursively delete a directory
+ private static boolean deleteDirectory(File directory) {
+ if (directory.exists() && directory.isDirectory()) {
+ File[] files = directory.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ deleteDirectory(files[i]);
+ } else {
+ files[i].delete();
+ }
+ }
+ }
+ return directory.delete();
+ }
+
+}

Back to the top