--- /dev/null
+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();
+ }
+}