Delay JSNI injection until the end of loadClass instead of doing it eagerly in findClass; we were getting problems with circular class load dependencies.

Review by: jat (postmortem)

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2606 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
index 8152abb..9b4cd4b 100644
--- a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
+++ b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
@@ -541,29 +541,38 @@
         updateJavaScriptHost();
       }
 
-      JsniMethods jsniMethods = newClass.getAnnotation(JsniMethods.class);
-      if (jsniMethods != null) {
-        for (JsniMethod jsniMethod : jsniMethods.value()) {
-          String[] bodyParts = jsniMethod.body();
-          int size = 0;
-          for (String bodyPart : bodyParts) {
-            size += bodyPart.length();
-          }
-          StringBuilder body = new StringBuilder(size);
-          for (String bodyPart : bodyParts) {
-            body.append(bodyPart);
-          }
-          shellJavaScriptHost.createNative(jsniMethod.file(),
-              jsniMethod.line(), jsniMethod.name(), jsniMethod.paramNames(),
-              body.toString());
-        }
-      }
       return newClass;
     } catch (UnableToCompleteException e) {
       throw new ClassNotFoundException(className);
     }
   }
 
+  /**
+   * Overridden to process JSNI annotations.
+   */
+  @Override
+  protected synchronized Class<?> loadClass(String name, boolean resolve)
+      throws ClassNotFoundException {
+    Class<?> newClass = super.loadClass(name, resolve);
+    JsniMethods jsniMethods = newClass.getAnnotation(JsniMethods.class);
+    if (jsniMethods != null) {
+      for (JsniMethod jsniMethod : jsniMethods.value()) {
+        String[] bodyParts = jsniMethod.body();
+        int size = 0;
+        for (String bodyPart : bodyParts) {
+          size += bodyPart.length();
+        }
+        StringBuilder body = new StringBuilder(size);
+        for (String bodyPart : bodyParts) {
+          body.append(bodyPart);
+        }
+        shellJavaScriptHost.createNative(jsniMethod.file(), jsniMethod.line(),
+            jsniMethod.name(), jsniMethod.paramNames(), body.toString());
+      }
+    }
+    return newClass;
+  }
+
   void clear() {
     // Release our references to the shell.
     shellJavaScriptHost = null;
@@ -614,8 +623,9 @@
    * @see JavaScriptHost
    */
   private void updateJavaScriptHost() {
-    // Find the application's JavaScriptHost interface.
-    //
+    if (javaScriptHostClass == null) {
+      return;
+    }
     Throwable caught;
     try {
       final Class<?>[] paramTypes = new Class[] {ShellJavaScriptHost.class};