Introduce lightweight RWT runner.
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 3 May 2020 10:25:56 +0000 (12:25 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 3 May 2020 10:25:56 +0000 (12:25 +0200)
org.argeo.eclipse.ui.rap/bnd.bnd
org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/jetty/RwtRunner.java [new file with mode: 0644]

index fb50c88ef8ac0c659ade648dcdb097e6ba6b5fc3..f73a8d0196bac8b56f7e3fadceff674690418a55 100644 (file)
@@ -2,4 +2,10 @@ Import-Package: org.eclipse.swt,\
 org.eclipse.jface.dialogs,\
 org.argeo.eclipse.ui.util,\
 org.eclipse.swt.events,\
+org.eclipse.jetty.util.component;resolution:=optional,\
+org.eclipse.jetty.http;resolution:=optional,\
+org.eclipse.jetty.io;resolution:=optional,\
+org.eclipse.jetty.security;resolution:=optional,\
+org.eclipse.jetty.server.handler;resolution:=optional,\
+org.eclipse.jetty.*;resolution:=optional,\
 *
diff --git a/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/jetty/RwtRunner.java b/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/jetty/RwtRunner.java
new file mode 100644 (file)
index 0000000..29165a4
--- /dev/null
@@ -0,0 +1,135 @@
+package org.argeo.eclipse.ui.jetty;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.rap.rwt.application.AbstractEntryPoint;
+import org.eclipse.rap.rwt.application.ApplicationRunner;
+import org.eclipse.rap.rwt.engine.RWTServlet;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/** A minimal RWT runner based on embedded Jetty. */
+public class RwtRunner {
+
+       private final Server server;
+       private final ServerConnector serverConnector;
+       private Path tempDir;
+
+       public RwtRunner() {
+               server = new Server(new QueuedThreadPool(10, 1));
+               serverConnector = new ServerConnector(server);
+               serverConnector.setPort(0);
+               server.setConnectors(new Connector[] { serverConnector });
+       }
+
+       protected Control createUi(Composite parent, Object context) {
+               return new Label(parent, SWT.NONE);
+       }
+
+       public void init() {
+               ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+               context.setContextPath("/");
+               server.setHandler(context);
+
+               String entryPoint = "app";
+
+               // rwt-resources requires a file system
+               try {
+                       tempDir = Files.createTempDirectory("argeo-rwtRunner");
+                       context.setBaseResource(Resource.newResource(tempDir.resolve("www").toString()));
+               } catch (IOException e) {
+                       throw new IllegalStateException("Cannot create temporary directory", e);
+               }
+               context.addEventListener(new ServletContextListener() {
+                       ApplicationRunner applicationRunner;
+
+                       @Override
+                       public void contextInitialized(ServletContextEvent sce) {
+                               applicationRunner = new ApplicationRunner(
+                                               (application) -> application.addEntryPoint("/" + entryPoint, () -> new AbstractEntryPoint() {
+                                                       private static final long serialVersionUID = 5678385921969090733L;
+
+                                                       @Override
+                                                       protected void createContents(Composite parent) {
+                                                               createUi(parent, null);
+                                                       }
+                                               }, null), sce.getServletContext());
+                               applicationRunner.start();
+                       }
+
+                       @Override
+                       public void contextDestroyed(ServletContextEvent sce) {
+                               applicationRunner.stop();
+                       }
+               });
+
+               context.addServlet(new ServletHolder(new RWTServlet()), "/" + entryPoint);
+
+               // Required to serve rwt-resources. It is important that this is last.
+               ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
+               context.addServlet(holderPwd, "/");
+
+               try {
+                       server.start();
+               } catch (Exception e) {
+                       throw new IllegalStateException("Cannot start Jetty server", e);
+               }
+       }
+
+       public void destroy() {
+               try {
+                       serverConnector.close();
+                       server.stop();
+                       // TODO delete temp dir
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+
+       public Integer getEffectivePort() {
+               return serverConnector.getLocalPort();
+       }
+
+       public void waitFor() throws InterruptedException {
+               server.join();
+       }
+
+       public static void main(String[] args) throws Exception {
+               RwtRunner rwtRunner = new RwtRunner() {
+
+                       @Override
+                       protected Control createUi(Composite parent, Object context) {
+                               Label label = new Label(parent, SWT.NONE);
+                               label.setText("Hello world!");
+                               return label;
+                       }
+               };
+               rwtRunner.init();
+               Runtime.getRuntime().addShutdownHook(new Thread(() -> rwtRunner.destroy(), "Jetty shutdown"));
+
+               long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
+               System.out.println("App available in " + jvmUptime + " ms, on port " + rwtRunner.getEffectivePort());
+
+               // open browser in app mode
+               Thread.sleep(2000);// wait for RWT to be ready
+               Runtime.getRuntime().exec("google-chrome --app=http://localhost:" + rwtRunner.getEffectivePort() + "/app");
+
+               rwtRunner.waitFor();
+       }
+}