From 213b9ca65d04a72d32047e5afc4d10cb1836ebe3 Mon Sep 17 00:00:00 2001 From: Jani Laakso Date: Tue, 16 Oct 2007 17:47:14 +0000 Subject: [PATCH] Added launchers for Hosted Mode (GWT java app), Desktop Mode (browser with control panel) and Standard Mode (browser only). svn changeset:2535/svn branch:trunk --- .../toolkit/launcher/BrowserLauncher.java | 92 +++++++++ .../toolkit/launcher/ITMillDesktopLaunch.java | 190 ++++++++++++++++++ .../toolkit/launcher/ITMillHostedLaunch.java | 57 ++++++ .../launcher/ITMillStandardLaunch.java | 142 +++++++++++++ 4 files changed, 481 insertions(+) create mode 100644 src/com/itmill/toolkit/launcher/BrowserLauncher.java create mode 100644 src/com/itmill/toolkit/launcher/ITMillDesktopLaunch.java create mode 100644 src/com/itmill/toolkit/launcher/ITMillHostedLaunch.java create mode 100644 src/com/itmill/toolkit/launcher/ITMillStandardLaunch.java diff --git a/src/com/itmill/toolkit/launcher/BrowserLauncher.java b/src/com/itmill/toolkit/launcher/BrowserLauncher.java new file mode 100644 index 0000000000..082f93e152 --- /dev/null +++ b/src/com/itmill/toolkit/launcher/BrowserLauncher.java @@ -0,0 +1,92 @@ +package com.itmill.toolkit.launcher; + +import java.io.IOException; + +/** + * This class opens default browser for ITMillDesktopLaunch class. Default + * browser is detected by the operating system. + * + */ +public class BrowserLauncher { + + /** + * Open browser on specified URL. + * + * @param url + */ + public static void openBrowser(String url) { + + Runtime runtime = Runtime.getRuntime(); + boolean started = false; + + String os = System.getProperty("os.name", "windows").toLowerCase(); + + // Linux + if (os.indexOf("linux") >= 0) { + + // Try x-www-browser + if (!started) { + try { + runtime.exec("x-www-browser " + url); + started = true; + } catch (IOException e) { + } + } + + // Try firefox + if (!started) { + try { + runtime.exec("firefox " + url); + started = true; + } catch (IOException e) { + } + } + + // Try mozilla + if (!started) { + try { + runtime.exec("mozilla " + url); + started = true; + } catch (IOException e) { + } + } + + // Try konqueror + if (!started) { + try { + runtime.exec("konqueror " + url); + started = true; + } catch (IOException e) { + } + } + } + + // OS X + if (os.indexOf("mac os x") >= 0) { + + // Try open + if (!started) { + try { + runtime.exec("open " + url); + started = true; + } catch (IOException e) { + } + } + } + + // Try cmd /start command on windows + if (os.indexOf("win") >= 0) { + if (!started) { + try { + runtime.exec("cmd /c start " + url); + started = true; + } catch (IOException e) { + } + } + } + + if (!started) + System.out.println("Failed to open browser. Please go to " + url); + } + +} diff --git a/src/com/itmill/toolkit/launcher/ITMillDesktopLaunch.java b/src/com/itmill/toolkit/launcher/ITMillDesktopLaunch.java new file mode 100644 index 0000000000..cb648e0339 --- /dev/null +++ b/src/com/itmill/toolkit/launcher/ITMillDesktopLaunch.java @@ -0,0 +1,190 @@ +package com.itmill.toolkit.launcher; + +import java.awt.FlowLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * This class starts servlet container and opens a simple control dialog. + * + */ +public class ITMillDesktopLaunch { + + public static void main(String[] args) { + + Map serverArgs = ITMillStandardLaunch.parseArguments(args); + boolean deployed = false; + try { + // Default deployment: embedded.war + deployed = deployEmbeddedWarfile(serverArgs); + } catch (IOException e1) { + e1.printStackTrace(); + deployed = false; + } + + // Check if deployment was succesful + if (!deployed && !serverArgs.containsKey("webroot")) { + // Default deployment failed, try other means + if (new File("WebContent").exists()) { + // Using WebContent directory as webroot + serverArgs.put("webroot", "WebContent"); + } else { + System.err.print("Failed to deploy Toolkit application. " + + "Please add --webroot parameter. Exiting."); + return; + } + } + + // Start the Winstone servlet container + String url = ITMillStandardLaunch.runServer(serverArgs); + + // Open browser into application URL + if (url != null) { + BrowserLauncher.openBrowser(url); + } + + // Open control dialog + if (url != null) { + openServerControlDialog(url); + } + + } + + /** + * Open a control dialog for embedded server. + * + * @param applicationUrl + * Application URL + */ + private static void openServerControlDialog(final String applicationUrl) { + + // Main frame + final String title = "Desktop Server"; + final JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + // Create link label and listen mouse click + final JLabel link = new JLabel("" + + "
Desktop Server is running at:
" + "" + applicationUrl + + "
Close this window to shutdown the server.
" + + ""); + link.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + BrowserLauncher.openBrowser(applicationUrl); + } + }); + + // Create a panel and add components to it. + final JPanel contentPane = new JPanel(new FlowLayout()); + frame.setContentPane(contentPane); + contentPane.add(link); + + // Close confirmation + final JLabel question = new JLabel( + "This will stop the server. Are you sure?"); + final JButton okButton = new JButton("OK"); + final JButton cancelButton = new JButton("Cancel"); + + // List for close verify buttons + ActionListener buttonListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == okButton) { + System.exit(0); + } else { + Rectangle bounds = frame.getBounds(); + frame.setTitle(title); + contentPane.removeAll(); + contentPane.add(link); + contentPane.setBounds(bounds); + frame.setBounds(bounds); + frame.setVisible(true); + frame.repaint(); + } + } + }; + okButton.addActionListener(buttonListener); + cancelButton.addActionListener(buttonListener); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + Rectangle bounds = frame.getBounds(); + frame.setTitle("Confirm close"); + contentPane.removeAll(); + contentPane.add(question); + contentPane.add(okButton); + contentPane.add(cancelButton); + frame.setBounds(bounds); + frame.setVisible(true); + frame.repaint(); + } + }); + + // Position the window nicely + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit() + .getScreenSize(); + int w = 270; + int h = 95; + int margin = 20; + frame.setBounds(new Rectangle(screenSize.width - w - margin, + screenSize.height - h - margin * 2, w, h)); + frame.toFront(); + frame.setVisible(true); + } + + /** + * Deploy file named "embedded.war" from classpath (inside jar file). + * + * @param args + * @return + * @throws IOException + */ + protected static boolean deployEmbeddedWarfile(Map args) throws IOException { + String embeddedWarfileName = "/embedded.war"; + InputStream embeddedWarfile = ITMillDesktopLaunch.class + .getResourceAsStream(embeddedWarfileName); + if (embeddedWarfile != null) { + File tempWarfile = File.createTempFile("embedded", ".war") + .getAbsoluteFile(); + tempWarfile.getParentFile().mkdirs(); + tempWarfile.deleteOnExit(); + + String embeddedWebroot = "winstoneEmbeddedWAR"; + File tempWebroot = new File(tempWarfile.getParentFile(), + embeddedWebroot); + tempWebroot.mkdirs(); + + OutputStream out = new FileOutputStream(tempWarfile, true); + int read = 0; + byte buffer[] = new byte[2048]; + while ((read = embeddedWarfile.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + out.close(); + embeddedWarfile.close(); + + args.put("warfile", tempWarfile.getAbsolutePath()); + args.put("webroot", tempWebroot.getAbsolutePath()); + args.remove("webappsDir"); + args.remove("hostsDir"); + return true; + } + return false; + } +} diff --git a/src/com/itmill/toolkit/launcher/ITMillHostedLaunch.java b/src/com/itmill/toolkit/launcher/ITMillHostedLaunch.java new file mode 100644 index 0000000000..a94c6f8df0 --- /dev/null +++ b/src/com/itmill/toolkit/launcher/ITMillHostedLaunch.java @@ -0,0 +1,57 @@ +package com.itmill.toolkit.launcher; + +import java.util.Map; + +import com.google.gwt.dev.GWTShell; + +/** + * Class for starting Google Web Toolkit (GWT) Hosted mode with without embedded + * tomcat (-noserver). Instead of tomcat we use external servlet container + * (Jetty). + * + * NOTE: you must edit Eclipse launcher and following parameters there. + * + * For program arguments: + * + * -noserver -out WebContent/ITMILL/widgetsets http://localhost:8080/ + * + * + * And for VM arguments: + * + * -XstartOnFirstThread -Xms256M -Xmx512M + * + * TODO: how to add *.launch files automatically when importing Eclipse + * workspace? + * + */ +public class ITMillHostedLaunch extends ITMillStandardLaunch { + + private final static String serverPort = "8080"; + + /** + * Main function for staring GWTShell and running Jetty. + * + * Command line Arguments are passed through to Jetty, see runServer method + * for options. + * + * @param args + */ + public static void main(String[] args) { + + // Pass-through of arguments for Jetty + Map serverArgs = parseArguments(args); + + String url = runServer(serverArgs); + + // Start GWTShell + + GWTShell.main(args); + + // Open browser into application URL + if (url != null) { + BrowserLauncher.openBrowser(url); + } + + } + +} diff --git a/src/com/itmill/toolkit/launcher/ITMillStandardLaunch.java b/src/com/itmill/toolkit/launcher/ITMillStandardLaunch.java new file mode 100644 index 0000000000..f53443fcc6 --- /dev/null +++ b/src/com/itmill/toolkit/launcher/ITMillStandardLaunch.java @@ -0,0 +1,142 @@ +package com.itmill.toolkit.launcher; + +import java.util.HashMap; +import java.util.Map; + +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.nio.SelectChannelConnector; +import org.mortbay.jetty.webapp.WebAppContext; +import org.mortbay.thread.BoundedThreadPool; + +/** + * Class for running Jetty servlet container within Eclipse project. + * + */ +public class ITMillStandardLaunch { + + private final static String serverPort = "8080"; + + /** + * Main function for running Jetty. + * + * Command line Arguments are passed through to Jetty, see runServer method + * for options. + * + * @param args + */ + public static void main(String[] args) { + + // Pass-through of arguments for Jetty + Map serverArgs = parseArguments(args); + + String url = runServer(serverArgs); + + // Open browser into application URL + if (url != null) { + BrowserLauncher.openBrowser(url); + } + + } + + /** + * Run the server with specified arguments. + * + * @param serverArgs + * @return + */ + protected static String runServer(Map serverArgs) { + + // Add help for System.out + System.out + .println("-------------------------------------------------\n" + + "Starting IT Mill Toolkit examples.\n" + + "Please go to http://localhost:" + + serverPort + + "\nif your web browser is not automatically started." + + "\n-------------------------------------------------\n"); + + // Assign default values for some arguments + assignDefault(serverArgs, "webroot", "WebContent"); + assignDefault(serverArgs, "httpPort", serverPort); + + try { + long started = System.currentTimeMillis(); + + Server server = new Server(); + + String threadPoolName = System.getProperty("jetty.threadpool.name", + "Jetty thread"); + int maxIdleTimeMs = Integer.getInteger( + "jetty.threadpool.maxIdleTimeMs", 60000); + int maxThreads = Integer.getInteger("jetty.threadpool.maxThreads", + 100); + int minThreads = Integer.getInteger("jetty.threadpool.minThreads", + 1); + int lowThreads = Integer.getInteger( + "jetty.threadpool.maxIdleTimeMs", 25); + BoundedThreadPool threadPool = new BoundedThreadPool(); + threadPool.setName(threadPoolName); + threadPool.setMaxIdleTimeMs(maxIdleTimeMs); + threadPool.setMaxThreads(maxThreads); + threadPool.setMinThreads(minThreads); + threadPool.setLowThreads(lowThreads); + server.setThreadPool(threadPool); + + Connector connector = new SelectChannelConnector(); + connector.setPort(Integer.valueOf(serverArgs.get("httpPort") + .toString())); + server.setConnectors(new Connector[] { connector }); + + WebAppContext webappcontext = new WebAppContext(); + webappcontext.setContextPath(""); + webappcontext.setWar(serverArgs.get("webroot").toString()); + + server.setHandler(webappcontext); + + server.start(); + System.err.println("Started Jetty in " + + (System.currentTimeMillis() - started) + "ms."); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + return "http://localhost:" + serverArgs.get("httpPort"); + } + + /** + * Assign default value for given key. + * + * @param map + * @param key + * @param value + */ + private static void assignDefault(Map map, String key, String value) { + if (!map.containsKey(key)) { + map.put(key, value); + } + } + + /** + * Parse all command line arguments into a map. + * + * Arguments format "key=value" are put into map. + * + * @param args + * @return map of arguments key value pairs. + */ + protected static Map parseArguments(String[] args) { + Map map = new HashMap(); + for (int i = 0; i < args.length; i++) { + int d = args[i].indexOf("="); + if (d > 0 && d < args[i].length() && args[i].startsWith("--")) { + String name = args[i].substring(2, d); + String value = args[i].substring(d + 1); + map.put(name, value); + } + } + return map; + } + +} -- 2.39.5