Simplified GWTShellServlet's pinning and lookup of servlet instances by module.  Changed HostedModeServletContextProxy to assert that its weakly-referenced moduleDef is non-null.

Suggested by: jat
Review by: jat


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2212 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
index 2d9a301..d348d97 100644
--- a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
+++ b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
@@ -96,20 +96,12 @@
       ReferenceMap.HARD, ReferenceMap.WEAK);
 
   /**
-   * Used to quickly lookup servlets by name, but does not pin them; servlets
-   * are pinned by their module in {@link #loadedServletsPinnedByModule}.
-   */
-  @SuppressWarnings("unchecked")
-  private final Map<String, HttpServlet> loadedServletsByModuleAndClassName = new ReferenceMap(
-      ReferenceMap.HARD, ReferenceMap.WEAK);
-
-  /**
    * The lifetime of the module pins the lifetime of the associated servlet;
    * this is because the loaded servlet has a weak backRef to its live module
    * through its context. When the module dies, the servlet needs to die also.
    */
   @SuppressWarnings("unchecked")
-  private final Map<ModuleDef, HttpServlet> loadedServletsPinnedByModule = new ReferenceMap(
+  private final Map<ModuleDef, Map<String, HttpServlet>> loadedServletsByModuleAndClassName = new ReferenceMap(
       ReferenceMap.WEAK, ReferenceMap.HARD, true);
 
   private final Map<String, String> mimeTypes = new HashMap<String, String>();
@@ -926,9 +918,19 @@
 
   private HttpServlet tryGetOrLoadServlet(TreeLogger logger,
       ModuleDef moduleDef, String className) {
+
+    // Maps className to live servlet for this module.
+    Map<String, HttpServlet> moduleServlets;
     synchronized (loadedServletsByModuleAndClassName) {
-      String moduleAndClassName = moduleDef.getName() + "/" + className;
-      HttpServlet servlet = loadedServletsByModuleAndClassName.get(moduleAndClassName);
+      moduleServlets = loadedServletsByModuleAndClassName.get(moduleDef);
+      if (moduleServlets == null) {
+        moduleServlets = new HashMap<String, HttpServlet>();
+        loadedServletsByModuleAndClassName.put(moduleDef, moduleServlets);
+      }
+    }
+
+    synchronized (moduleServlets) {
+      HttpServlet servlet = moduleServlets.get(className);
       if (servlet != null) {
         // Found it.
         //
@@ -963,8 +965,7 @@
 
         servlet.init(config);
 
-        loadedServletsByModuleAndClassName.put(moduleAndClassName, servlet);
-        loadedServletsPinnedByModule.put(moduleDef, servlet);
+        moduleServlets.put(className, servlet);
         return servlet;
       } catch (ClassNotFoundException e) {
         caught = e;
diff --git a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java b/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
index 7f4a2af..adf1ced 100644
--- a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
+++ b/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
@@ -154,9 +154,10 @@
    */
   public URL getResource(String path) throws MalformedURLException {
     ModuleDef moduleDef = moduleDefRef.get();
-    if (moduleDef == null) {
-      return context.getResource(path);
-    }
+    assert (moduleDef != null) : "GWTShellServlet should have guaranteed that a"
+        + " live servlet will never process a request for a dead module; if you"
+        + " are using this servlet outside the context of processing a call,"
+        + " then don't do that";
 
     String moduleContext = "/" + moduleDef.getName() + "/";
     if (!path.startsWith(moduleContext)) {
@@ -164,7 +165,7 @@
       moduleContext = "/" + moduleDef.getCanonicalName() + "/";
       if (!path.startsWith(moduleContext)) {
         // This path is in a different context; just return null
-      return null;
+        return null;
       }
     }