]> git.argeo.org Git - lgpl/argeo-commons.git/commitdiff
Servlet-independent handler support working
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 22 Sep 2024 07:40:18 +0000 (09:40 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 22 Sep 2024 07:40:18 +0000 (09:40 +0200)
org.argeo.cms.ee/bnd.bnd
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/AbstractJettyHttpContext.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/JettyHttpServer.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/ee10/CmsJettyServer.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/ee10/ServletHttpContext.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/ee8/CmsJavaxJettyServer.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/server/HttpContextJettyContextHandler.java
org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/server/JettyHttpContext.java
org.argeo.cms.lib.jetty/src/static-root/index.html [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/http/server/HttpServerUtils.java
osgi/equinox/org.argeo.cms.lib.equinox/src/org/argeo/cms/equinox/http/jetty/JavaxJettyServer.java

index adff33d30d7c7b9482841a0e336d4c080ed9c043..592abffdb45190c0581f543fabf9ff9acd5ea08e 100644 (file)
@@ -2,6 +2,7 @@ Import-Package:\
 org.osgi.service.http;version=0.0.0,\
 org.osgi.service.http.whiteboard;version=0.0.0,\
 org.osgi.framework.namespace;version=0.0.0,\
+org.eclipse.rap.service.http,\
 org.argeo.cms.osgi,\
 *
 
index 76336b11886208706d7f8b1f4a3b5ac70e073ab1..75b3c1a678697803ab78a4c6dcdf85198c623d78 100644 (file)
@@ -4,7 +4,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
-import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.Handler;
 
 import com.sun.net.httpserver.Authenticator;
 import com.sun.net.httpserver.Filter;
@@ -30,7 +30,7 @@ public abstract class AbstractJettyHttpContext extends HttpContext {
                this.path = path;
        }
 
-       protected abstract ContextHandler getJettyHandler();
+       protected abstract Handler getJettyHandler();
 
        @Override
        public HttpHandler getHandler() {
index b3ffe3ddb2874fb9c8f28a822c330822393e0268..24cc7d306f7b496a6d69498eb957b7017ffd9f58 100644 (file)
@@ -14,9 +14,9 @@ import org.argeo.api.cms.CmsLog;
 import org.argeo.api.cms.CmsState;
 import org.argeo.cms.CmsDeployProperty;
 import org.argeo.cms.http.server.HttpServerUtils;
-import org.argeo.cms.jetty.ee10.ContextHandlerHttpContext;
 import org.argeo.cms.jetty.server.JettyHttpContext;
 import org.eclipse.jetty.http.UriCompliance;
+import org.eclipse.jetty.http.pathmap.PathSpec;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.HttpConfiguration;
 import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -24,7 +24,11 @@ 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.ContextHandlerCollection;
+import org.eclipse.jetty.server.handler.PathMappingsHandler;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.resource.ResourceFactory;
+import org.eclipse.jetty.util.resource.Resources;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.ExecutorThreadPool;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -59,8 +63,10 @@ public class JettyHttpServer extends HttpsServer {
 
        private final Map<String, AbstractJettyHttpContext> contexts = new TreeMap<>();
 
-       private Handler rootContextHandler;
-       protected final ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
+       private Handler rootHandler;
+       // protected final ContextHandlerCollection contextHandlerCollection = new
+       // ContextHandlerCollection(true);
+       PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(true);
 
        private boolean started;
 
@@ -111,15 +117,30 @@ public class JettyHttpServer extends HttpsServer {
                        // holder
 
                        // context
-                       rootContextHandler = createRootContextHandler();
+                       rootHandler = createRootHandler();
                        // httpContext.addServlet(holder, "/*");
-                       if (rootContextHandler != null)
-                               configureRootContextHandler(rootContextHandler);
+                       if (rootHandler != null)
+                               configureRootHandler(rootHandler);
+
+//                     if (rootContextHandler != null && !contexts.containsKey("/"))
+//                             contextHandlerCollection.addHandler(rootContextHandler);
+//                     server.setHandler(contextHandlerCollection);
+                       if (rootHandler != null && !contexts.containsKey("/")) {
+                               pathMappingsHandler.addMapping(PathSpec.from("/"), rootHandler);
+                       } else {
+                               ResourceFactory resourceFactory = ResourceFactory.of(server);
+                               Resource rootResourceDir = resourceFactory.newClassLoaderResource("/static-root/");
+                               if (!Resources.isReadableDirectory(rootResourceDir))
+                                       throw new IllegalStateException("Unable to find root resource");
 
-                       if (rootContextHandler != null && !contexts.containsKey("/"))
-                               contextHandlerCollection.addHandler(rootContextHandler);
+                               ResourceHandler rootResourceHandler = new ResourceHandler();
+                               rootResourceHandler.setBaseResource(rootResourceDir);
+                               rootResourceHandler.setDirAllowed(false);
+                               rootResourceHandler.setWelcomeFiles("index.html");
 
-                       server.setHandler(contextHandlerCollection);
+                               pathMappingsHandler.addMapping(PathSpec.from("/"), rootResourceHandler);
+                       }
+                       server.setHandler(pathMappingsHandler);
 
                        //
                        // START
@@ -268,7 +289,19 @@ public class JettyHttpServer extends HttpsServer {
                AbstractJettyHttpContext httpContext = new JettyHttpContext(this, path);
                contexts.put(path, httpContext);
 
-               contextHandlerCollection.addHandler(httpContext.getJettyHandler());
+               Handler jettyHandler = httpContext.getJettyHandler();
+               // contextHandlerCollection.addHandler(httpContext.getJettyHandler());
+               // FIXME make path more robust
+               PathSpec pathSpec = PathSpec.from(path + "*");
+               pathMappingsHandler.addMapping(pathSpec, jettyHandler);
+               if (isStarted()) {
+                       // server is already started, handler has to be started explicitly
+                       try {
+                               jettyHandler.start();
+                       } catch (Exception e) {
+                               throw new IllegalStateException("Could not start dynamically added Jetty handler", e);
+                       }
+               }
                return httpContext;
        }
 
@@ -279,14 +312,23 @@ public class JettyHttpServer extends HttpsServer {
                if (!contexts.containsKey(path))
                        throw new IllegalArgumentException("Context " + path + " does not exist");
                AbstractJettyHttpContext httpContext = contexts.remove(path);
-               if (httpContext instanceof ContextHandlerHttpContext contextHandlerHttpContext) {
-                       // TODO stop handler first?
-                       // FIXME understand compatibility with Jetty 12
-                       // contextHandlerCollection.removeHandler(contextHandlerHttpContext.getServletContextHandler());
-               } else {
-                       // FIXME apparently servlets cannot be removed in Jetty, we should replace the
-                       // handler
+               Handler jettyHandler = httpContext.getJettyHandler();
+               if (jettyHandler.isStarted()) {
+                       try {
+                               jettyHandler.stop();
+                       } catch (Exception e) {
+                               log.error("Cannot stop Jetty handler " + path, e);
+                       }
                }
+
+//             if (httpContext instanceof ContextHandlerHttpContext contextHandlerHttpContext) {
+//                     // TODO stop handler first?
+//                     // FIXME understand compatibility with Jetty 12
+//                     // contextHandlerCollection.removeHandler(contextHandlerHttpContext.getServletContextHandler());
+//             } else {
+//                     // FIXME apparently servlets cannot be removed in Jetty, we should replace the
+//                     // handler
+//             }
        }
 
        @Override
@@ -342,17 +384,17 @@ public class JettyHttpServer extends HttpsServer {
                return httpsConnector.getLocalPort();
        }
 
-       protected Handler createRootContextHandler() {
+       protected Handler createRootHandler() {
                return null;
        }
 
-       protected void configureRootContextHandler(Handler servletContextHandler) {
+       protected void configureRootHandler(Handler jettyHandler) {
 
        }
 
        // TODO protect it?
-       public Handler getRootContextHandler() {
-               return rootContextHandler;
+       public Handler getRootHandler() {
+               return rootHandler;
        }
 
        public void setCmsState(CmsState cmsState) {
@@ -371,11 +413,11 @@ public class JettyHttpServer extends HttpsServer {
        public static void main(String... args) {
                JettyHttpServer httpServer = new JettyHttpServer();
                System.setProperty("argeo.http.port", "8080");
-               httpServer.createContext("/", (exchange) -> {
+
+               httpServer.createContext("/hello", (exchange) -> {
                        exchange.getResponseBody().write("Hello World!".getBytes());
                });
-               httpServer.start();
-               httpServer.createContext("/sub/context", (exchange) -> {
+               httpServer.createContext("/subcontext", (exchange) -> {
                        final String key = "count";
                        Integer count = (Integer) exchange.getHttpContext().getAttributes().get(key);
                        if (count == null)
@@ -388,5 +430,6 @@ public class JettyHttpServer extends HttpsServer {
                        sb.append(" relativePath=" + HttpServerUtils.relativize(exchange));
                        exchange.getResponseBody().write(sb.toString().getBytes());
                });
+               httpServer.start();
        }
 }
index aa373149657387353d6336e028b83e1c7f1c1a05..ca8e5d8d0d4fb14f38fba4022744ac075a56bbc4 100644 (file)
@@ -39,7 +39,7 @@ public class CmsJettyServer extends JettyHttpServer {
        }
 
        @Override
-       protected ServletContextHandler createRootContextHandler() {
+       protected ServletContextHandler createRootHandler() {
                ServletContextHandler servletContextHandler = new ServletContextHandler();
                servletContextHandler.setAttribute(INTERNAL_CONTEXT_CLASSLOADER,
                                Thread.currentThread().getContextClassLoader());
@@ -70,7 +70,7 @@ public class CmsJettyServer extends JettyHttpServer {
        }
 
        @Override
-       protected void configureRootContextHandler(Handler servletContextHandler) {
+       protected void configureRootHandler(Handler servletContextHandler) {
                addServlets((ServletContextHandler) servletContextHandler);
        }
 
index b8d6cf882be6f8b9af98dc1dfda3c3a811f532f1..d7bae5dfdd1be6a2c295c7017638437db13708a9 100644 (file)
@@ -30,7 +30,7 @@ public class ServletHttpContext extends AbstractJettyHttpContext {
        public ServletHttpContext(JettyHttpServer httpServer, String path) {
                super(httpServer, path);
 
-               ServletContextHandler rootContextHandler = (ServletContextHandler) httpServer.getRootContextHandler();
+               ServletContextHandler rootContextHandler = (ServletContextHandler) httpServer.getRootHandler();
                HttpContextServlet servlet = new HttpContextServlet(this);
                rootContextHandler.addServlet(new ServletHolder(servlet), path + "*");
        }
@@ -60,7 +60,7 @@ public class ServletHttpContext extends AbstractJettyHttpContext {
 
        @Override
        protected ServletContextHandler getJettyHandler() {
-               return (ServletContextHandler) getJettyHttpServer().getRootContextHandler();
+               return (ServletContextHandler) getJettyHttpServer().getRootHandler();
        }
 
 }
index b518877e6e21ef5a3337441aa7940ef0e472d958..9abc00d08d48e24d5404771e9565f09e98f6cc24 100644 (file)
@@ -42,7 +42,7 @@ public class CmsJavaxJettyServer extends JettyHttpServer {
        }
 
        @Override
-       protected Handler createRootContextHandler() {
+       protected Handler createRootHandler() {
                ServletContextHandler servletContextHandler = new ServletContextHandler();
                servletContextHandler.setAttribute(INTERNAL_CONTEXT_CLASSLOADER,
                                Thread.currentThread().getContextClassLoader());
@@ -74,7 +74,7 @@ public class CmsJavaxJettyServer extends JettyHttpServer {
 //     }
 
        @Override
-       protected void configureRootContextHandler(Handler servletContextHandler) {
+       protected void configureRootHandler(Handler servletContextHandler) {
                addServlets(rootContextHandler);
        }
 
index 5a768dd826a56673cea83cb8cfae4e65ac5e9584..26b33c640a01382d07c154f1dcc99badd0544e6f 100644 (file)
@@ -8,7 +8,8 @@ import com.sun.net.httpserver.HttpContext;
 class HttpContextJettyContextHandler extends ContextHandler {
 
        public HttpContextJettyContextHandler(HttpContext httpContext) {
-               super(new HttpContextJettyHandler(httpContext), httpContext.getPath());
+               // FIXME make path more robust
+               super(new HttpContextJettyHandler(httpContext), httpContext.getPath() + "/*");
        }
 
 }
index 92411835efee91640dff781fe76c13ebde673c01..e530c310a0385744881160c2dfdbefb5104400af 100644 (file)
@@ -1,10 +1,12 @@
 package org.argeo.cms.jetty.server;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import org.argeo.cms.jetty.AbstractJettyHttpContext;
 import org.argeo.cms.jetty.ContextHandlerAttributes;
 import org.argeo.cms.jetty.JettyHttpServer;
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.handler.ContextHandler;
 
 import com.sun.net.httpserver.HttpContext;
@@ -14,18 +16,26 @@ import com.sun.net.httpserver.HttpContext;
  * the jakarta/javax servlet APIs).
  */
 public class JettyHttpContext extends AbstractJettyHttpContext {
-       private final ContextHandler contextHandler;
-       private final ContextHandlerAttributes attributes;
+       private final Handler handler;
+       private Map<String, Object> attributes;
 
        public JettyHttpContext(JettyHttpServer httpServer, String path) {
                super(httpServer, path);
-               contextHandler = new HttpContextJettyContextHandler(this);
-               attributes = new ContextHandlerAttributes(contextHandler);
+               boolean useContextHandler = false;
+               if (useContextHandler) {
+                       // TODO not working yet
+                       // (sub contexts do not work)
+                       handler = new HttpContextJettyContextHandler(this);
+                       attributes = new ContextHandlerAttributes((ContextHandler) handler);
+               } else {
+                       handler = new HttpContextJettyHandler(this);
+                       attributes = new HashMap<>();
+               }
        }
 
        @Override
-       protected ContextHandler getJettyHandler() {
-               return contextHandler;
+       protected Handler getJettyHandler() {
+               return handler;
        }
 
        @Override
diff --git a/org.argeo.cms.lib.jetty/src/static-root/index.html b/org.argeo.cms.lib.jetty/src/static-root/index.html
new file mode 100644 (file)
index 0000000..e69de29
index 9d2c1930ae09e7cfd0f400553b5372054bca2508..e3def9d08771654f4fe483c4097636746caa4ec0 100644 (file)
@@ -31,7 +31,7 @@ public class HttpServerUtils {
                Objects.requireNonNull(fullPath);
                String contextPath = httpContext.getPath();
                if (!fullPath.startsWith(contextPath))
-                       throw new IllegalArgumentException(fullPath + " does not belong to context" + contextPath);
+                       throw new IllegalArgumentException(fullPath + " does not belong to context " + contextPath);
                String path = fullPath.substring(contextPath.length());
                // TODO optimise?
                if (!startWithSlash && path.startsWith(SLASH)) {
index afa61dec703f5a5f0028c3973c2969a8fee0829d..34fdd3e6311567fabae30e40ac24055d7c5bbacc 100644 (file)
@@ -17,7 +17,6 @@ import javax.servlet.http.HttpSessionListener;
 import org.argeo.api.cms.CmsLog;
 import org.argeo.cms.jetty.ee10.CmsJettyServer;
 import org.argeo.cms.jetty.ee8.CmsJavaxJettyServer;
-import org.eclipse.equinox.http.servlet.HttpServiceServlet;
 import org.eclipse.jetty.ee8.nested.SessionHandler;
 import org.eclipse.jetty.ee8.servlet.ServletContextHandler;
 import org.eclipse.jetty.ee8.servlet.ServletHolder;
@@ -47,7 +46,8 @@ public class JavaxJettyServer extends CmsJavaxJettyServer {
        }
 
        public static class InternalHttpServiceServlet implements HttpSessionListener, HttpSessionIdListener, Servlet {
-               private final Servlet httpServiceServlet = new HttpServiceServlet();
+               // FIXME dependency to equinox.http
+               private final Servlet httpServiceServlet = null;// = new HttpServiceServlet();
                private ClassLoader contextLoader;
                private final Method sessionDestroyed;
                private final Method sessionIdChanged;