Fixes OOPHM build breakage.
Patch by: jgw, jat
Review by: jat (Desk check)


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4664 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java b/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java
index f76cc25..eb3df67 100644
--- a/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java
+++ b/dev/oophm/overlay/com/google/gwt/dev/GWTShell.java
@@ -441,6 +441,10 @@
     return false;
   }
 
+  public WebServerRestart hasWebServer() {
+    return WebServerRestart.NONE;
+  }
+
   /**
    * Launch the arguments as Urls in separate windows.
    */
@@ -491,6 +495,10 @@
     throw new UnableToCompleteException();
   }
 
+  public void restartServer(TreeLogger logger) throws UnableToCompleteException {
+    // Unimplemented.
+  }
+
   @Override
   protected void compile(TreeLogger logger) throws UnableToCompleteException {
     throw new UnsupportedOperationException();
@@ -612,8 +620,7 @@
     ImageIcon gwtIcon = loadImageIcon("icon24.png");
     frame = new JFrame("GWT Hosted Mode");
     tabs = new JTabbedPane();
-    boolean checkForUpdates = doShouldCheckForUpdates();
-    mainWnd = new ShellMainWindow(this, checkForUpdates, options.getLogLevel());
+    mainWnd = new ShellMainWindow(this, options.getLogLevel());
     tabs.addTab("Hosted Mode", gwtIcon, mainWnd, "GWT Hosted-mode");
     if (!options.isNoServer()) {
       ImageIcon tomcatIcon = loadImageIcon("tomcat24.png");
diff --git a/dev/oophm/overlay/com/google/gwt/dev/shell/PlatformSpecific.java b/dev/oophm/overlay/com/google/gwt/dev/shell/PlatformSpecific.java
index 049361d..d32da9e 100644
--- a/dev/oophm/overlay/com/google/gwt/dev/shell/PlatformSpecific.java
+++ b/dev/oophm/overlay/com/google/gwt/dev/shell/PlatformSpecific.java
@@ -16,6 +16,16 @@
 package com.google.gwt.dev.shell;
 
 import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
 
 /**
  * Performs platform-specific class selection.
@@ -23,26 +33,71 @@
 public class PlatformSpecific {
 
   /**
-   * All of these classes must extend CheckForUpdates.
+   * All of these classes must extend CheckForUpdates. Note that currently only
+   * IE has a custom implementation (to handle proxies) and that CheckForUpdates
+   * must be the last one in the list.
    */
   private static final String[] updaterClassNames = new String[] {
-  // "com.google.gwt.dev.shell.ie.CheckForUpdatesIE6",
-  // "com.google.gwt.dev.shell.moz.CheckForUpdatesMoz",
-  // "com.google.gwt.dev.shell.mac.CheckForUpdatesSaf"
-  };
+      "com.google.gwt.dev.shell.ie.CheckForUpdatesIE6",
+      "com.google.gwt.dev.shell.CheckForUpdates"};
 
-  @SuppressWarnings("unchecked")
-  // Class.forName
-  public static CheckForUpdates createUpdateChecker() {
+  public static FutureTask<UpdateResult> checkForUpdatesInBackgroundThread(
+      final TreeLogger logger, final long minCheckMillis) {
+    final String entryPoint = PlatformSpecific.computeEntryPoint();
+    FutureTask<UpdateResult> task = new FutureTask<UpdateResult>(
+        new Callable<UpdateResult>() {
+          public UpdateResult call() throws Exception {
+            final CheckForUpdates updateChecker = createUpdateChecker(logger,
+                entryPoint);
+            return updateChecker == null ? null
+                : updateChecker.check(minCheckMillis);
+          }
+        });
+    Thread checkerThread = new Thread(task, "GWT Update Checker");
+    checkerThread.setDaemon(true);
+    checkerThread.start();
+    return task;
+  }
+
+  /**
+   * Find the first method named "main" on the call stack and use its class as
+   * the entry point.
+   */
+  public static String computeEntryPoint() {
+    Throwable t = new Throwable();
+    for (StackTraceElement stackTrace : t.getStackTrace()) {
+      if (stackTrace.getMethodName().equals("main")) {
+        // Strip package name from main's class
+        String className = stackTrace.getClassName();
+        int i = className.lastIndexOf('.');
+        if (i >= 0) {
+          return className.substring(i + 1);
+        }
+        return className;
+      }
+    }
+    return null;
+  }
+
+  public static CheckForUpdates createUpdateChecker(TreeLogger logger) {
+    return createUpdateChecker(logger, computeEntryPoint());
+  }
+
+  public static CheckForUpdates createUpdateChecker(TreeLogger logger,
+      String entryPoint) {
     try {
       for (int i = 0; i < updaterClassNames.length; i++) {
         try {
-          Class<CheckForUpdates> clazz = (Class<CheckForUpdates>) Class.forName(updaterClassNames[i]);
-          Constructor<CheckForUpdates> ctor = clazz.getDeclaredConstructor(new Class[] {});
-          CheckForUpdates checker = ctor.newInstance(new Object[] {});
+          Class<? extends CheckForUpdates> clazz = Class.forName(
+              updaterClassNames[i]).asSubclass(CheckForUpdates.class);
+          Constructor<? extends CheckForUpdates> ctor = clazz.getDeclaredConstructor(new Class[] {
+              TreeLogger.class, String.class});
+          CheckForUpdates checker = ctor.newInstance(new Object[] {
+              logger, entryPoint});
           return checker;
-        } catch (ClassNotFoundException e) {
-          // keep trying
+        } catch (Exception e) {
+          // Other exceptions can occur besides ClassNotFoundException,
+          // so ignore them all so we can find a functional updater.
         }
       }
     } catch (Throwable e) {
@@ -50,4 +105,34 @@
     }
     return null;
   }
+
+  public static void logUpdateAvailable(TreeLogger logger,
+      FutureTask<UpdateResult> updater) {
+    if (updater != null && updater.isDone()) {
+      UpdateResult result = null;
+      try {
+        result = updater.get(0, TimeUnit.MILLISECONDS);
+      } catch (InterruptedException e) {
+        // Silently ignore exception
+      } catch (ExecutionException e) {
+        // Silently ignore exception
+      } catch (TimeoutException e) {
+        // Silently ignore exception
+      }
+      logUpdateAvailable(logger, result);
+    }
+  }
+
+  public static void logUpdateAvailable(TreeLogger logger, UpdateResult result) {
+    if (result != null) {
+      final URL url = result.getURL();
+      logger.log(TreeLogger.WARN, "A new version of GWT ("
+          + result.getNewVersion() + ") is available", null, new HelpInfo() {
+        @Override
+        public URL getURL() {
+          return url;
+        }
+      });
+    }
+  }
 }
diff --git a/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java b/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
index e150a1f..57ab665 100644
--- a/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
+++ b/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
@@ -34,9 +34,7 @@
 
   private SwingLoggerPanel logWindow;
 
-  public ShellMainWindow(GWTShell shell, boolean checkForUpdates,
-      TreeLogger.Type maxLevel) {
-    // TODO(jat): implement update check
+  public ShellMainWindow(GWTShell shell, TreeLogger.Type maxLevel) {
     super(new BorderLayout());
     JPanel panel = new JPanel(new GridLayout(2, 1));
     JPanel optionPanel = new JPanel();