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;
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;
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;
// 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
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;
}
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
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) {
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)
sb.append(" relativePath=" + HttpServerUtils.relativize(exchange));
exchange.getResponseBody().write(sb.toString().getBytes());
});
+ httpServer.start();
}
}
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;
* 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