Revision: 6283
Author: j...@google.com
Date: Thu Oct  1 17:01:51 2009
Log: Checkpoint work on abstracting out develmode UI.

http://code.google.com/p/google-web-toolkit/source/detail?r=6283

Added:
  /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/SwingUI.java
Deleted:
   
/changes/jat/abstractui/dev/core/src/com/google/gwt/dev/shell/BrowserWindowController.java
Modified:
  /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/HostedModeBase.java
  /changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java
   
/changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/HostedMode.java
   
/changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
  /changes/jat/abstractui/user/src/com/google/gwt/junit/JUnitShell.java

=======================================
--- /dev/null
+++ /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/SwingUI.java        
 
Thu Oct  1 17:01:51 2009
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.dev;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.TreeLogger.Type;
+import com.google.gwt.dev.HostedModeBase.DevelopmentModeUI;
+import com.google.gwt.dev.OophmHostedModeBase.TabPanelCollection;
+import com.google.gwt.dev.WebServerPanel.RestartAction;
+import com.google.gwt.dev.shell.ShellMainWindow;
+import com.google.gwt.dev.util.collect.HashMap;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.net.URL;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JTabbedPane;
+import javax.swing.WindowConstants;
+
+/**
+ * Implements the Swing UI for development mode.
+ */
+public class SwingUI extends DevelopmentModeUI {
+
+  private final Map<ModuleHandle, ModulePanel> moduleTabs = new  
IdentityHashMap<ModuleHandle, ModulePanel>();
+  private final Map<DevelModeTabKey, ModuleTabPanel> tabPanels = new  
HashMap<DevelModeTabKey, ModuleTabPanel>();
+
+  public class SwingModuleHandle implements ModuleHandle {
+
+    public TreeLogger getLogger() {
+      // TODO(jat) Auto-generated method stub
+      return null;
+    }
+
+  }
+
+  private final HostedModeBase hostedModeBase;
+  private JFrame frame;
+  private JTabbedPane tabs;
+  private ShellMainWindow mainWnd;
+  private WebServerPanel webServerLog;
+
+  public SwingUI(HostedModeBase hostedModeBase) {
+    this.hostedModeBase = hostedModeBase;
+  }
+
+  @Override
+  public void initialize() {
+    if (hostedModeBase.isHeadless()) {
+      return;
+    }
+    ImageIcon gwtIcon = loadImageIcon("icon24.png");
+    frame = new JFrame("GWT Development Mode");
+    tabs = new JTabbedPane();
+    if (hostedModeBase.options.alsoLogToFile()) {
+      hostedModeBase.options.getLogDir().mkdirs();
+    }
+    mainWnd = new ShellMainWindow(hostedModeBase.options.getLogLevel(),
+        hostedModeBase.options.getLogFile("main.log"));
+    tabs.addTab("Development Mode", gwtIcon, mainWnd, "GWT Development  
mode");
+    frame.getContentPane().add(tabs);
+    frame.setSize(950, 700);
+    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+    frame.addWindowListener(new WindowAdapter() {
+      @Override
+      public void windowClosed(WindowEvent e) {
+        callback(DONE, null);
+      }
+    });
+    frame.setIconImage(loadImageIcon("icon16.png").getImage());
+    frame.setVisible(true);
+  }
+
+  protected static final String PACKAGE_PATH = SwingUI.class.getPackage(
+      ).getName().replace('.', '/').concat("/shell/");
+
+  /**
+   * Loads an image from the classpath in this package.
+   */
+  static ImageIcon loadImageIcon(String name) {
+    return loadImageIcon(name, true);
+  }
+
+  /**
+   * Loads an image from the classpath, optionally prepending this package.
+   *
+   * @param name name of an image file.
+   * @param prependPackage true if {...@link #PACKAGE_PATH} should be  
prepended to
+   *          this name.
+   */
+  static ImageIcon loadImageIcon(String name, boolean prependPackage) {
+    ClassLoader cl = OophmHostedModeBase.class.getClassLoader();
+    if (prependPackage) {
+      name = PACKAGE_PATH + name;
+    }
+
+    URL url = (name == null) ? null : cl.getResource(name);
+    if (url != null) {
+      ImageIcon image = new ImageIcon(url);
+      return image;
+    } else {
+      // Bad image.
+      return new ImageIcon();
+    }
+  }
+
+  @Override
+  public TreeLogger getTopLogger(Type logLevel) {
+    return mainWnd == null ? null : mainWnd.getLogger();
+  }
+
+  @Override
+  public TreeLogger getWebServerLogger(String serverName, String iconName)  
{
+    if (webServerLog == null) {
+      webServerLog = new WebServerPanel(hostedModeBase.getPort(),
+          hostedModeBase.options.getLogLevel(),
+          hostedModeBase.options.getLogFile("webserver.log"),
+          new RestartAction() {
+            public void restartServer(TreeLogger logger) {
+              callback(RESTART_SERVER, logger);
+            }
+          });
+      Icon serverIcon = null;
+      tabs.insertTab(serverName, serverIcon, webServerLog, null, 1);
+    }
+    return webServerLog.getLogger();
+  }
+
+  @Override
+  public ModuleHandle loadModule(String userAgent, String remoteSocket,
+      String url, String tabKey, String moduleName, String sessionKey,
+      String agentTag, TreeLogger.Type logLevel) {
+    ModuleTabPanel tabPanel = null;
+    ModulePanel tab = null;
+    if (!hostedModeBase.isHeadless()) {
+      tabPanel = findModuleTab(userAgent, remoteSocket, url, tabKey,
+          moduleName);
+      tab = tabPanel.addModuleSession(logLevel, moduleName, sessionKey,
+          hostedModeBase.options.getLogFile(String.format("%s-%s-%d.log",  
moduleName,
+              agentTag, getNextSessionCounter(
+                  hostedModeBase.options.getLogDir()))));
+      TreeLogger logger = tab.getLogger();
+      TreeLogger branch = logger.branch(TreeLogger.INFO, "Loading module "
+          + moduleName);
+      if (url != null) {
+        branch.log(TreeLogger.INFO, "Top URL: " + url);
+      }
+      branch.log(TreeLogger.INFO, "User agent: " + userAgent);
+      branch.log(TreeLogger.TRACE, "Remote socket: " + remoteSocket);
+      if (tabKey != null) {
+        branch.log(TreeLogger.DEBUG, "Tab key: " + tabKey);
+      }
+      if (sessionKey != null) {
+        branch.log(TreeLogger.DEBUG, "Session key: " + sessionKey);
+      }
+
+      // TODO: Switch to a wait cursor?
+
+      SwingModuleHandle module = new SwingModuleHandle();
+      moduleTabs.put(module, tab);
+    }
+    return null;
+  }
+
+  private static int sessionCounter = 0;
+
+  protected int getNextSessionCounter(File logdir) {
+    if (sessionCounter == 0 && logdir != null) {
+      // first time only, figure out the "last" session count already in  
use
+      for (String filename : logdir.list()) {
+        if (filename.matches("^[A-Za-z0-9_$]*-[a-z]*-[0-9]*.log$")) {
+          String substring = filename.substring(filename.lastIndexOf('-')  
+ 1,
+              filename.length() - 4);
+          int number = Integer.parseInt(substring);
+          if (number > sessionCounter) {
+            sessionCounter = number;
+          }
+        }
+      }
+    }
+    return ++sessionCounter;
+  }
+
+  @Override
+  public void unloadModule(ModuleHandle module) {
+    SwingModuleHandle handle = (SwingModuleHandle) module;
+    Disconnectable tab = moduleTabs.remove(handle);
+    if (tab != null) {
+      tab.disconnect();
+    }
+  }
+
+  private ModuleTabPanel findModuleTab(String userAgent, String  
remoteSocket,
+      String url, String tabKey, String moduleName) {
+    int hostEnd = remoteSocket.indexOf(':');
+    if (hostEnd < 0) {
+      hostEnd = remoteSocket.length();
+    }
+    String remoteHost = remoteSocket.substring(0, hostEnd);
+    final DevelModeTabKey key = new DevelModeTabKey(userAgent, url, tabKey,
+        remoteHost);
+    ModuleTabPanel moduleTabPanel = tabPanels.get(key);
+    if (moduleTabPanel == null) {
+      moduleTabPanel = new ModuleTabPanel(userAgent, remoteSocket, url,
+          new TabPanelCollection() {
+            public void addTab(ModuleTabPanel tabPanel, ImageIcon icon,
+                String title, String tooltip) {
+              synchronized (tabs) {
+                tabs.addTab(title, icon, tabPanel, tooltip);
+                tabPanels.put(key, tabPanel);
+              }
+            }
+
+            public void removeTab(ModuleTabPanel tabPanel) {
+              synchronized (tabs) {
+                tabs.remove(tabPanel);
+                tabPanels.remove(key);
+              }
+            }
+          }, moduleName);
+    }
+    return moduleTabPanel;
+  }
+}
=======================================
---  
/changes/jat/abstractui/dev/core/src/com/google/gwt/dev/shell/BrowserWindowController.java
       
Sun Sep 20 12:33:31 2009
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
- * use this file except in compliance with the License. You may obtain a  
copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations  
under
- * the License.
- */
-package com.google.gwt.dev.shell;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
-/**
- * Interface to the browser window controller.
- */
-public interface BrowserWindowController {
-  /**
-   * Whether to display server control(s).
-   */
-  enum WebServerRestart {
-    DISABLED, ENABLED, NONE
-  }
-
-  void closeAllBrowserWindows();
-
-  boolean hasBrowserWindowsOpen();
-
-  WebServerRestart hasWebServer();
-
-  String normalizeURL(String string);
-
-  void restartServer(TreeLogger logger) throws UnableToCompleteException;
-}
=======================================
---  
/changes/jat/abstractui/dev/core/src/com/google/gwt/dev/HostedModeBase.java     
 
Sun Sep 20 13:03:25 2009
+++  
/changes/jat/abstractui/dev/core/src/com/google/gwt/dev/HostedModeBase.java     
 
Thu Oct  1 17:01:51 2009
@@ -17,17 +17,22 @@

  import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.TreeLogger.Type;
  import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.HostedModeBase.DevelopmentModeUI.ModuleHandle;
  import com.google.gwt.dev.Precompile.PrecompileOptionsImpl;
  import com.google.gwt.dev.cfg.ModuleDef;
  import com.google.gwt.dev.cfg.ModuleDefLoader;
  import com.google.gwt.dev.jjs.JJSOptions;
  import com.google.gwt.dev.shell.ArtifactAcceptor;
+import com.google.gwt.dev.shell.BrowserListener;
  import com.google.gwt.dev.shell.BrowserWidgetHost;
  import com.google.gwt.dev.shell.BrowserWidgetHostChecker;
-import com.google.gwt.dev.shell.BrowserWindowController;
  import com.google.gwt.dev.shell.CheckForUpdates;
+import com.google.gwt.dev.shell.ModuleSpaceHost;
+import com.google.gwt.dev.shell.OophmSessionHandler;
  import com.google.gwt.dev.shell.ShellModuleSpaceHost;
+import com.google.gwt.dev.util.BrowserInfo;
  import com.google.gwt.dev.util.Util;
  import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization;
  import com.google.gwt.dev.util.arg.ArgHandlerDisableCastChecking;
@@ -39,15 +44,22 @@
  import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
  import com.google.gwt.dev.util.arg.OptionGenDir;
  import com.google.gwt.dev.util.arg.OptionLogLevel;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
  import com.google.gwt.util.tools.ArgHandlerFlag;
  import com.google.gwt.util.tools.ArgHandlerString;

  import java.io.File;
+import java.io.PrintWriter;
  import java.util.ArrayList;
  import java.util.Collections;
+import java.util.HashMap;
  import java.util.HashSet;
+import java.util.IdentityHashMap;
  import java.util.List;
+import java.util.Map;
+import java.util.Random;
  import java.util.Set;
+import java.util.concurrent.Semaphore;

  /**
   * The main executable class for the hosted mode shell. This class must  
not have
@@ -56,7 +68,123 @@
   * TODO: remove BrowserWidget references (which reference SWT via  
inheritance,
   * though it doesn't appear to cause any harm currently.
   */
-abstract class HostedModeBase implements BrowserWindowController {
+abstract class HostedModeBase {
+
+  private final Map<ModuleSpaceHost, ModuleHandle> loadedModules = new  
IdentityHashMap<ModuleSpaceHost, ModuleHandle>();
+
+  public class UiBrowserWidgetHostImpl extends BrowserWidgetHostImpl {
+
+    private ModuleHandle module;
+
+    public ModuleSpaceHost createModuleSpaceHost(TreeLogger mainLogger,
+        String moduleName, String userAgent, String url, String tabKey,
+        String sessionKey, String remoteSocket)
+        throws UnableToCompleteException {
+      if (sessionKey == null) {
+        // if we don't have a unique session key, make one up
+        sessionKey = randomString();
+      }
+      TreeLogger logger = mainLogger;
+      TreeLogger.Type maxLevel = options.getLogLevel();
+      String agentTag = BrowserInfo.getShortName(userAgent).toLowerCase();
+      module = ui.loadModule(userAgent, remoteSocket, url, tabKey,  
moduleName,
+          sessionKey, agentTag, maxLevel);
+      logger = module.getLogger();
+      try {
+        // Try to find an existing loaded version of the module def.
+        ModuleDef moduleDef = loadModule(logger, moduleName, true);
+        assert (moduleDef != null);
+
+        // Create a sandbox for the module.
+        // TODO(jat): consider multiple instances of the same module open  
at
+        // once
+        TypeOracle typeOracle = moduleDef.getTypeOracle(logger);
+        ShellModuleSpaceHost host = doCreateShellModuleSpaceHost(logger,
+            typeOracle, moduleDef);
+
+        loadedModules.put(host, module);
+        return host;
+      } catch (RuntimeException e) {
+        logger.log(TreeLogger.ERROR, "Exception initializing module", e);
+        ui.unloadModule(module);
+        throw e;
+      }
+    }
+
+    public void unloadModule(ModuleSpaceHost moduleSpaceHost) {
+      ModuleHandle module = loadedModules.remove(moduleSpaceHost);
+      if (module != null) {
+        ui.unloadModule(module);
+      }
+    }
+
+  }
+
+  private static final Random RNG = new Random();
+
+  /**
+   * Produce a random string that has low probability of collisions.
+   *
+   * <p>In this case, we use 16 characters, each drawn from a pool of 94,
+   * so the number of possible values is 94^16, leading to an expected  
number
+   * of values used before a collision occurs as sqrt(pi/2) * 94^8  
(treated the
+   * same as a birthday attack), or a little under 10^16.
+   *
+   * <p>This algorithm is also implemented in hosted.html, though it is not
+   * technically important that they match.
+   *
+   * @return a random string
+   */
+  protected static String randomString() {
+    StringBuilder buf = new StringBuilder(16);
+    for (int i = 0; i < 16; ++i) {
+      buf.append((char) RNG.nextInt('~' - '!' + 1) + '!');
+    }
+    return buf.toString();
+  }
+
+  public abstract static class DevelopmentModeUI {
+
+    public static final String DONE = "done";
+    public static final String RESTART_SERVER = "restart-server";
+
+    public interface ModuleHandle {
+
+      TreeLogger getLogger();
+    }
+
+    public interface Callback {
+      // TODO: typesafe callbacks
+      public void callback(String event, Object callbackData);
+    }
+
+    private final Map<String, Callback> callbacks = new HashMap<String,  
Callback>();
+
+    public abstract void initialize();
+
+    public void setCallback(String event, Callback callback) {
+      callbacks.put(event, callback);
+    }
+
+    protected void callback(String event, Object callbackData) {
+      Callback callback = callbacks.get(event);
+      if (callback != null) {
+        callback(event, callbackData);
+      }
+    }
+
+    public abstract TreeLogger getTopLogger(TreeLogger.Type logLevel);
+
+    // TODO: How to pass icon?
+    public abstract TreeLogger getWebServerLogger(String serverName,
+        String iconName);
+
+    public abstract ModuleHandle loadModule(String userAgent,
+        String remoteSocket, String url, String tabKey, String moduleName,
+        String sessionKey, String agentTag, Type logLevel);
+
+    public abstract void unloadModule(ModuleHandle module);
+  }

    /**
     * Handles the -blacklist command line argument.
@@ -251,10 +379,64 @@
        return HostedModeBase.this.normalizeURL(whatTheUserTyped);
      }
    }
+
+
+  /**
+   * Handles the -portHosted command line flag.
+   */
+  protected static class ArgHandlerPortHosted extends ArgHandlerString {
+
+    private final OptionPortHosted options;
+
+    public ArgHandlerPortHosted(OptionPortHosted options) {
+      this.options = options;
+    }
+
+    @Override
+    public String[] getDefaultArgs() {
+      return new String[] {"-portHosted", "9997"};
+    }
+
+    @Override
+    public String getPurpose() {
+      return "Listens on the specified port for hosted mode connections";
+    }
+
+    @Override
+    public String getTag() {
+      return "-portHosted";
+    }
+
+    @Override
+    public String[] getTagArgs() {
+      return new String[] {"port-number | \"auto\""};
+    }
+
+    @Override
+    public boolean setString(String value) {
+      if (value.equals("auto")) {
+        options.setPortHosted(0);
+      } else {
+        try {
+          options.setPortHosted(Integer.parseInt(value));
+        } catch (NumberFormatException e) {
+          System.err.println("A port must be an integer or \"auto\"");
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+
+  protected interface OptionPortHosted {
+    int getPortHosted();
+
+    void setPortHosted(int portHosted);
+  }

    protected interface HostedModeBaseOptions extends JJSOptions,  
OptionLogDir,
        OptionLogLevel, OptionGenDir, OptionNoServer, OptionPort,
-      OptionStartupURLs {
+      OptionPortHosted, OptionStartupURLs {

      /**
       * The base shell work directory.
@@ -272,7 +454,15 @@
      private File logDir;
      private int port;
      private final List<String> startupURLs = new ArrayList<String>();
-
+    private int portHosted;
+
+    public int getPortHosted() {
+      return portHosted;
+    }
+
+    public void setPortHosted(int port) {
+      portHosted = port;
+    }
      public void addStartupURL(String url) {
        startupURLs.add(url);
      }
@@ -380,6 +570,7 @@
        registerHandler(new ArgHandlerDisableClassMetadata(options));
        registerHandler(new ArgHandlerDisableCastChecking(options));
        registerHandler(new ArgHandlerDraftCompile(options));
+      registerHandler(new ArgHandlerPortHosted(options));
      }
    }

@@ -416,8 +607,12 @@

    private boolean headlessMode = false;

+  private TreeLogger topLogger;
+
    private boolean started;

+  protected DevelopmentModeUI ui;
+
    public HostedModeBase() {
      // Set any platform specific system properties.
      BootStrapPlatform.initHostedMode();
@@ -428,16 +623,14 @@
    public final void addStartupURL(String url) {
      options.addStartupURL(url);
    }
-
-  public abstract void closeAllBrowserWindows();

    public final int getPort() {
      return options.getPort();
    }

-  public abstract TreeLogger getTopLogger();
-
-  public abstract boolean hasBrowserWindowsOpen();
+  public TreeLogger getTopLogger() {
+    return topLogger;
+  }

    /**
     * Launch the arguments as Urls in separate windows.
@@ -448,28 +641,53 @@
      return normalizeURL(unknownUrlText, getPort(), getHost());
    }

+  private final Semaphore blockUntilDone = new Semaphore(0);
+
    /**
     * Sets up all the major aspects of running the shell graphically,  
including
     * creating the main window and optionally starting the embedded Tomcat
     * server.
     */
    public final void run() {
+    if (ui == null) {
+      ui = new SwingUI(this);
+    }
      try {
        if (startUp()) {
          // Eager AWT init for OS X to ensure safe coexistence with SWT.
          BootStrapPlatform.initGui();

-        // Tomcat's running now, so launch browsers for startup urls now.
+        // The web server is running now, so launch browsers for startup  
urls.
          launchStartupUrls(getTopLogger());
        }

-      pumpEventLoop();
+      blockUntilDone.acquire();
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        shutDown();
      }
    }
+
+  protected final void setDone() {
+    blockUntilDone.release();
+  }
+
+  protected abstract void restartServer();
+
+  public class Callback implements DevelopmentModeUI.Callback {
+
+    public void callback(String event, Object callbackData) {
+      if (DevelopmentModeUI.DONE.equals(event)) {
+        setDone();
+        return;
+      } else if (DevelopmentModeUI.RESTART_SERVER.equals(event)) {
+        restartServer();
+        return;
+      }
+      // TODO: unexpected event?
+    }
+  }

    public final void setPort(int port) {
      options.setPort(port);
@@ -528,10 +746,9 @@

    protected boolean doStartup() {
      // Create the main app window.
-    openAppWindow();
+    ui.initialize();

      // Initialize the logger.
-    //
      initializeLogger();

      // Check for updates
@@ -549,8 +766,33 @@
        checkerThread.setDaemon(true);
        checkerThread.start();
      }
+
+    // Accept connections from OOPHM clients
+    ensureOophmListener();
+
      return true;
    }
+
+  protected int codeServerPort;
+
+  protected BrowserListener listener;
+
+  private BrowserWidgetHostImpl browserHost = new  
UiBrowserWidgetHostImpl();
+
+  protected void ensureOophmListener() {
+    if (listener == null) {
+      codeServerPort = options.getPortHosted();
+      listener = new BrowserListener(getTopLogger(), codeServerPort,
+          new OophmSessionHandler(browserHost));
+      listener.start();
+      try {
+        // save the port we actually used if it was auto
+        codeServerPort = listener.getSocketPort();
+      } catch (UnableToCompleteException e) {
+        // ignore errors listening, we will catch them later
+      }
+    }
+  }

    protected abstract int doStartUpServer();

@@ -558,7 +800,17 @@
      return "localhost";
    }

-  protected abstract void initializeLogger();
+  private void initializeLogger() {
+    Type logLevel = options.getLogLevel();
+    if (headlessMode) {
+      PrintWriterTreeLogger logger = new PrintWriterTreeLogger(
+          new PrintWriter(System.out));
+      logger.setMaxDetail(logLevel);
+      topLogger = logger;
+    } else {
+      topLogger = ui.getTopLogger(logLevel);
+    }
+  }

    /**
     * Called from a selection script as it begins to load in hosted mode.  
This
@@ -570,7 +822,15 @@
     *         will trigger a full-page refresh by the calling (out of date)
     *         selection script
     */
-  protected abstract boolean initModule(String moduleName);
+  protected boolean initModule(String moduleName) {
+    /*
+     * Not used in legacy mode due to GWTShellServlet playing this role.
+     *
+     * TODO: something smarter here and actually make GWTShellServlet less
+     * magic?
+     */
+    return false;
+  }

    /**
     * By default we will open the application window.
@@ -599,28 +859,6 @@
      assert (moduleDef != null) : "Required module state is absent";
      return moduleDef;
    }
-
-  protected abstract boolean notDone();
-
-  protected abstract void openAppWindow();
-
-  protected abstract void processEvents() throws Exception;
-
-  protected final void pumpEventLoop() {
-    TreeLogger logger = getTopLogger();
-
-    // Run the event loop. When there are no open shells, quit.
-    //
-    while (notDone()) {
-      try {
-        processEvents();
-      } catch (Throwable e) {
-        String msg = e.getMessage();
-        msg = (msg != null ? msg : e.getClass().getName());
-        logger.log(TreeLogger.ERROR, msg, e);
-      }
-    }
-  }

    protected final void setHeadless(boolean headlessMode) {
      this.headlessMode = headlessMode;
=======================================
---  
/changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java      
 
Wed Sep 23 11:22:27 2009
+++  
/changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java      
 
Thu Oct  1 17:01:51 2009
@@ -38,7 +38,7 @@
   */
  @SuppressWarnings("deprecation")
  @Deprecated
-public class GWTShell extends OophmHostedModeBase {
+public class GWTShell extends HostedModeBase {

    /**
     * Handles the list of startup urls that can be passed at the end of the
@@ -248,9 +248,10 @@

    @Override
    protected int doStartUpServer() {
+    TreeLogger logger = ui.getWebServerLogger("Tomcat", null);
      // TODO(bruce): make tomcat work in terms of the modular launcher
      String whyFailed = EmbeddedTomcatServer.start(isHeadless() ?  
getTopLogger()
-        : webServerLog.getLogger(), getPort(), options);
+        : logger, getPort(), options);

      if (whyFailed != null) {
        getTopLogger().log(TreeLogger.ERROR, "Starting Tomcat: " +  
whyFailed);
@@ -258,14 +259,4 @@
      }
      return EmbeddedTomcatServer.getPort();
    }
-
-  @Override
-  protected ImageIcon getWebServerIcon() {
-    return null;
-  }
-
-  @Override
-  protected String getWebServerName() {
-    return "Tomcat";
-  }
-}
+}
=======================================
---  
/changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/HostedMode.java    
 
Sat Aug 22 16:01:38 2009
+++  
/changes/jat/abstractui/dev/oophm/overlay/com/google/gwt/dev/HostedMode.java    
 
Thu Oct  1 17:01:51 2009
@@ -41,14 +41,12 @@
  import java.util.HashMap;
  import java.util.Map;

-import javax.swing.ImageIcon;
-
  /**
   * The main executable class for the hosted mode shell. NOTE: the public  
API for
   * this class is to be determined. Consider this class as having <b>no</b>
   * public API other than {...@link #main(String[])}.
   */
-public class HostedMode extends OophmHostedModeBase {
+public class HostedMode extends HostedModeBase {

    /**
     * Handles the -server command line flag.
@@ -165,7 +163,7 @@
      }
    }

-  interface HostedModeOptions extends OophmHostedModeBaseOptions,
+  interface HostedModeOptions extends HostedModeBaseOptions,
        CompilerOptions {
      ServletContainerLauncher getServletContainerLauncher();

@@ -175,7 +173,7 @@
    /**
     * Concrete class to implement all hosted mode options.
     */
-  static class HostedModeOptionsImpl extends OophmHostedModeBaseOptionsImpl
+  static class HostedModeOptionsImpl extends HostedModeBaseOptionsImpl
        implements HostedModeOptions {
      private File extraDir;
      private int localWorkers;
@@ -286,12 +284,7 @@
    HostedMode() {
    }

-  public WebServerRestart hasWebServer() {
-    return options.isNoServer() ? WebServerRestart.DISABLED
-        : WebServerRestart.ENABLED;
-  }
-
-  public void restartServer(TreeLogger logger) throws  
UnableToCompleteException {
+  protected void restartServer(TreeLogger logger) throws  
UnableToCompleteException {
      server.refresh();
    }

@@ -382,7 +375,7 @@
    @Override
    protected int doStartUpServer() {
      try {
-      TreeLogger serverLogger = webServerLog.getLogger();
+      TreeLogger serverLogger = ui.getWebServerLogger(getWebServerName(),  
null);
        serverLogger.log(TreeLogger.INFO, "Starting HTTP on port " +  
getPort(),
            null);
        server = options.getServletContainerLauncher().start(serverLogger,
@@ -408,13 +401,6 @@
      return super.getHost();
    }

-  @Override
-  protected ImageIcon getWebServerIcon() {
-    return  
loadImageIcon(options.getServletContainerLauncher().getIconPath(),
-        false);
-  }
-
-  @Override
    protected String getWebServerName() {
      return options.getServletContainerLauncher().getName();
    }
=======================================
---  
/changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
        
Sun Sep 20 13:03:25 2009
+++  
/changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
        
Thu Oct  1 17:01:51 2009
@@ -18,7 +18,6 @@
  import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.UnableToCompleteException;
  import com.google.gwt.core.ext.typeinfo.TypeOracle;
-import com.google.gwt.dev.WebServerPanel.RestartAction;
  import com.google.gwt.dev.cfg.ModuleDef;
  import com.google.gwt.dev.shell.BrowserListener;
  import com.google.gwt.dev.shell.BrowserWidgetHost;
@@ -29,14 +28,10 @@
  import com.google.gwt.dev.util.BrowserInfo;
  import com.google.gwt.dev.util.collect.HashMap;
  import com.google.gwt.dev.util.log.AbstractTreeLogger;
-import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
  import com.google.gwt.util.tools.ArgHandlerString;

  import java.awt.Cursor;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
  import java.io.File;
-import java.io.PrintWriter;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.IdentityHashMap;
@@ -46,7 +41,6 @@
  import javax.swing.ImageIcon;
  import javax.swing.JFrame;
  import javax.swing.JTabbedPane;
-import javax.swing.WindowConstants;

  /**
   * Base class for OOPHM hosted mode shells.
@@ -77,85 +71,6 @@
      void removeTab(ModuleTabPanel tabPanel);
    }

-  /**
-   * Handles the -portHosted command line flag.
-   */
-  protected static class ArgHandlerPortHosted extends ArgHandlerString {
-
-    private final OptionPortHosted options;
-
-    public ArgHandlerPortHosted(OptionPortHosted options) {
-      this.options = options;
-    }
-
-    @Override
-    public String[] getDefaultArgs() {
-      return new String[] {"-portHosted", "9997"};
-    }
-
-    @Override
-    public String getPurpose() {
-      return "Listens on the specified port for hosted mode connections";
-    }
-
-    @Override
-    public String getTag() {
-      return "-portHosted";
-    }
-
-    @Override
-    public String[] getTagArgs() {
-      return new String[] {"port-number | \"auto\""};
-    }
-
-    @Override
-    public boolean setString(String value) {
-      if (value.equals("auto")) {
-        options.setPortHosted(0);
-      } else {
-        try {
-          options.setPortHosted(Integer.parseInt(value));
-        } catch (NumberFormatException e) {
-          System.err.println("A port must be an integer or \"auto\"");
-          return false;
-        }
-      }
-      return true;
-    }
-  }
-
-  protected interface OptionPortHosted {
-    int getPortHosted();
-
-    void setPortHosted(int portHosted);
-  }
-
-  abstract static class ArgProcessor extends HostedModeBase.ArgProcessor {
-    public ArgProcessor(OophmHostedModeBaseOptions options, boolean  
forceServer) {
-      super(options, forceServer);
-      registerHandler(new ArgHandlerPortHosted(options));
-    }
-  }
-
-  interface OophmHostedModeBaseOptions extends HostedModeBaseOptions,
-      OptionPortHosted {
-  }
-
-  /**
-   * Concrete class to implement all shell options.
-   */
-  static class OophmHostedModeBaseOptionsImpl extends  
HostedModeBaseOptionsImpl
-      implements OophmHostedModeBaseOptions {
-    private int portHosted;
-
-    public int getPortHosted() {
-      return portHosted;
-    }
-
-    public void setPortHosted(int port) {
-      portHosted = port;
-    }
-  }

    private class OophmBrowserWidgetHostImpl extends BrowserWidgetHostImpl {
      private final Map<ModuleSpaceHost, ModulePanel> moduleTabs = new  
IdentityHashMap<ModuleSpaceHost, ModulePanel>();
@@ -234,111 +149,6 @@
          tab.disconnect();
        }
      }
-
-    private ModuleTabPanel findModuleTab(String userAgent, String  
remoteSocket,
-        String url, String tabKey, String moduleName) {
-      int hostEnd = remoteSocket.indexOf(':');
-      if (hostEnd < 0) {
-        hostEnd = remoteSocket.length();
-      }
-      String remoteHost = remoteSocket.substring(0, hostEnd);
-      final DevelModeTabKey key = new DevelModeTabKey(userAgent, url,  
tabKey,
-          remoteHost);
-      ModuleTabPanel moduleTabPanel = tabPanels.get(key);
-      if (moduleTabPanel == null) {
-        moduleTabPanel = new ModuleTabPanel(userAgent, remoteSocket, url,
-            new TabPanelCollection() {
-              public void addTab(ModuleTabPanel tabPanel, ImageIcon icon,
-                  String title, String tooltip) {
-                synchronized (tabs) {
-                  tabs.addTab(title, icon, tabPanel, tooltip);
-                  tabPanels.put(key, tabPanel);
-                }
-              }
-
-              public void removeTab(ModuleTabPanel tabPanel) {
-                synchronized (tabs) {
-                  tabs.remove(tabPanel);
-                  tabPanels.remove(key);
-                }
-              }
-            }, moduleName);
-      }
-      return moduleTabPanel;
-    }
-  }
-
-  protected static final String PACKAGE_PATH =  
OophmHostedModeBase.class.getPackage().getName().replace(
-      '.', '/').concat("/shell/");
-
-  private static final Random RNG = new Random();
-
-  private static int sessionCounter = 0;
-
-  /**
-   * Produce a random string that has low probability of collisions.
-   *
-   * <p>In this case, we use 16 characters, each drawn from a pool of 94,
-   * so the number of possible values is 94^16, leading to an expected  
number
-   * of values used before a collision occurs as sqrt(pi/2) * 94^8  
(treated the
-   * same as a birthday attack), or a little under 10^16.
-   *
-   * <p>This algorithm is also implemented in hosted.html, though it is not
-   * technically important that they match.
-   *
-   * @return a random string
-   */
-  protected static String randomString() {
-    StringBuilder buf = new StringBuilder(16);
-    for (int i = 0; i < 16; ++i) {
-      buf.append((char) RNG.nextInt('~' - '!' + 1) + '!');
-    }
-    return buf.toString();
-  }
-
-  /**
-   * Loads an image from the classpath in this package.
-   */
-  static ImageIcon loadImageIcon(String name) {
-    return loadImageIcon(name, true);
-  }
-
-  /**
-   * Loads an image from the classpath, optionally prepending this package.
-   *
-   * @param name name of an image file.
-   * @param prependPackage true if {...@link #PACKAGE_PATH} should be  
prepended to
-   *          this name.
-   */
-  static ImageIcon loadImageIcon(String name, boolean prependPackage) {
-    ClassLoader cl = OophmHostedModeBase.class.getClassLoader();
-    if (prependPackage) {
-      name = PACKAGE_PATH + name;
-    }
-
-    URL url = (name == null) ? null : cl.getResource(name);
-    if (url != null) {
-      ImageIcon image = new ImageIcon(url);
-      return image;
-    } else {
-      // Bad image.
-      return new ImageIcon();
-    }
-  }
-
-  protected int codeServerPort;
-
-  protected BrowserListener listener;
-
-  /**
-   * Hiding super field because it's actually the same object, just with a
-   * stronger type.
-   */
-  @SuppressWarnings("hiding")
-  protected final OophmHostedModeBaseOptionsImpl options =  
(OophmHostedModeBaseOptionsImpl) super.options;
-
-  // TODO(jat): clean up access to this field
-  protected WebServerPanel webServerLog;

    private BrowserWidgetHostImpl browserHost = new  
OophmBrowserWidgetHostImpl();

@@ -352,24 +162,6 @@

    private AbstractTreeLogger topLogger;

-  public OophmHostedModeBase() {
-    super();
-  }
-
-  @Override
-  public void closeAllBrowserWindows() {
-  }
-
-  @Override
-  public TreeLogger getTopLogger() {
-    return topLogger;
-  }
-
-  @Override
-  public boolean hasBrowserWindowsOpen() {
-    return false;
-  }
-
    /**
     * Launch the arguments as Urls in separate windows.
     */
@@ -430,61 +222,10 @@
    protected void compile(TreeLogger logger) throws  
UnableToCompleteException {
      throw new UnsupportedOperationException();
    }
-
-  @Override
-  protected boolean doStartup() {
-    if (super.doStartup()) {
-      // Accept connections from OOPHM clients
-      ensureOophmListener();
-      return true;
-    }
-    return false;
-  }

    protected final BrowserWidgetHost getBrowserHost() {
      return browserHost;
    }
-
-  protected int getNextSessionCounter(File logdir) {
-    if (sessionCounter == 0 && logdir != null) {
-      // first time only, figure out the "last" session count already in  
use
-      for (String filename : logdir.list()) {
-        if (filename.matches("^[A-Za-z0-9_$]*-[a-z]*-[0-9]*.log$")) {
-          String substring = filename.substring(filename.lastIndexOf('-')  
+ 1,
-              filename.length() - 4);
-          int number = Integer.parseInt(substring);
-          if (number > sessionCounter) {
-            sessionCounter = number;
-          }
-        }
-      }
-    }
-    return ++sessionCounter;
-  }
-
-  /**
-   * @return the icon to use for the web server tab
-   */
-  protected ImageIcon getWebServerIcon() {
-    return null;
-  }
-
-  /**
-   * @return the name of the web server tab
-   */
-  protected String getWebServerName() {
-    return "Server";
-  }
-
-  @Override
-  protected void initializeLogger() {
-    if (mainWnd != null) {
-      topLogger = mainWnd.getLogger();
-    } else {
-      topLogger = new PrintWriterTreeLogger(new PrintWriter(System.out));
-    }
-    topLogger.setMaxDetail(options.getLogLevel());
-  }

    @Override
    protected boolean initModule(String moduleName) {
@@ -496,57 +237,6 @@
       */
      return false;
    }
-
-  @Override
-  protected synchronized boolean notDone() {
-    return !mainWindowClosed;
-  }
-
-  @Override
-  protected void openAppWindow() {
-    if (isHeadless()) {
-      return;
-    }
-    ImageIcon gwtIcon = loadImageIcon("icon24.png");
-    frame = new JFrame("GWT Development Mode");
-    tabs = new JTabbedPane();
-    if (options.alsoLogToFile()) {
-      options.getLogDir().mkdirs();
-    }
-    mainWnd = new ShellMainWindow(options.getLogLevel(),
-        options.getLogFile("main.log"));
-    tabs.addTab("Development Mode", gwtIcon, mainWnd, "GWT Development  
mode");
-    if (!options.isNoServer()) {
-      webServerLog = new WebServerPanel(getPort(), options.getLogLevel(),
-          options.getLogFile("webserver.log"),
-          new RestartAction() {
-            public void restartServer(TreeLogger logger) {
-              try {
-                OophmHostedModeBase.this.restartServer(logger);
-              } catch (UnableToCompleteException e) {
-                // Already logged why it failed
-              }
-            }
-          });
-      tabs.addTab(getWebServerName(), getWebServerIcon(), webServerLog);
-    }
-    frame.getContentPane().add(tabs);
-    frame.setSize(950, 700);
-    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-    frame.addWindowListener(new WindowAdapter() {
-      @Override
-      public void windowClosed(WindowEvent e) {
-        setMainWindowClosed();
-      }
-    });
-    frame.setIconImage(loadImageIcon("icon16.png").getImage());
-    frame.setVisible(true);
-  }
-
-  @Override
-  protected void processEvents() throws Exception {
-    Thread.sleep(10);
-  }

    protected synchronized void setMainWindowClosed() {
      mainWindowClosed = true;
=======================================
--- /changes/jat/abstractui/user/src/com/google/gwt/junit/JUnitShell.java       
 
Wed Sep 30 17:53:07 2009
+++ /changes/jat/abstractui/user/src/com/google/gwt/junit/JUnitShell.java       
 
Thu Oct  1 17:01:51 2009
@@ -396,34 +396,19 @@
     * @return the list of remote user agents
     */
    public static String[] getRemoteUserAgents() {
-    if (unitTestShell == null) {
-      return null;
-    }
-    return unitTestShell.remoteUserAgents;
+    return getUnitTestShell().remoteUserAgents;
    }

    /**
     * Checks if a testCase should not be executed. Currently, a test is  
either
     * executed on all clients (mentioned in this test) or on no clients.
     *
-   * @param testInfo the test info to check
+   * @param testCase current testCase.
     * @return true iff the test should not be executed on any of the  
specified
     *         clients.
     */
-  public static boolean mustNotExecuteTest(TestInfo testInfo) {
-    if (unitTestShell == null) {
-      throw new IllegalStateException(
-          "mustNotExecuteTest cannot be called before runTest()");
-    }
-    try {
-      Class<?> testClass = TestCase.class.getClassLoader().loadClass(
-          testInfo.getTestClass());
-      return unitTestShell.mustNotExecuteTest(getBannedPlatforms(testClass,
-          testInfo.getTestMethod()));
-    } catch (ClassNotFoundException e) {
-      throw new IllegalArgumentException("Could not load test class: "
-          + testInfo.getTestClass());
-    }
+  public static boolean mustNotExecuteTest(TestCase testCase) {
+    return  
getUnitTestShell().mustNotExecuteTest(getBannedPlatforms(testCase));
    }

    /**
@@ -503,19 +488,16 @@
    }

    /**
-   * Returns the set of banned {...@code Platform} for a test method.
-   *
-   * @param testClass the testClass
-   * @param methodName the name of the test method
+   * returns the set of banned {...@code Platform} for a test method.
     */
-  private static Set<Platform> getBannedPlatforms(Class<?> testClass,
-      String methodName) {
+  private static Set<Platform> getBannedPlatforms(TestCase testCase) {
+    Class<?> testClass = testCase.getClass();
      Set<Platform> bannedSet = EnumSet.noneOf(Platform.class);
      if (testClass.isAnnotationPresent(DoNotRunWith.class)) {
         
bannedSet.addAll(Arrays.asList(testClass.getAnnotation(DoNotRunWith.class).value()));
      }
      try {
-      Method testMethod = testClass.getMethod(methodName);
+      Method testMethod = testClass.getMethod(testCase.getName());
        if (testMethod.isAnnotationPresent(DoNotRunWith.class)) {
          bannedSet.addAll(Arrays.asList(testMethod.getAnnotation(
              DoNotRunWith.class).value()));
@@ -554,10 +536,6 @@
        // TODO: install a shutdown hook? Not necessary with GWTShell.
        unitTestShell.lastLaunchFailed = false;
      }
-    if (unitTestShell.thread != Thread.currentThread()) {
-      throw new IllegalThreadStateException(
-          "JUnitShell can only be accessed from the thread that created  
it.");
-    }

      return unitTestShell;
    }
@@ -662,17 +640,11 @@
     */
    private long testMethodTimeout;

-  /**
-   * The thread that created the JUnitShell.
-   */
-  private Thread thread;
-
    /**
     * Enforce the singleton pattern. The call to {...@link GWTShell}'s ctor  
forces
     * server mode and disables processing extra arguments as URLs to be  
shown.
     */
    private JUnitShell() {
-    thread = Thread.currentThread();
      setRunTomcat(true);
      setHeadless(true);
    }
@@ -692,15 +664,6 @@
        throw new RuntimeException("Unable to determine my ip address", e);
      }
    }
-
-  @Override
-  public TreeLogger getTopLogger() {
-    if (consoleLogger != null) {
-      return consoleLogger;
-    } else {
-      return super.getTopLogger();
-    }
-  }

    /**
     * Check for updates once a minute.
@@ -724,16 +687,6 @@
      }
      return true;
    }
-
-  @Override
-  protected void initializeLogger() {
-    if (isHeadless()) {
-      consoleLogger = new PrintWriterTreeLogger();
-      consoleLogger.setMaxDetail(options.getLogLevel());
-    } else {
-      super.initializeLogger();
-    }
-  }

    /**
     * Overrides {...@link GWTShell#notDone()} to wait for the  
currently-running test
@@ -928,8 +881,7 @@
    private void runTestImpl(GWTTestCase testCase, TestResult testResult)
        throws UnableToCompleteException {

-    if (mustNotExecuteTest(getBannedPlatforms(testCase.getClass(),
-        testCase.getName()))) {
+    if (mustNotExecuteTest(testCase)) {
        return;
      }


--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to