]> git.argeo.org Git - lgpl/argeo-commons.git/blob - jetty/EquinoxJettyServer.java
Prepare next development cycle
[lgpl/argeo-commons.git] / jetty / EquinoxJettyServer.java
1 package org.argeo.cms.equinox.http.jetty;
2
3 import java.io.IOException;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Method;
6
7 import javax.servlet.Servlet;
8 import javax.servlet.ServletConfig;
9 import javax.servlet.ServletContext;
10 import javax.servlet.ServletException;
11 import javax.servlet.ServletRequest;
12 import javax.servlet.ServletResponse;
13 import javax.servlet.http.HttpSessionEvent;
14 import javax.servlet.http.HttpSessionIdListener;
15 import javax.servlet.http.HttpSessionListener;
16
17 import org.argeo.api.cms.CmsLog;
18 import org.argeo.cms.jetty.CmsJettyServer;
19 import org.eclipse.equinox.http.servlet.HttpServiceServlet;
20 import org.eclipse.jetty.ee8.nested.SessionHandler;
21 import org.eclipse.jetty.ee8.servlet.ServletContextHandler;
22 import org.eclipse.jetty.ee8.servlet.ServletHolder;
23 import org.osgi.framework.Constants;
24
25 /** A {@link CmsJettyServer} integrating with Equinox HTTP framework. */
26 public class EquinoxJettyServer extends CmsJettyServer {
27 private final static CmsLog log = CmsLog.getLog(EquinoxJettyServer.class);
28 private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
29
30 @Override
31 protected void addServlets(ServletContextHandler rootContextHandler) throws ServletException {
32 ServletHolder holder = new ServletHolder(new InternalHttpServiceServlet());
33 holder.setInitOrder(0);
34 holder.setInitParameter(Constants.SERVICE_VENDOR, "Eclipse.org"); //$NON-NLS-1$
35 holder.setInitParameter(Constants.SERVICE_DESCRIPTION, "Equinox Jetty-based Http Service"); //$NON-NLS-1$
36
37 rootContextHandler.addServlet(holder, "/*");
38
39 // post-start
40 SessionHandler sessionManager = rootContextHandler.getSessionHandler();
41 sessionManager.addEventListener((HttpSessionIdListener) holder.getServlet());
42 }
43
44 public static class InternalHttpServiceServlet implements HttpSessionListener, HttpSessionIdListener, Servlet {
45 private final Servlet httpServiceServlet = new HttpServiceServlet();
46 private ClassLoader contextLoader;
47 private final Method sessionDestroyed;
48 private final Method sessionIdChanged;
49
50 public InternalHttpServiceServlet() {
51 Class<?> clazz = httpServiceServlet.getClass();
52
53 try {
54 sessionDestroyed = clazz.getMethod("sessionDestroyed", new Class<?>[] { String.class }); //$NON-NLS-1$
55 } catch (Exception e) {
56 throw new IllegalStateException(e);
57 }
58 try {
59 sessionIdChanged = clazz.getMethod("sessionIdChanged", new Class<?>[] { String.class }); //$NON-NLS-1$
60 } catch (Exception e) {
61 throw new IllegalStateException(e);
62 }
63 }
64
65 @Override
66 public void init(ServletConfig config) throws ServletException {
67 ServletContext context = config.getServletContext();
68 contextLoader = (ClassLoader) context.getAttribute(INTERNAL_CONTEXT_CLASSLOADER);
69
70 Thread thread = Thread.currentThread();
71 ClassLoader current = thread.getContextClassLoader();
72 thread.setContextClassLoader(contextLoader);
73 try {
74 httpServiceServlet.init(config);
75 } finally {
76 thread.setContextClassLoader(current);
77 }
78 }
79
80 @Override
81 public void destroy() {
82 Thread thread = Thread.currentThread();
83 ClassLoader current = thread.getContextClassLoader();
84 thread.setContextClassLoader(contextLoader);
85 try {
86 httpServiceServlet.destroy();
87 } finally {
88 thread.setContextClassLoader(current);
89 }
90 contextLoader = null;
91 }
92
93 @Override
94 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
95 Thread thread = Thread.currentThread();
96 ClassLoader current = thread.getContextClassLoader();
97 thread.setContextClassLoader(contextLoader);
98 try {
99 httpServiceServlet.service(req, res);
100 } catch (IllegalStateException e) {
101 // context is probably in shutdown
102 if (log.isTraceEnabled())
103 log.error("Cannot process request", e);
104 } finally {
105 thread.setContextClassLoader(current);
106 }
107 }
108
109 @Override
110 public ServletConfig getServletConfig() {
111 return httpServiceServlet.getServletConfig();
112 }
113
114 @Override
115 public String getServletInfo() {
116 return httpServiceServlet.getServletInfo();
117 }
118
119 @Override
120 public void sessionCreated(HttpSessionEvent event) {
121 // Nothing to do.
122 }
123
124 @Override
125 public void sessionDestroyed(HttpSessionEvent event) {
126 Thread thread = Thread.currentThread();
127 ClassLoader current = thread.getContextClassLoader();
128 thread.setContextClassLoader(contextLoader);
129 try {
130 sessionDestroyed.invoke(httpServiceServlet, event.getSession().getId());
131 } catch (IllegalAccessException | IllegalArgumentException e) {
132 // not likely
133 } catch (InvocationTargetException e) {
134 throw new RuntimeException(e.getCause());
135 } finally {
136 thread.setContextClassLoader(current);
137 }
138 }
139
140 @Override
141 public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
142 Thread thread = Thread.currentThread();
143 ClassLoader current = thread.getContextClassLoader();
144 thread.setContextClassLoader(contextLoader);
145 try {
146 sessionIdChanged.invoke(httpServiceServlet, oldSessionId);
147 } catch (IllegalAccessException | IllegalArgumentException e) {
148 // not likely
149 } catch (InvocationTargetException e) {
150 throw new RuntimeException(e.getCause());
151 } finally {
152 thread.setContextClassLoader(current);
153 }
154 }
155 }
156
157 }