Revision: 7027
Author: j...@google.com
Date: Thu Nov 19 12:24:42 2009
Log: Rearrange how module logging is handled.

Patch by: jat
Review by: rdayal

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

Added:
  /trunk/dev/core/src/com/google/gwt/dev/ModuleHandle.java
Modified:
  /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java
  /trunk/dev/core/src/com/google/gwt/dev/HeadlessUI.java
  /trunk/dev/core/src/com/google/gwt/dev/SwingUI.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
  /trunk/dev/core/src/com/google/gwt/dev/shell/remoteui/RemoteUI.java
  /trunk/dev/core/src/com/google/gwt/dev/ui/CloseModuleCallback.java
  /trunk/dev/core/src/com/google/gwt/dev/ui/DevModeUI.java
  /trunk/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java

=======================================
--- /dev/null
+++ /trunk/dev/core/src/com/google/gwt/dev/ModuleHandle.java    Thu Nov 19  
12:24:42 2009
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * Opaque handle to a module instance - external code can only get a  
logger or
+ * notify the module handle it is no longer needed.
+ */
+public interface ModuleHandle {
+
+  /**
+   * @return the logger for this module.
+   */
+  TreeLogger getLogger();
+
+  /**
+   * Mark the module instance associated with this handle as unloaded.
+   */
+  void unload();
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java     Wed Nov 18  
15:02:16 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java     Thu Nov 19  
12:24:42 2009
@@ -17,7 +17,6 @@

  import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.TreeLogger.HelpInfo;
  import com.google.gwt.core.ext.linker.ArtifactSet;
  import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
  import com.google.gwt.dev.Precompile.PrecompileOptionsImpl;
@@ -38,7 +37,6 @@
  import com.google.gwt.dev.ui.DevModeUI;
  import com.google.gwt.dev.ui.DoneCallback;
  import com.google.gwt.dev.ui.DoneEvent;
-import com.google.gwt.dev.ui.DevModeUI.ModuleHandle;
  import com.google.gwt.dev.util.BrowserInfo;
  import com.google.gwt.dev.util.Util;
  import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
@@ -57,7 +55,6 @@
  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;
@@ -77,22 +74,25 @@
     */
    public class UiBrowserWidgetHostImpl implements BrowserWidgetHost {

-    public ModuleSpaceHost createModuleSpaceHost(TreeLogger mainLogger,
-        String moduleName, String userAgent, String url, String tabKey,
-        String sessionKey, BrowserChannelServer serverChannel,
-        byte[] userAgentIcon) throws UnableToCompleteException {
+    public ModuleHandle createModuleLogger(String moduleName, String  
userAgent,
+        String url, String tabKey, String sessionKey,
+        BrowserChannelServer serverChannel, byte[] userAgentIcon) {
        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);
        String remoteSocket = serverChannel.getRemoteEndpoint();
-      ModuleHandle module = ui.loadModule(userAgent, remoteSocket, url,  
tabKey,
-          moduleName, sessionKey, agentTag, userAgentIcon, maxLevel);
+      ModuleHandle module = ui.getModuleLogger(userAgent, remoteSocket,  
url,
+          tabKey, moduleName, sessionKey, agentTag, userAgentIcon,  
maxLevel);
+      return module;
+    }
+
+    public ModuleSpaceHost createModuleSpaceHost(ModuleHandle module,
+        String moduleName) throws UnableToCompleteException {
        // TODO(jat): add support for closing an active module
-      logger = module.getLogger();
+      TreeLogger logger = module.getLogger();
        try {
          // Try to find an existing loaded version of the module def.
          ModuleDef moduleDef = loadModule(logger, moduleName, true);
@@ -102,26 +102,13 @@

          ShellModuleSpaceHost host = doCreateShellModuleSpaceHost(logger,
              moduleDef.getCompilationState(logger), moduleDef);
-
-        loadedModules.put(host, module);
          return host;
        } catch (RuntimeException e) {
          logger.log(TreeLogger.ERROR, "Exception initializing module", e);
-        ui.unloadModule(module);
+        module.unload();
          throw e;
        }
      }
-
-    public TreeLogger getLogger() {
-      return getTopLogger();
-    }
-
-    public void unloadModule(ModuleSpaceHost moduleSpaceHost) {
-      ModuleHandle module = loadedModules.remove(moduleSpaceHost);
-      if (module != null) {
-        ui.unloadModule(module);
-      }
-    }
    }

    /**
@@ -589,7 +576,8 @@

    private static final AtomicLong uniqueId = new AtomicLong();

-  public static String normalizeURL(String unknownUrlText, int port,  
String host) {
+  public static String normalizeURL(String unknownUrlText, int port,
+      String host) {
      if (unknownUrlText.indexOf(":") != -1) {
        // Assume it's a full url.
        return unknownUrlText;
@@ -676,8 +664,6 @@

    private boolean headlessMode = false;

-  private final Map<ModuleSpaceHost, ModuleHandle> loadedModules = new  
IdentityHashMap<ModuleSpaceHost, ModuleHandle>();
-
    private boolean started;

    private TreeLogger topLogger;
@@ -709,16 +695,19 @@
    public void launchStartupUrls(final TreeLogger logger) {
      ensureCodeServerListener();
      String startupURL = "";
-    try {
-      for (String prenormalized : options.getStartupURLs()) {
-        startupURL = normalizeURL(prenormalized, getPort(), getHost());
-        logger.log(TreeLogger.TRACE, "Starting URL: " + startupURL, null);
-        launchURL(startupURL);
-      }
-    } catch (UnableToCompleteException e) {
-      logger.log(TreeLogger.ERROR,
-          "Unable to open new window for startup URL: " + startupURL,  
null);
-    }
+    Map<String, URL> startupUrls = new HashMap<String, URL>();
+    for (String prenormalized : options.getStartupURLs()) {
+      startupURL = normalizeURL(prenormalized, getPort(), getHost());
+      logger.log(TreeLogger.TRACE, "Starting URL: " + startupURL, null);
+      try {
+        URL url = processUrl(startupURL);
+        startupUrls.put(prenormalized, url);
+      } catch (UnableToCompleteException e) {
+        logger.log(TreeLogger.ERROR,
+            "Unable to process startup URL " + startupURL, null);
+      }
+    }
+    ui.setStartupUrls(startupUrls);
    }

    /**
@@ -737,7 +726,7 @@
        // Eager AWT init for OS X to ensure safe coexistence with SWT.
        BootStrapPlatform.initGui();

-      if (startUp() && !options.useRemoteUI()) {
+      if (startUp()) {
          // The web server is running now, so launch browsers for startup  
urls.
          launchStartupUrls(getTopLogger());
        }
@@ -838,7 +827,7 @@
      if (listener == null) {
        codeServerPort = options.getCodeServerPort();
        listener = new BrowserListener(getTopLogger(), codeServerPort,
-          new OophmSessionHandler(browserHost));
+          new OophmSessionHandler(getTopLogger(), browserHost));
        listener.start();
        try {
          // save the port we actually used if it was auto
@@ -861,55 +850,6 @@
    protected final boolean isHeadless() {
      return headlessMode;
    }
-
-  protected void launchURL(String url) throws UnableToCompleteException {
-    /*
-     * TODO(jat): properly support launching arbitrary browsers -- need  
some UI
-     * API tweaks to support that.
-     */
-    URL parsedUrl = null;
-    try {
-      parsedUrl = new URL(url);
-      String path = parsedUrl.getPath();
-      String query = parsedUrl.getQuery();
-      String hash = parsedUrl.getRef();
-      String hostedParam =  
BrowserListener.getDevModeURLParams(listener.getEndpointIdentifier());
-      if (query == null) {
-        query = hostedParam;
-      } else {
-        query += '&' + hostedParam;
-      }
-      path += '?' + query;
-      if (hash != null) {
-        path += '#' + hash;
-      }
-      parsedUrl = new URL(parsedUrl.getProtocol(), parsedUrl.getHost(),
-          parsedUrl.getPort(), path);
-      url = parsedUrl.toExternalForm();
-    } catch (MalformedURLException e) {
-      getTopLogger().log(TreeLogger.ERROR, "Invalid URL " + url, e);
-      throw new UnableToCompleteException();
-    }
-
-    final URL helpInfoUrl = parsedUrl;
-    getTopLogger().log(TreeLogger.INFO,
-        "Waiting for browser connection to " + url, null, new HelpInfo() {
-          @Override
-          public String getAnchorText() {
-            return "Launch default browser";
-          }
-
-          @Override
-          public String getPrefix() {
-            return "";
-          }
-
-          @Override
-          public URL getURL() {
-            return helpInfoUrl;
-          }
-        });
-  }

    /**
     * Perform an initial hosted mode link, without overwriting newer or
@@ -950,6 +890,37 @@
      assert (moduleDef != null) : "Required module state is absent";
      return moduleDef;
    }
+
+  protected URL processUrl(String url) throws UnableToCompleteException {
+    /*
+     * TODO(jat): properly support launching arbitrary browsers -- need  
some UI
+     * API tweaks to support that.
+     */
+    URL parsedUrl = null;
+    try {
+      parsedUrl = new URL(url);
+      String path = parsedUrl.getPath();
+      String query = parsedUrl.getQuery();
+      String hash = parsedUrl.getRef();
+      String hostedParam =  
BrowserListener.getDevModeURLParams(listener.getEndpointIdentifier());
+      if (query == null) {
+        query = hostedParam;
+      } else {
+        query += '&' + hostedParam;
+      }
+      path += '?' + query;
+      if (hash != null) {
+        path += '#' + hash;
+      }
+      parsedUrl = new URL(parsedUrl.getProtocol(), parsedUrl.getHost(),
+          parsedUrl.getPort(), path);
+      url = parsedUrl.toExternalForm();
+    } catch (MalformedURLException e) {
+      getTopLogger().log(TreeLogger.ERROR, "Invalid URL " + url, e);
+      throw new UnableToCompleteException();
+    }
+    return parsedUrl;
+  }

    protected abstract void produceOutput(TreeLogger logger,
        StandardLinkerContext linkerStack, ArtifactSet artifacts, ModuleDef  
module)
@@ -990,8 +961,8 @@
          return false;
        }
        options.setPort(resultPort);
-      getTopLogger().log(TreeLogger.TRACE,
-          "Started web server on port " + resultPort);
+      getTopLogger().log(TreeLogger.TRACE, "Started web server on port "
+          + resultPort);
      }

      return true;
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/HeadlessUI.java      Fri Oct 16  
20:22:17 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/HeadlessUI.java      Thu Nov 19  
12:24:42 2009
@@ -34,17 +34,16 @@
    }

    @Override
-  public ModuleHandle loadModule(String userAgent, String remoteSocket,
+  public ModuleHandle getModuleLogger(String userAgent, String  
remoteSocket,
        String url, String tabKey, String moduleName, String sessionKey,
        String agentTag, byte[] agentIcon, Type logLevel) {
      return new ModuleHandle() {
        public TreeLogger getLogger() {
          return getConsoleLogger();
        }
-    };
-  }
-
-  @Override
-  public void unloadModule(ModuleHandle module) {
+
+      public void unload() {
+      }
+    };
    }
  }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/SwingUI.java Wed Nov 18 08:54:53  
2009
+++ /trunk/dev/core/src/com/google/gwt/dev/SwingUI.java Thu Nov 19 12:24:42  
2009
@@ -16,6 +16,7 @@
  package com.google.gwt.dev;

  import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.TreeLogger.HelpInfo;
  import com.google.gwt.core.ext.TreeLogger.Type;
  import com.google.gwt.dev.DevModeBase.HostedModeBaseOptions;
  import com.google.gwt.dev.WebServerPanel.RestartAction;
@@ -35,6 +36,7 @@
  import java.lang.reflect.Method;
  import java.net.URL;
  import java.util.ArrayList;
+import java.util.Collections;
  import java.util.List;
  import java.util.Map;

@@ -78,6 +80,12 @@
      public ModulePanel getTab() {
        return tab;
      }
+
+    public void unload() {
+      if (tab != null) {
+        tab.disconnect();
+      }
+    }
    }

    /**
@@ -162,6 +170,36 @@
    public SwingUI(HostedModeBaseOptions options) {
      this.options = options;
    }
+
+  @Override
+  public ModuleHandle getModuleLogger(String userAgent, String  
remoteSocket,
+      String url, String tabKey, String moduleName, String sessionKey,
+      String agentTag, byte[] agentIcon, TreeLogger.Type logLevel) {
+    // TODO(jat): add support for closing an active module
+    ModuleTabPanel tabPanel = null;
+    ModulePanel tab = null;
+    tabPanel = findModuleTab(userAgent, remoteSocket, url, tabKey,
+        moduleName, agentIcon);
+    tab = tabPanel.addModuleSession(logLevel, moduleName, sessionKey,
+        options.getLogFile(String.format("%s-%s-%d.log", moduleName,  
agentTag,
+            getNextSessionCounter(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?
+    return new SwingModuleHandle(logger, tab);
+  }

    @Override
    public TreeLogger getTopLogger() {
@@ -229,41 +267,30 @@
    }

    @Override
-  public ModuleHandle loadModule(String userAgent, String remoteSocket,
-      String url, String tabKey, String moduleName, String sessionKey,
-      String agentTag, byte[] agentIcon, TreeLogger.Type logLevel) {
-    // TODO(jat): add support for closing an active module
-    ModuleTabPanel tabPanel = null;
-    ModulePanel tab = null;
-    tabPanel = findModuleTab(userAgent, remoteSocket, url, tabKey,
-        moduleName, agentIcon);
-    tab = tabPanel.addModuleSession(logLevel, moduleName, sessionKey,
-        options.getLogFile(String.format("%s-%s-%d.log", moduleName,  
agentTag,
-            getNextSessionCounter(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?
-    return new SwingModuleHandle(logger, tab);
-  }
-
-  @Override
-  public void unloadModule(ModuleHandle module) {
-    SwingModuleHandle handle = (SwingModuleHandle) module;
-    Disconnectable tab = handle.getTab();
-    if (tab != null) {
-      tab.disconnect();
+  public void setStartupUrls(Map<String, URL> urls) {
+    // TODO(jat): provide UI for selecting URLs and launching
+    ArrayList<String> keys = new ArrayList<String>(urls.keySet());
+    Collections.sort(keys);
+    for (String url : keys) {
+      final URL helpInfoUrl = urls.get(url);
+      getTopLogger().log(TreeLogger.INFO, "Waiting for browser connection  
to "
+          + helpInfoUrl.toExternalForm(), null,
+          new HelpInfo() {
+            @Override
+            public String getAnchorText() {
+              return "Launch default browser";
+            }
+
+            @Override
+            public String getPrefix() {
+              return "";
+            }
+
+            @Override
+            public URL getURL() {
+              return helpInfoUrl;
+            }
+          });
      }
    }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java    Mon  
Oct 26 14:02:26 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java    Thu  
Nov 19 12:24:42 2009
@@ -254,8 +254,7 @@

      /**
       * Load a new instance of a module.
-     *
-     * @param logger
+     *
       * @param channel
       * @param moduleName
       * @param userAgent
@@ -267,9 +266,9 @@
       *     24x24) representing the user agent or null if unavailable
       * @return a TreeLogger to use for the module's logs
       */
-    public abstract TreeLogger loadModule(TreeLogger logger,
-        BrowserChannel channel, String moduleName, String userAgent,  
String url,
-        String tabKey, String sessionKey, byte[] userAgentIcon);
+    public abstract TreeLogger loadModule(BrowserChannel channel,
+        String moduleName, String userAgent, String url, String tabKey,
+        String sessionKey, byte[] userAgentIcon);

      public abstract ExceptionOrReturnValue setProperty(BrowserChannel  
channel,
          int refId, int dispId, Value newValue);
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java      
 
Thu Nov 19 10:58:27 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java      
 
Thu Nov 19 12:24:42 2009
@@ -373,7 +373,7 @@
      Thread.currentThread().setName(
          "Code server for " + moduleName + " from " + userAgent + " on " +  
url
          + " @ " + sessionKey);
-    logger = handler.loadModule(logger, this, moduleName, userAgent, url,
+    logger = handler.loadModule(this, moduleName, userAgent, url,
          tabKey, sessionKey, iconBytes);
      try {
        // send LoadModule response
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java Thu  
Nov  5 10:42:40 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java Thu  
Nov 19 12:24:42 2009
@@ -15,8 +15,8 @@
   */
  package com.google.gwt.dev.shell;

-import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.ModuleHandle;

  /**
   * Interface that unifies access to the <code>BrowserWidget</code>,
@@ -25,9 +25,8 @@
  public interface BrowserWidgetHost {

    /**
-   * For OOPHM.
+   * Create a logger for a module instance.
     *
-   * @param logger
     * @param moduleName
     * @param userAgent
     * @param url URL of top-level window, may be null for old browser  
plugins
@@ -37,16 +36,22 @@
     * @param serverChannel connection from the client
     * @param userAgentIcon byte array containing an icon (which fits in  
24x24)
     *     for this user agent or null if unavailable
+   * @return ModuleHandle instance -- caller is responsible for calling
+   *     {...@link ModuleHandle#unload()} on it when done
     */
-  ModuleSpaceHost createModuleSpaceHost(TreeLogger logger, String  
moduleName,
-      String userAgent, String url, String tabKey, String sessionKey,
-      BrowserChannelServer serverChannel, byte[] userAgentIcon)
-      throws UnableToCompleteException;
-
-  TreeLogger getLogger();
+  ModuleHandle createModuleLogger(String moduleName, String userAgent,
+      String url, String tabKey, String sessionKey,
+      BrowserChannelServer serverChannel, byte[] userAgentIcon);

    /**
-   * For OOPHM.
+   * Create a ModuleSpaceHost for the specified module.
+   *
+   * @param module ModuleHandle returned from a previous createModuleLogger
+   *     call.
+   * @param moduleName name of module to create
+   * @return ModuleSpaceHost instance
+   * @throws UnableToCompleteException
     */
-  void unloadModule(ModuleSpaceHost moduleSpaceHost);
-}
+  ModuleSpaceHost createModuleSpaceHost(ModuleHandle module, String  
moduleName)
+      throws UnableToCompleteException;
+}
=======================================
---  
/trunk/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java        
 
Wed Oct 28 17:37:45 2009
+++  
/trunk/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java        
 
Thu Nov 19 12:24:42 2009
@@ -250,9 +250,9 @@
    }

    @Override
-  public TreeLogger loadModule(TreeLogger logger, BrowserChannel channel,
-      String moduleName, String userAgent, String url, String tabKey,
-      String sessionKey, byte[] userAgentIcon) {
+  public TreeLogger loadModule(BrowserChannel channel, String moduleName,
+      String userAgent, String url, String tabKey, String sessionKey,
+      byte[] userAgentIcon) {
      throw new UnsupportedOperationException("loadModule must not be  
called");
    }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java       
 
Thu Nov 12 14:37:28 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java       
 
Thu Nov 19 12:24:42 2009
@@ -16,6 +16,7 @@
  package com.google.gwt.dev.shell;

  import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.ModuleHandle;
  import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
  import com.google.gwt.dev.shell.BrowserChannel.Value;
  import com.google.gwt.dev.shell.JsValue.DispatchMethod;
@@ -34,16 +35,20 @@

    private BrowserWidgetHost host;

-  private TreeLogger logger;
-
    private Map<BrowserChannelServer, ModuleSpace> moduleMap =  
Collections.synchronizedMap(new HashMap<BrowserChannelServer,  
ModuleSpace>());

+  private Map<BrowserChannelServer, ModuleHandle> moduleHandleMap =  
Collections.synchronizedMap(new HashMap<BrowserChannelServer,  
ModuleHandle>());
+
+  private final TreeLogger topLogger;
+
    /**
     * Listens for new connections from browsers.
+   * @param topLogger logger to use for non-module-related messages
+   * @param host BrowserWidgetHost instance
     */
-  public OophmSessionHandler(BrowserWidgetHost host) {
+  public OophmSessionHandler(TreeLogger topLogger, BrowserWidgetHost host)  
{
      this.host = host;
-    logger = host.getLogger();
+    this.topLogger = topLogger;
    }

    @Override
@@ -60,7 +65,9 @@
        int dispId) {
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    assert moduleSpace != null;
+    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    assert moduleSpace != null && moduleHandle != null;
+    TreeLogger logger = moduleHandle.getLogger();
      ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      try {
        JsValueOOPHM obj = new JsValueOOPHM();
@@ -94,7 +101,9 @@
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
      ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    assert moduleSpace != null;
+    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    assert moduleSpace != null && moduleHandle != null;
+    TreeLogger logger = moduleHandle.getLogger();
      CompilingClassLoader cl = moduleSpace.getIsolatedClassLoader();

      // Treat dispatch id 0 as toString()
@@ -155,21 +164,21 @@
    }

    @Override
-  public synchronized TreeLogger loadModule(TreeLogger loadModuleLogger,
-      BrowserChannel channel, String moduleName, String userAgent, String  
url,
-      String tabKey, String sessionKey, byte[] userAgentIcon) {
-    logger = loadModuleLogger;
+  public synchronized TreeLogger loadModule(BrowserChannel channel,
+      String moduleName, String userAgent, String url, String tabKey,
+      String sessionKey, byte[] userAgentIcon) {
+    PerfLogger.start("OophmSessionHandler.loadModule " + moduleName);
+    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
+    ModuleHandle moduleHandle = host.createModuleLogger(moduleName,  
userAgent,
+        url, tabKey, sessionKey, serverChannel, userAgentIcon);
+    TreeLogger logger = moduleHandle.getLogger();
+    moduleHandleMap.put(serverChannel, moduleHandle);
+    ModuleSpace moduleSpace = null;
      try {
-      PerfLogger.start("OophmSessionHandler.loadModule " + moduleName);
        // Attach a new ModuleSpace to make it programmable.
-      //
-      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-      ModuleSpaceHost msh = host.createModuleSpaceHost(loadModuleLogger,
-          moduleName, userAgent, url, tabKey, sessionKey, serverChannel,
-          userAgentIcon);
-      logger = msh.getLogger();
-      ModuleSpace moduleSpace = new ModuleSpaceOOPHM(msh, moduleName,
-          serverChannel);
+      ModuleSpaceHost msh = host.createModuleSpaceHost(moduleHandle,
+          moduleName);
+      moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, serverChannel);
        moduleMap.put(serverChannel, moduleSpace);
        PerfLogger.start("ModuleSpace.onLoad");
        moduleSpace.onLoad(logger);
@@ -178,14 +187,20 @@
        // that can go wrong trying to load a module, including Error-derived
        // things like NoClassDefFoundError.
        //
-      this.logger.log(TreeLogger.ERROR, "Failed to load module '" +  
moduleName
-          + "' from user agent '" + userAgent + "' at "
+      moduleHandle.getLogger().log(TreeLogger.ERROR, "Failed to load  
module '"
+          + moduleName + "' from user agent '" + userAgent + "' at "
            + channel.getRemoteEndpoint(), e);
+      if (moduleSpace != null) {
+        moduleSpace.dispose();
+      }
+      moduleHandle.unload();
+      moduleMap.remove(serverChannel);
+      moduleHandleMap.remove(serverChannel);
      } finally {
        PerfLogger.end();
        PerfLogger.end();
      }
-    return this.logger;
+    return moduleHandle.getLogger();
    }

    @Override
@@ -193,7 +208,9 @@
        int dispId, Value newValue) {
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    assert moduleSpace != null;
+    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    assert moduleSpace != null && moduleHandle != null;
+    TreeLogger logger = moduleHandle.getLogger();
      ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      try {
        JsValueOOPHM obj = new JsValueOOPHM();
@@ -220,16 +237,18 @@
    @Override
    public void unloadModule(BrowserChannel channel, String moduleName) {
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
+    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    if (moduleSpace == null) {
-      logger.log(TreeLogger.ERROR, "Unload request without a module  
loaded",
+    if (moduleSpace == null || moduleHandle == null) {
+      topLogger.log(TreeLogger.ERROR, "Unload request without a module  
loaded",
            null);
        return;
      }
-    logger.log(TreeLogger.INFO, "Unloading module "
+    moduleHandle.getLogger().log(TreeLogger.INFO, "Unloading module "
          + moduleSpace.getModuleName() + " (" + moduleName + ")", null);
-    host.unloadModule(moduleSpace.host);
      moduleSpace.dispose();
+    moduleHandle.unload();
      moduleMap.remove(serverChannel);
+    moduleHandleMap.remove(serverChannel);
    }
  }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/remoteui/RemoteUI.java Wed  
Nov 18 13:50:42 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/remoteui/RemoteUI.java Thu  
Nov 19 12:24:42 2009
@@ -17,6 +17,7 @@

  import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.TreeLogger.Type;
+import com.google.gwt.dev.ModuleHandle;
  import com.google.gwt.dev.shell.BrowserListener;
  import com.google.gwt.dev.ui.DevModeUI;
  import com.google.gwt.dev.ui.DoneCallback;
@@ -85,7 +86,7 @@
    }

    @Override
-  public ModuleHandle loadModule(String userAgent, String remoteSocket,
+  public ModuleHandle getModuleLogger(String userAgent, String  
remoteSocket,
        String url, String tabKey, String moduleName, String sessionKey,
        String agentTag, byte[] agentIcon, Type logLevel) {

@@ -100,6 +101,24 @@
        public TreeLogger getLogger() {
          return moduleLogger;
        }
+
+      public void unload() {
+        synchronized (modulesLock) {
+          if (!modules.contains(this)) {
+            return;
+          }
+        }
+
+        ViewerServiceTreeLogger moduleLogger = (ViewerServiceTreeLogger)  
(getLogger());
+
+        try {
+          viewerServiceClient.disconnectLog(moduleLogger.getLogHandle());
+        } finally {
+          synchronized (modulesLock) {
+            modules.remove(this);
+          }
+        }
+      }
      };
      synchronized (modulesLock) {
        modules.add(handle);
@@ -154,23 +173,4 @@
    public boolean supportsRestartWebServer() {
      return hasCallback(RestartServerEvent.getType());
    }
-
-  @Override
-  public void unloadModule(ModuleHandle module) {
-    synchronized (modulesLock) {
-      if (!modules.contains(module)) {
-        return;
-      }
-    }
-
-    ViewerServiceTreeLogger moduleLogger = (ViewerServiceTreeLogger)  
(module.getLogger());
-
-    try {
-      viewerServiceClient.disconnectLog(moduleLogger.getLogHandle());
-    } finally {
-      synchronized (modulesLock) {
-        modules.remove(module);
-      }
-    }
-  }
-}
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/ui/CloseModuleCallback.java  Tue  
Oct 13 16:57:19 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/ui/CloseModuleCallback.java  Thu  
Nov 19 12:24:42 2009
@@ -15,7 +15,7 @@
   */
  package com.google.gwt.dev.ui;

-import com.google.gwt.dev.ui.DevModeUI.ModuleHandle;
+import com.google.gwt.dev.ModuleHandle;

  /**
   * Callback for a request to close an active module from the UI.
@@ -28,7 +28,7 @@
     * the UI), there will be separate calls for each one.
     *
     * @param moduleHandle module handle returned from
-   *     {...@link DevModeUI#loadModule}.
+   *     {...@link DevModeUI#getModuleLogger}.
     */
    void onCloseModule(ModuleHandle moduleHandle);
  }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/ui/DevModeUI.java    Tue Oct 13  
16:57:19 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/ui/DevModeUI.java    Thu Nov 19  
12:24:42 2009
@@ -17,8 +17,10 @@

  import com.google.gwt.core.ext.TreeLogger;
  import com.google.gwt.core.ext.TreeLogger.Type;
+import com.google.gwt.dev.ModuleHandle;
  import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

+import java.net.URL;
  import java.util.HashMap;
  import java.util.Map;

@@ -27,19 +29,6 @@
   * alternate UIs can be implemented.
   */
  public abstract class DevModeUI {
-
-  /**
-   * Opaque handle to a module - it is returned from loadModule and the  
client
-   * can only pass it to unloadModule or get a logger for messages about  
that
-   * module.
-   */
-  public interface ModuleHandle {
-
-    /**
-     * @return the logger for this module.
-     */
-    TreeLogger getLogger();
-  }

    /**
     * Map of callbacks.
@@ -57,6 +46,31 @@
     */
    private Type logLevel;

+  /**
+   * Show that a module is loaded in the UI.
+   *
+   * <p>Note that the {...@link CloseModuleEvent} should already have a  
callback
+   * registered when this is called if needed -- the UI is not required to
+   * change the UI if it is registered later.
+   *
+   * @param userAgent full user agent name
+   * @param remoteSocket name of remote socket endpoint in host:port format
+   * @param url URL of top-level window
+   * @param tabKey stable browser tab identifier, or the empty string if no
+   *     such identifier is available
+   * @param moduleName the name of the module loaded
+   * @param sessionKey a unique session key
+   * @param agentTag short-form user agent identifier, suitable for use in
+   *     a label for this connection
+   * @param agentIcon icon to use for the user agent (fits inside 24x24) or
+   *     null if unavailable
+   * @param logLevel logging detail requested
+   * @return a handle to the module
+   */
+  public abstract ModuleHandle getModuleLogger(String userAgent,
+      String remoteSocket, String url, String tabKey, String moduleName,
+      String sessionKey, String agentTag, byte[] agentIcon, Type logLevel);
+
    /**
     * Create a top-level logger for messages which are not associated with  
the
     * web server or any module.  Defaults to logging to stdout.
@@ -66,7 +80,7 @@
    public TreeLogger getTopLogger() {
      return getConsoleLogger();
    }
-
+
    /**
     * Create the web server portion of the UI if not already created, and
     * return its TreeLogger instance.
@@ -83,7 +97,7 @@
     */
    public abstract TreeLogger getWebServerLogger(String serverName,
        byte[] serverIcon);
-
+
    /**
     * Initialize the UI - must be called exactly once and before any other  
method
     * on this class.
@@ -95,31 +109,6 @@
    public void initialize(Type logLevel) {
      this.logLevel = logLevel;
    }
-
-  /**
-   * Show that a module is loaded in the UI.
-   *
-   * <p>Note that the {...@link CloseModuleEvent} should already have a  
callback
-   * registered when this is called if needed -- the UI is not required to
-   * change the UI if it is registered later.
-   *
-   * @param userAgent full user agent name
-   * @param remoteSocket name of remote socket endpoint in host:port format
-   * @param url URL of top-level window
-   * @param tabKey stable browser tab identifier, or the empty string if no
-   *     such identifier is available
-   * @param moduleName the name of the module loaded
-   * @param sessionKey a unique session key
-   * @param agentTag short-form user agent identifier, suitable for use in
-   *     a label for this connection
-   * @param agentIcon icon to use for the user agent (fits inside 24x24) or
-   *     null if unavailable
-   * @param logLevel logging detail requested
-   * @return a handle to the module
-   */
-  public abstract ModuleHandle loadModule(String userAgent,
-      String remoteSocket, String url, String tabKey, String moduleName,
-      String sessionKey, String agentTag, byte[] agentIcon, Type logLevel);

    /**
     * Sets the callback for a given event type..
@@ -135,13 +124,15 @@
    }

    /**
-   * Show that a previously loaded module has been unloaded.
+   * Set the URLs that should be available to start.
     *
-   * @param module ModuleHandle instance returned from loadModule on this  
UI
-   *     instance
+   * @param urls map of URLs -- the key is the name supplied with  
-startupUrls,
+   *     and the value is the mapped URL with all parameters included
     */
-  public abstract void unloadModule(ModuleHandle module);
-
+  public void setStartupUrls(Map<String, URL> urls) {
+    // do nothing by default
+  }
+
    /**
     * Call callback for a given event.
     *
=======================================
---  
/trunk/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java     
 
Tue Oct 13 16:57:19 2009
+++  
/trunk/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java     
 
Thu Nov 19 12:24:42 2009
@@ -156,9 +156,9 @@
      }

      @Override
-    public TreeLogger loadModule(TreeLogger logger, BrowserChannel channel,
-        String moduleName, String userAgent, String url, String tabKey,
-        String sessionKey, byte[] userAgentIcon) {
+    public TreeLogger loadModule(BrowserChannel channel, String moduleName,
+        String userAgent, String url, String tabKey, String sessionKey,
+        byte[] userAgentIcon) {
        loadedModule = moduleName;
        this.moduleName = moduleName;
        this.userAgent = userAgent;
@@ -166,7 +166,7 @@
        this.tabKey = tabKey;
        this.sessionKey = sessionKey;
        this.userAgentIcon = userAgentIcon;
-      return logger;
+      return new FailErrorLogger();
      }

      @Override

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

Reply via email to