Move Equinox specific code to the appropriate variant
[lgpl/argeo-commons.git] / osgi / equinox / org.argeo.cms.lib.equinox / src / org / argeo / cms / equinox / http / jetty / EquinoxJettyServer.java
diff --git a/osgi/equinox/org.argeo.cms.lib.equinox/src/org/argeo/cms/equinox/http/jetty/EquinoxJettyServer.java b/osgi/equinox/org.argeo.cms.lib.equinox/src/org/argeo/cms/equinox/http/jetty/EquinoxJettyServer.java
new file mode 100644 (file)
index 0000000..e6595a0
--- /dev/null
@@ -0,0 +1,151 @@
+package org.argeo.cms.equinox.http.jetty;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.argeo.cms.jetty.CmsJettyServer;
+import org.eclipse.equinox.http.servlet.HttpServiceServlet;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.osgi.framework.Constants;
+
+/** A {@link CmsJettyServer} integrating with Equinox HTTP framework. */
+public class EquinoxJettyServer extends CmsJettyServer {
+       private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
+
+       @Override
+       protected void addServlets(ServletContextHandler rootContextHandler) throws ServletException {
+               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$
+
+               rootContextHandler.addServlet(holder, "/*");
+
+               // post-start
+               SessionHandler sessionManager = rootContextHandler.getSessionHandler();
+               sessionManager.addEventListener((HttpSessionIdListener) holder.getServlet());
+       }
+
+       public static class InternalHttpServiceServlet implements HttpSessionListener, HttpSessionIdListener, Servlet {
+               private final Servlet httpServiceServlet = new HttpServiceServlet();
+               private ClassLoader contextLoader;
+               private final Method sessionDestroyed;
+               private final Method sessionIdChanged;
+
+               public InternalHttpServiceServlet() {
+                       Class<?> clazz = httpServiceServlet.getClass();
+
+                       try {
+                               sessionDestroyed = clazz.getMethod("sessionDestroyed", new Class<?>[] { String.class }); //$NON-NLS-1$
+                       } catch (Exception e) {
+                               throw new IllegalStateException(e);
+                       }
+                       try {
+                               sessionIdChanged = clazz.getMethod("sessionIdChanged", new Class<?>[] { String.class }); //$NON-NLS-1$
+                       } catch (Exception e) {
+                               throw new IllegalStateException(e);
+                       }
+               }
+
+               @Override
+               public void init(ServletConfig config) throws ServletException {
+                       ServletContext context = config.getServletContext();
+                       contextLoader = (ClassLoader) context.getAttribute(INTERNAL_CONTEXT_CLASSLOADER);
+
+                       Thread thread = Thread.currentThread();
+                       ClassLoader current = thread.getContextClassLoader();
+                       thread.setContextClassLoader(contextLoader);
+                       try {
+                               httpServiceServlet.init(config);
+                       } finally {
+                               thread.setContextClassLoader(current);
+                       }
+               }
+
+               @Override
+               public void destroy() {
+                       Thread thread = Thread.currentThread();
+                       ClassLoader current = thread.getContextClassLoader();
+                       thread.setContextClassLoader(contextLoader);
+                       try {
+                               httpServiceServlet.destroy();
+                       } finally {
+                               thread.setContextClassLoader(current);
+                       }
+                       contextLoader = null;
+               }
+
+               @Override
+               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);
+                       }
+               }
+
+               @Override
+               public ServletConfig getServletConfig() {
+                       return httpServiceServlet.getServletConfig();
+               }
+
+               @Override
+               public String getServletInfo() {
+                       return httpServiceServlet.getServletInfo();
+               }
+
+               @Override
+               public void sessionCreated(HttpSessionEvent event) {
+                       // Nothing to do.
+               }
+
+               @Override
+               public void sessionDestroyed(HttpSessionEvent event) {
+                       Thread thread = Thread.currentThread();
+                       ClassLoader current = thread.getContextClassLoader();
+                       thread.setContextClassLoader(contextLoader);
+                       try {
+                               sessionDestroyed.invoke(httpServiceServlet, event.getSession().getId());
+                       } catch (IllegalAccessException | IllegalArgumentException e) {
+                               // not likely
+                       } catch (InvocationTargetException e) {
+                               throw new RuntimeException(e.getCause());
+                       } finally {
+                               thread.setContextClassLoader(current);
+                       }
+               }
+
+               @Override
+               public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
+                       Thread thread = Thread.currentThread();
+                       ClassLoader current = thread.getContextClassLoader();
+                       thread.setContextClassLoader(contextLoader);
+                       try {
+                               sessionIdChanged.invoke(httpServiceServlet, oldSessionId);
+                       } catch (IllegalAccessException | IllegalArgumentException e) {
+                               // not likely
+                       } catch (InvocationTargetException e) {
+                               throw new RuntimeException(e.getCause());
+                       } finally {
+                               thread.setContextClassLoader(current);
+                       }
+               }
+       }
+
+}