Update checking now occurs when using command-line tools if no check has occurred in the last 24 hours. - Users who don't use hosted mode should now be aware when GWT is updated. - An update notifaction will only be emitted on a successful compile - Update checking now uses TreeLogger's HelpInfo so that users are no longer confronted with modal dialog. - -XdisableUpdateCheck is added to the command line tools so that, for example, build systems behind firewalls can opt-out. Patch by: jat Review by: me git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4524 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java index 00c9f23..6778230 100644 --- a/dev/core/src/com/google/gwt/dev/Compiler.java +++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -22,6 +22,9 @@ 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.shell.CheckForUpdates; +import com.google.gwt.dev.shell.PlatformSpecific; +import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult; import com.google.gwt.dev.util.PerfLogger; import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.arg.ArgHandlerExtraDir; @@ -32,6 +35,7 @@ import java.io.File; import java.io.IOException; +import java.util.concurrent.FutureTask; /** * The main executable entry point for the GWT Java to JavaScript compiler. @@ -112,7 +116,16 @@ if (new ArgProcessor(options).processArgs(args)) { CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { - return new Compiler(options).run(logger); + FutureTask<UpdateResult> updater = null; + if (!options.isUpdateCheckDisabled()) { + updater = PlatformSpecific.checkForUpdatesInBackgroundThread(logger, + CheckForUpdates.ONE_DAY); + } + boolean success = new Compiler(options).run(logger); + if (success) { + PlatformSpecific.logUpdateAvailable(logger, updater); + } + return success; } }; if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java index 156f2b9..5cbe5cd 100644 --- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java +++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -21,6 +21,9 @@ 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.shell.CheckForUpdates; +import com.google.gwt.dev.shell.PlatformSpecific; +import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult; import com.google.gwt.dev.util.PerfLogger; import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers; @@ -30,6 +33,7 @@ import java.io.File; import java.io.IOException; +import java.util.concurrent.FutureTask; /** * The main executable entry point for the GWT Java to JavaScript compiler. @@ -107,7 +111,16 @@ if (new ArgProcessor(options).processArgs(args)) { CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { - return new GWTCompiler(options).run(logger); + FutureTask<UpdateResult> updater = null; + if (!options.isUpdateCheckDisabled()) { + updater = PlatformSpecific.checkForUpdatesInBackgroundThread(logger, + CheckForUpdates.ONE_DAY); + } + boolean success = new GWTCompiler(options).run(logger); + if (success) { + PlatformSpecific.logUpdateAvailable(logger, updater); + } + return success; } }; if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
diff --git a/dev/core/src/com/google/gwt/dev/HostedModeBase.java b/dev/core/src/com/google/gwt/dev/HostedModeBase.java index 28741a0e..3b7faa7 100644 --- a/dev/core/src/com/google/gwt/dev/HostedModeBase.java +++ b/dev/core/src/com/google/gwt/dev/HostedModeBase.java
@@ -27,7 +27,9 @@ 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.PlatformSpecific; import com.google.gwt.dev.shell.ShellModuleSpaceHost; import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization; @@ -425,6 +427,13 @@ } /** + * Derived classes can override to lengthen ping delay. + */ + protected long checkForUpdatesInterval() { + return CheckForUpdates.ONE_MINUTE; + } + + /** * Compiles all modules. */ protected abstract void compile(TreeLogger logger) @@ -461,13 +470,6 @@ "gen"), doCreateArtifactAcceptor(moduleDef)); } - /** - * Derived classes can override to prevent automatic update checking. - */ - protected boolean doShouldCheckForUpdates() { - return true; - } - protected abstract void doShutDownServer(); protected boolean doStartup() { @@ -479,6 +481,22 @@ // Initialize the logger. // initializeLogger(); + + // Check for updates + final TreeLogger logger = getTopLogger(); + final CheckForUpdates updateChecker + = PlatformSpecific.createUpdateChecker(logger); + if (updateChecker != null) { + Thread checkerThread = new Thread("GWT Update Checker") { + @Override + public void run() { + PlatformSpecific.logUpdateAvailable(logger, + updateChecker.check(checkForUpdatesInterval())); + } + }; + checkerThread.setDaemon(true); + checkerThread.start(); + } return true; }
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java index c0ca5a2..cb86208 100644 --- a/dev/core/src/com/google/gwt/dev/Precompile.java +++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -36,14 +36,19 @@ import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler; import com.google.gwt.dev.jjs.JsOutputOption; import com.google.gwt.dev.jjs.UnifiedAst; +import com.google.gwt.dev.shell.CheckForUpdates; +import com.google.gwt.dev.shell.PlatformSpecific; import com.google.gwt.dev.shell.StandardRebindOracle; +import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult; import com.google.gwt.dev.util.PerfLogger; import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization; +import com.google.gwt.dev.util.arg.ArgHandlerDisableUpdateCheck; import com.google.gwt.dev.util.arg.ArgHandlerEnableAssertions; import com.google.gwt.dev.util.arg.ArgHandlerGenDir; import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle; import com.google.gwt.dev.util.arg.ArgHandlerValidateOnlyFlag; +import com.google.gwt.dev.util.arg.OptionDisableUpdateCheck; import com.google.gwt.dev.util.arg.OptionGenDir; import com.google.gwt.dev.util.arg.OptionValidateOnly; @@ -53,6 +58,7 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; +import java.util.concurrent.FutureTask; /** * Performs the first phase of compilation, generating the set of permutations @@ -64,7 +70,7 @@ * The set of options for the precompiler. */ public interface PrecompileOptions extends JJSOptions, CompileTaskOptions, - OptionGenDir, OptionValidateOnly { + OptionGenDir, OptionValidateOnly, OptionDisableUpdateCheck { } static class ArgProcessor extends CompileArgProcessor { @@ -75,6 +81,7 @@ registerHandler(new ArgHandlerEnableAssertions(options)); registerHandler(new ArgHandlerDisableAggressiveOptimization(options)); registerHandler(new ArgHandlerValidateOnlyFlag(options)); + registerHandler(new ArgHandlerDisableUpdateCheck(options)); } @Override @@ -85,6 +92,7 @@ static class PrecompileOptionsImpl extends CompileTaskOptionsImpl implements PrecompileOptions { + private boolean disableUpdateCheck; private File genDir; private final JJSOptionsImpl jjsOptions = new JJSOptionsImpl(); private boolean validateOnly; @@ -101,6 +109,7 @@ jjsOptions.copyFrom(other); + setDisableUpdateCheck(other.isUpdateCheckDisabled()); setGenDir(other.getGenDir()); setValidateOnly(other.isValidateOnly()); } @@ -121,6 +130,10 @@ return jjsOptions.isEnableAssertions(); } + public boolean isUpdateCheckDisabled() { + return disableUpdateCheck; + } + public boolean isValidateOnly() { return validateOnly; } @@ -129,6 +142,10 @@ jjsOptions.setAggressivelyOptimize(aggressivelyOptimize); } + public void setDisableUpdateCheck(boolean disabled) { + disableUpdateCheck = disabled; + } + public void setEnableAssertions(boolean enableAssertions) { jjsOptions.setEnableAssertions(enableAssertions); } @@ -227,7 +244,16 @@ if (new ArgProcessor(options).processArgs(args)) { CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { - return new Precompile(options).run(logger); + FutureTask<UpdateResult> updater = null; + if (!options.isUpdateCheckDisabled()) { + updater = PlatformSpecific.checkForUpdatesInBackgroundThread(logger, + CheckForUpdates.ONE_DAY); + } + boolean success = new Precompile(options).run(logger); + if (success) { + PlatformSpecific.logUpdateAvailable(logger, updater); + } + return success; } }; if (CompileTaskRunner.runWithAppropriateLogger(options, task)) { @@ -290,8 +316,7 @@ merged.put(rebindResultsString, permutation); } } - return new Precompilation(unifiedAst, merged.values(), - generatedArtifacts); + return new Precompilation(unifiedAst, merged.values(), generatedArtifacts); } catch (UnableToCompleteException e) { // We intentionally don't pass in the exception here since the real // cause has been logged.
diff --git a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java index bda5243..c12aebb 100644 --- a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java +++ b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
@@ -221,10 +221,8 @@ shell.setImages(ShellMainWindow.getIcons()); - boolean checkForUpdates = doShouldCheckForUpdates(); - mainWnd = new ShellMainWindow(this, shell, options.isNoServer() ? 0 - : getPort(), checkForUpdates); + : getPort()); shell.setSize(700, 600); if (!isHeadless()) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/CheckForUpdates.java b/dev/core/src/com/google/gwt/dev/shell/CheckForUpdates.java index e9e7886..51bfbe4 100644 --- a/dev/core/src/com/google/gwt/dev/shell/CheckForUpdates.java +++ b/dev/core/src/com/google/gwt/dev/shell/CheckForUpdates.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.shell; +import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.dev.About; import org.w3c.dom.Document; @@ -27,8 +28,11 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; @@ -43,18 +47,121 @@ * Orchestrates a best-effort attempt to find out if a new version of GWT is * available. */ -public abstract class CheckForUpdates { +public class CheckForUpdates { /** - * Abstract the action to take when an update is available. + * Represents a GWT version. */ - public static interface UpdateAvailableCallback { - void onUpdateAvailable(String html); + public static class GwtVersion implements Comparable<GwtVersion> { + + private final int[] version = new int[3]; + + /** + * Create a version that avoids any nagging -- "0.0.999". + */ + public GwtVersion() { + version[2] = 999; + } + + /** + * Parse a version number as a string. An empty or null string are + * explicitly allowed and are equivalent to "0.0.0". + * + * @param versionString + * @throws NumberFormatException + */ + public GwtVersion(String versionString) throws NumberFormatException { + if (versionString == null) { + return; + } + int part = 0; + int v = 0; + int len = versionString.length(); + for (int i = 0; i < len; ++i) { + char ch = versionString.charAt(i); + if (ch == '.') { + if (part >= version.length) { + throw new NumberFormatException(); + } + version[part++] = v; + v = 0; + } else if (Character.isDigit(ch)) { + int digit = Character.digit(ch, 10); + if (digit < 0) { + throw new NumberFormatException(); + } + v = v * 10 + digit; + } + } + version[part++] = v; + } + + public int compareTo(GwtVersion o) { + for (int i = 0; i <= 2; ++i) { + if (version[i] != o.version[i]) { + return version[i] - o.version[i]; + } + } + return 0; + } + + public int getPart(int part) { + // TODO: something besides IORE here? + return version[part]; + } + + public boolean isNoNagVersion() { + return version[2] == 999; + } + + public boolean isUnspecified() { + return version[0] == 0 && version[1] == 0 && version[2] == 0; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append(version[0]).append('.').append(version[1]).append('.'); + buf.append(version[2]); + return buf.toString(); + } } - protected static final String LAST_SERVER_VERSION = "lastServerVersion"; - private static final boolean DEBUG_VERSION_CHECK; + /** + * Returns the result of an update check. + */ + public interface UpdateResult { + /** + * @return the new version of GWT available. + */ + GwtVersion getNewVersion(); + + /** + * @return the URL for details about the new version. + */ + URL getURL(); + } + + public static final long ONE_DAY = 24 * 60 * 60 * 1000; + public static final long ONE_MINUTE = 60 * 1000; + + // System properties used by CheckForUpdates + protected static final String PROPERTY_DEBUG_HTTP_GET = "gwt.debugLowLevelHttpGet"; + protected static final String PROPERTY_FORCE_NONNATIVE = "gwt.forceVersionCheckNonNative"; + protected static final String PROPERTY_PREFS_NAME = "gwt.prefsPathName"; + protected static final String PROPERTY_QUERY_URL = "gwt.forceVersionCheckURL"; + + // Log levels -- in general we want the logging of the update process + // to not be visible to normal users. + private static final TreeLogger.Type CHECK_ERROR = TreeLogger.DEBUG; + private static final TreeLogger.Type CHECK_INFO = TreeLogger.SPAM; + private static final TreeLogger.Type CHECK_SPAM = TreeLogger.SPAM; + private static final TreeLogger.Type CHECK_WARN = TreeLogger.SPAM; + + // Preferences keys private static final String FIRST_LAUNCH = "firstLaunch"; + private static final String HIGHEST_RUN_VERSION = "highestRunVersion"; + private static final String LAST_PING = "lastPing"; private static final String NEXT_PING = "nextPing"; // Uncomment one of constants below to try different variations of failure to @@ -75,74 +182,6 @@ // The real URL that should be used. private static final String QUERY_URL = "http://tools.google.com/webtoolkit/currentversion.xml"; - private static final int VERSION_PARTS = 3; - private static final String VERSION_REGEXP = "\\d+\\.\\d+\\.\\d+"; - - static { - // Do this in a static initializer so we can ignore all exceptions. - // - boolean debugVersionCheck = false; - try { - if (System.getProperty("gwt.debugVersionCheck") != null) { - debugVersionCheck = true; - } - } catch (Throwable e) { - // Always silently ignore any errors. - // - } finally { - DEBUG_VERSION_CHECK = debugVersionCheck; - } - } - - /** - * Determines whether the server version is definitively newer than the client - * version. If any errors occur in the comparison, this method returns false - * to avoid unwanted erroneous notifications. - * - * @param clientVersion The current client version - * @param serverVersion The current server version - * @return true if the server is definitely newer, otherwise false - */ - protected static boolean isServerVersionNewer(String clientVersion, - String serverVersion) { - if (clientVersion == null || serverVersion == null) { - return false; - } - - // must match expected format - if (!clientVersion.matches(VERSION_REGEXP) - || !serverVersion.matches(VERSION_REGEXP)) { - return false; - } - - // extract the relevant parts - String[] clientParts = clientVersion.split("\\."); - String[] serverParts = serverVersion.split("\\."); - if (clientParts.length != VERSION_PARTS - || serverParts.length != VERSION_PARTS) { - return false; - } - - // examine piece by piece from most significant to least significant - for (int i = 0; i < VERSION_PARTS; ++i) { - try { - int clientPart = Integer.parseInt(clientParts[i]); - int serverPart = Integer.parseInt(serverParts[i]); - if (serverPart < clientPart) { - return false; - } - - if (serverPart > clientPart) { - return true; - } - } catch (NumberFormatException e) { - return false; - } - } - - return false; - } - private static String getTextOfLastElementHavingTag(Document doc, String tagName) { NodeList nodeList = doc.getElementsByTagName(tagName); @@ -161,197 +200,97 @@ return null; } - private static void parseResponse(Preferences prefs, byte[] response, - UpdateAvailableCallback callback) throws IOException, - ParserConfigurationException, SAXException { + private String entryPoint; + private TreeLogger logger; + private GwtVersion myVersion; - if (DEBUG_VERSION_CHECK) { - System.out.println("Parsing response (length " + response.length + ")"); - } + /** + * Create an update checker which will poll a server URL and log a message + * about an update if available. + * + * @param logger TreeLogger to use + */ + public CheckForUpdates(TreeLogger logger) { + this(logger, null); + } - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - ByteArrayInputStream bais = new ByteArrayInputStream(response); - - // Parse the XML. - // - builder.setErrorHandler(new ErrorHandler() { - - public void error(SAXParseException exception) throws SAXException { - // fail quietly - } - - public void fatalError(SAXParseException exception) throws SAXException { - // fail quietly - } - - public void warning(SAXParseException exception) throws SAXException { - // fail quietly - } - }); - Document doc = builder.parse(bais); - - // The latest version number. - // - String version = getTextOfLastElementHavingTag(doc, "latest-version"); - if (version == null) { - // Not valid; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Failed to find <latest-version>"); - } - return; - } else { - version = version.trim(); - } - - String[] versionParts = version.split("\\."); - if (versionParts.length != 3) { - // Not valid; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Bad version format: " + version); - } - return; - } + /** + * Create an update checker which will poll a server URL and log a message + * about an update if available. + * + * @param logger TreeLogger to use + * @param entryPoint the name of the main entry point used for this execution + */ + public CheckForUpdates(TreeLogger logger, String entryPoint) { + this.logger = logger; + this.entryPoint = entryPoint; try { - Integer.parseInt(versionParts[0]); - Integer.parseInt(versionParts[1]); - Integer.parseInt(versionParts[2]); + myVersion = new GwtVersion(About.GWT_VERSION_NUM); } catch (NumberFormatException e) { - // Not valid; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Bad version number: " + version); - } - return; + // if our build version number is bogus, use one that avoids nagging + myVersion = new GwtVersion(); } - - // Ping delay for server-controlled throttling. - // - String pingDelaySecsStr = getTextOfLastElementHavingTag(doc, - "min-wait-seconds"); - int pingDelaySecs = 0; - if (pingDelaySecsStr == null) { - // Not valid; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Missing <min-wait-seconds>"); - } - return; - } else { - try { - pingDelaySecs = Integer.parseInt(pingDelaySecsStr.trim()); - } catch (NumberFormatException e) { - // Not a valid number; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Bad min-wait-seconds number: " + pingDelaySecsStr); - } - return; - } - } - - // Read the HTML. - // - String html = getTextOfLastElementHavingTag(doc, "notification"); - - if (html == null) { - // Not valid; quietly fail. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Missing <notification>"); - } - return; - } - - // Okay -- this is a valid response. - // - processResponse(prefs, version, pingDelaySecs, html, callback); } - private static void processResponse(Preferences prefs, String version, - int pingDelaySecs, String html, UpdateAvailableCallback callback) { - - // Record a ping; don't ping again until the delay is up. - // - long nextPingTime = System.currentTimeMillis() + pingDelaySecs * 1000; - prefs.put(NEXT_PING, String.valueOf(nextPingTime)); - - if (DEBUG_VERSION_CHECK) { - System.out.println("Ping delay is " + pingDelaySecs + "; next ping at " - + new Date(nextPingTime)); - } - - /* - * Stash the version we got last time for comparison below, and record for - * next time the version we just got. - */ - String lastServerVersion = prefs.get(LAST_SERVER_VERSION, null); - prefs.put(LAST_SERVER_VERSION, version); - - // Are we up to date already? - // - if (!isServerVersionNewer(About.GWT_VERSION_NUM, version)) { - - // Yes, we are. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("Server version is not newer"); - } - return; - } - - // Have we already prompted for this particular server version? - // - if (version.equals(lastServerVersion)) { - - // We've already nagged the user once. Don't do it again. - // - if (DEBUG_VERSION_CHECK) { - System.out.println("A notification has already been shown for " - + version); - } - return; - } - - if (DEBUG_VERSION_CHECK) { - System.out.println("Server version has changed to " + version - + "; notification will be shown"); - } - - // Commence nagging. - // - callback.onUpdateAvailable(html); + /** + * Check for updates and log to the logger if they are available. + * + * @return an UpdateResult or null if there is no new update + */ + public UpdateResult check() { + return check(0); } - public void check(final UpdateAvailableCallback callback) { - + /** + * Check for updates and log to the logger if they are available. + * + * @return an UpdateResult or null if there is no new update + */ + public UpdateResult check(long minCheckMillis) { + TreeLogger branch = logger.branch(CHECK_INFO, "Checking for updates"); try { - String forceCheckURL = System.getProperty("gwt.forceVersionCheckURL"); + String prefsName = System.getProperty(PROPERTY_PREFS_NAME); + Preferences prefs; + if (prefsName != null) { + prefs = Preferences.userRoot().node(prefsName); + } else { + prefs = Preferences.userNodeForPackage(CheckForUpdates.class); + } - if (forceCheckURL != null && DEBUG_VERSION_CHECK) { - System.out.println("Explicit version check URL: " + forceCheckURL); + String queryURL = QUERY_URL; + String forceCheckURL = System.getProperty(PROPERTY_QUERY_URL); + + if (forceCheckURL != null) { + branch.log(CHECK_INFO, "Explicit version check URL: " + forceCheckURL); + queryURL = forceCheckURL; } // Get our unique user id (based on absolute timestamp). // long currentTimeMillis = System.currentTimeMillis(); - Preferences prefs = Preferences.userNodeForPackage(CheckForUpdates.class); - - // Get our unique user id (based on absolute timestamp). - // String firstLaunch = prefs.get(FIRST_LAUNCH, null); if (firstLaunch == null) { firstLaunch = Long.toHexString(currentTimeMillis); prefs.put(FIRST_LAUNCH, firstLaunch); - - if (DEBUG_VERSION_CHECK) { - System.out.println("Setting first launch to " + firstLaunch); - } + branch.log(CHECK_SPAM, "Setting first launch to " + firstLaunch); } else { - if (DEBUG_VERSION_CHECK) { - System.out.println("First launch was " + firstLaunch); + branch.log(CHECK_SPAM, "First launch was " + firstLaunch); + } + + // See if enough time has passed. + // + String lastPing = prefs.get(LAST_PING, "0"); + if (lastPing != null) { + try { + long lastPingTime = Long.parseLong(lastPing); + if (currentTimeMillis < lastPingTime + minCheckMillis) { + // it's not time yet + branch.log(CHECK_INFO, "Last ping was " + new Date(lastPingTime) + + ", min wait is " + minCheckMillis + "ms"); + return null; + } + } catch (NumberFormatException e) { + branch.log(CHECK_WARN, "Error parsing last ping time", e); } } @@ -363,73 +302,86 @@ long nextPingTime = Long.parseLong(nextPing); if (currentTimeMillis < nextPingTime) { // it's not time yet - if (DEBUG_VERSION_CHECK) { - System.out.println("Next ping is not until " - + new Date(nextPingTime)); - } - return; + branch.log(CHECK_INFO, "Next ping is not until " + + new Date(nextPingTime)); + return null; } } catch (NumberFormatException e) { - // ignore + branch.log(CHECK_WARN, "Error parsing next ping time", e); } } // See if new version is available. // - String queryURL = forceCheckURL != null ? forceCheckURL : QUERY_URL; String url = queryURL + "?v=" + About.GWT_VERSION_NUM + "&id=" - + firstLaunch; - - if (DEBUG_VERSION_CHECK) { - System.out.println("Checking for new version at " + url); + + firstLaunch + "&r=" + About.GWT_SVNREV; + if (entryPoint != null) { + url += "&e=" + entryPoint; } + branch.log(CHECK_INFO, "Checking for new version at " + url); + // Do the HTTP GET. // byte[] response; String fullUserAgent = makeUserAgent(); - if (System.getProperty("gwt.forceVersionCheckNonNative") == null) { + if (System.getProperty(PROPERTY_FORCE_NONNATIVE) == null) { // Use subclass. // - response = doHttpGet(fullUserAgent, url); + response = doHttpGet(branch, fullUserAgent, url); } else { // Use the pure Java version, but it probably doesn't work with proxies. // - response = httpGetNonNative(fullUserAgent, url); + response = httpGetNonNative(branch, fullUserAgent, url); } if (response == null || response.length == 0) { // Problem. Quietly fail. // - if (DEBUG_VERSION_CHECK) { - System.out.println("Failed to obtain current version info via HTTP"); - } - return; + branch.log(CHECK_ERROR, + "Failed to obtain current version info via HTTP"); + return null; } // Parse and process the response. // Bad responses will be silently ignored. // - parseResponse(prefs, response, callback); + return parseResponse(branch, prefs, response); } catch (Throwable e) { // Always silently ignore any errors. // - if (DEBUG_VERSION_CHECK) { - System.out.println("Exception while processing version info"); - e.printStackTrace(); - } + branch.log(CHECK_INFO, "Exception while processing version info", e); } + return null; } - protected abstract byte[] doHttpGet(String userAgent, String url); + /** + * Default implementation just uses the platform-independent method. A + * subclass should override this method for platform-dependent proxy handling, + * for example. + * + * @param branch TreeLogger to use + * @param userAgent user agent string to send in request + * @param url URL to fetch + * @return byte array of response, or null if an error + */ + protected byte[] doHttpGet(TreeLogger branch, String userAgent, String url) { + return httpGetNonNative(branch, userAgent, url); + } /** * This default implementation uses regular Java HTTP, which doesn't deal with * proxies automagically. See the IE6 subclasses for an implementation that * does deal with proxies. + * + * @param branch TreeLogger to use + * @param userAgent user agent string to send in request + * @param url URL to fetch + * @return byte array of response, or null if an error */ - protected byte[] httpGetNonNative(String userAgent, String url) { + protected byte[] httpGetNonNative(TreeLogger branch, String userAgent, + String url) { Throwable caught; InputStream is = null; try { @@ -458,8 +410,8 @@ } } - if (System.getProperty("gwt.debugLowLevelHttpGet") != null) { - caught.printStackTrace(); + if (System.getProperty(PROPERTY_DEBUG_HTTP_GET) != null) { + branch.log(CHECK_ERROR, "Exception in HTTP request", caught); } return null; @@ -496,4 +448,165 @@ return ua; } + + private UpdateResult parseResponse(TreeLogger branch, Preferences prefs, + byte[] response) throws IOException, ParserConfigurationException, + SAXException { + + branch.log(CHECK_SPAM, "Parsing response (length " + response.length + ")"); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + ByteArrayInputStream bais = new ByteArrayInputStream(response); + + // Parse the XML. + // + builder.setErrorHandler(new ErrorHandler() { + + public void error(SAXParseException exception) throws SAXException { + // fail quietly + } + + public void fatalError(SAXParseException exception) throws SAXException { + // fail quietly + } + + public void warning(SAXParseException exception) throws SAXException { + // fail quietly + } + }); + Document doc = builder.parse(bais); + + // The latest version number. + // + String versionString = getTextOfLastElementHavingTag(doc, "latest-version"); + if (versionString == null) { + // Not valid; quietly fail. + // + branch.log(CHECK_ERROR, "Failed to find <latest-version>"); + return null; + } + GwtVersion currentReleasedVersion; + try { + currentReleasedVersion = new GwtVersion(versionString.trim()); + } catch (NumberFormatException e) { + branch.log(CHECK_ERROR, "Bad version: " + versionString, e); + return null; + } + + // Ping delay for server-controlled throttling. + // + String pingDelaySecsStr = getTextOfLastElementHavingTag(doc, + "min-wait-seconds"); + int pingDelaySecs = 0; + if (pingDelaySecsStr == null) { + // Not valid; quietly fail. + // + branch.log(CHECK_ERROR, "Missing <min-wait-seconds>"); + return null; + } + try { + pingDelaySecs = Integer.parseInt(pingDelaySecsStr.trim()); + } catch (NumberFormatException e) { + // Not a valid number; quietly fail. + // + branch.log(CHECK_ERROR, "Bad min-wait-seconds number: " + + pingDelaySecsStr); + return null; + } + + String url = getTextOfLastElementHavingTag(doc, "notification-url"); + + if (url == null) { + // no URL, so write the HTML locally and provide a URL from that + + // Read the HTML. + // + String html = getTextOfLastElementHavingTag(doc, "notification"); + + if (html == null) { + // Not valid; quietly fail. + // + branch.log(CHECK_ERROR, "Missing <notification>"); + return null; + } + PrintWriter writer = null; + try { + String tempDir = System.getProperty("java.io.tmpdir"); + File updateHtml = new File(tempDir, "gwt-update-" + + currentReleasedVersion + ".html"); + writer = new PrintWriter(new FileOutputStream(updateHtml)); + writer.print(html); + url = "file://" + updateHtml.getAbsolutePath(); + } finally { + if (writer != null) { + writer.close(); + } + } + } + + // Okay -- this is a valid response. + // + return processResponse(branch, prefs, currentReleasedVersion, + pingDelaySecs, url); + } + + private UpdateResult processResponse(TreeLogger branch, Preferences prefs, + final GwtVersion serverVersion, int pingDelaySecs, final String notifyUrl) { + + // Record a ping; don't ping again until the delay is up. + // + long currentTimeMillis = System.currentTimeMillis(); + long nextPingTime = currentTimeMillis + pingDelaySecs * 1000; + prefs.put(NEXT_PING, String.valueOf(nextPingTime)); + prefs.put(LAST_PING, String.valueOf(currentTimeMillis)); + + branch.log(CHECK_INFO, "Ping delay is " + pingDelaySecs + "; next ping at " + + new Date(nextPingTime)); + + if (myVersion.isNoNagVersion()) { + // If the version number indicates no nagging about updates, exit here + // once we have recorded the next ping time. No-nag versions (ie, + // trunk builds) should also not update the highest version that has been + // run. + return null; + } + + // Update the highest version of GWT that has been run if we are later. + GwtVersion highestRunVersion = new GwtVersion(prefs.get( + HIGHEST_RUN_VERSION, null)); + if (myVersion.compareTo(highestRunVersion) > 0) { + highestRunVersion = myVersion; + prefs.put(HIGHEST_RUN_VERSION, highestRunVersion.toString()); + } + + // Are we up to date already? + // + if (highestRunVersion.compareTo(serverVersion) >= 0) { + // Yes, we are. + // + branch.log(CHECK_INFO, "Server version (" + serverVersion + + ") is not newer than " + highestRunVersion); + return null; + } + + // Commence nagging. + // + URL url = null; + try { + url = new URL(notifyUrl); + } catch (MalformedURLException e) { + logger.log(CHECK_ERROR, "Malformed notify URL: " + notifyUrl, e); + } + final URL finalUrl = url; + return new UpdateResult() { + public GwtVersion getNewVersion() { + return serverVersion; + } + + public URL getURL() { + return finalUrl; + } + }; + } }
diff --git a/dev/core/src/com/google/gwt/dev/shell/PlatformSpecific.java b/dev/core/src/com/google/gwt/dev/shell/PlatformSpecific.java index 30a834d..cd25809 100644 --- a/dev/core/src/com/google/gwt/dev/shell/PlatformSpecific.java +++ b/dev/core/src/com/google/gwt/dev/shell/PlatformSpecific.java
@@ -17,12 +17,20 @@ 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.dev.shell.CheckForUpdates.UpdateResult; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +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; /** * Performs platform-specific class selection. @@ -38,12 +46,51 @@ "com.google.gwt.dev.shell.mac.BrowserWidgetSaf"}; /** - * 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.CheckForUpdates"}; + + 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 BrowserWidget createBrowserWidget(TreeLogger logger, Composite parent, BrowserWidgetHost host) @@ -51,10 +98,11 @@ Throwable caught = null; try { for (int i = 0; i < browserClassNames.length; i++) { - Class<BrowserWidget> clazz = null; + Class<? extends BrowserWidget> clazz = null; try { - clazz = (Class<BrowserWidget>) Class.forName(browserClassNames[i]); - Constructor<BrowserWidget> ctor = clazz.getDeclaredConstructor(new Class[] { + clazz = Class.forName(browserClassNames[i]).asSubclass( + BrowserWidget.class); + Constructor<? extends BrowserWidget> ctor = clazz.getDeclaredConstructor(new Class[] { Shell.class, BrowserWidgetHost.class}); BrowserWidget bw = ctor.newInstance(new Object[] {parent, host}); return bw; @@ -85,16 +133,25 @@ throw new UnableToCompleteException(); } - public static CheckForUpdates createUpdateChecker() { + 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) { @@ -102,4 +159,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/core/src/com/google/gwt/dev/shell/ShellMainWindow.java b/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java index 031cc44..0e58953 100644 --- a/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java +++ b/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java
@@ -181,7 +181,7 @@ private Toolbar toolbar; public ShellMainWindow(BrowserWindowController browserWindowController, - final Shell parent, int serverPort, boolean checkForUpdates) { + final Shell parent, int serverPort) { super(parent, SWT.NONE); this.browserWindowController = browserWindowController; @@ -227,41 +227,6 @@ data.verticalAlignment = GridData.FILL; logPane.setLayoutData(data); } - - // check for updates - if (checkForUpdates) { - try { - final CheckForUpdates updateChecker = PlatformSpecific.createUpdateChecker(); - if (updateChecker != null) { - final CheckForUpdates.UpdateAvailableCallback callback = new CheckForUpdates.UpdateAvailableCallback() { - public void onUpdateAvailable(final String html) { - // Do this on the main thread. - // - parent.getDisplay().asyncExec(new Runnable() { - public void run() { - new BrowserDialog(parent, getLogger(), html).open(true); - } - - }); - } - }; - - // Run the update checker on a background thread. - // - Thread checkerThread = new Thread() { - @Override - public void run() { - updateChecker.check(callback); - } - }; - - checkerThread.setDaemon(true); - checkerThread.start(); - } - } catch (Throwable e) { - // Always silently ignore any errors. - } - } } public AbstractTreeLogger getLogger() {
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerDisableUpdateCheck.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerDisableUpdateCheck.java new file mode 100644 index 0000000..142f69c --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerDisableUpdateCheck.java
@@ -0,0 +1,51 @@ +/* + * 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.util.arg; + +import com.google.gwt.util.tools.ArgHandlerFlag; + +/** + * Handles the -XdisableUpdateCheck command line flag. + */ +public final class ArgHandlerDisableUpdateCheck extends ArgHandlerFlag { + + private final OptionDisableUpdateCheck option; + + public ArgHandlerDisableUpdateCheck(OptionDisableUpdateCheck option) { + this.option = option; + } + + @Override + public String getPurpose() { + return "Disable the check to see if an update version of GWT is available"; + } + + @Override + public String getTag() { + return "-XdisableUpdateCheck"; + } + + @Override + public boolean isUndocumented() { + return true; + } + + @Override + public boolean setFlag() { + option.setDisableUpdateCheck(true); + return true; + } +}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/OptionDisableUpdateCheck.java b/dev/core/src/com/google/gwt/dev/util/arg/OptionDisableUpdateCheck.java new file mode 100644 index 0000000..085d0d2 --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/util/arg/OptionDisableUpdateCheck.java
@@ -0,0 +1,32 @@ +/* + * 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.util.arg; + +/** + * Option to set the compiler working directory. + */ +public interface OptionDisableUpdateCheck { + + /** + * Check to see if update checks are disabled. + */ + boolean isUpdateCheckDisabled(); + + /** + * Sets the disable update check flag. + */ + void setDisableUpdateCheck(boolean disabled); +}
diff --git a/dev/core/test/com/google/gwt/dev/shell/CheckForUpdatesTest.java b/dev/core/test/com/google/gwt/dev/shell/CheckForUpdatesTest.java index c3255c1..dad4351 100644 --- a/dev/core/test/com/google/gwt/dev/shell/CheckForUpdatesTest.java +++ b/dev/core/test/com/google/gwt/dev/shell/CheckForUpdatesTest.java
@@ -1,56 +1,80 @@ package com.google.gwt.dev.shell; import junit.framework.TestCase; +import com.google.gwt.dev.shell.CheckForUpdates.GwtVersion; public class CheckForUpdatesTest extends TestCase { /* - * Test method for - * 'com.google.gwt.dev.shell.CheckForUpdates.isServerVersionNewer(String, - * String)' + * Test GwtVersion comparisons */ - public final void testIsServerVersionNewer() { - assertFalse(CheckForUpdates.isServerVersionNewer(null, null)); + public final void testVersionComparison() { + GwtVersion v1 = new GwtVersion(null); + assertEquals(0, v1.compareTo(v1)); - assertFalse(CheckForUpdates.isServerVersionNewer("1", "2")); - assertFalse(CheckForUpdates.isServerVersionNewer("2", "1")); + v1 = new GwtVersion("1"); + assertEquals(0, v1.compareTo(v1)); + GwtVersion v2 = new GwtVersion("2"); + assertTrue(v1.compareTo(v2) < 0); + assertTrue(v2.compareTo(v1) > 0); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", null)); - assertFalse(CheckForUpdates.isServerVersionNewer(null, "1.2.3")); + v1 = new GwtVersion("1.2.3"); + v2 = new GwtVersion(null); + assertTrue(v1.compareTo(v2) > 0); + assertTrue(v2.compareTo(v1) < 0); - assertFalse(CheckForUpdates.isServerVersionNewer("2", "1.2.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "2")); + v1 = new GwtVersion("1.2.3"); + v2 = new GwtVersion("2.0.0"); + assertTrue(v1.compareTo(v2) < 0); + assertTrue(v2.compareTo(v1) > 0); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "2.3.4.5")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3.4", "2.3.4")); + v1 = new GwtVersion("1.2.99"); + v2 = new GwtVersion("2.0.0"); + assertTrue(v1.compareTo(v2) < 0); + assertTrue(v2.compareTo(v1) > 0); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "1.2.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.3000", - "1000.2000.3000")); - assertFalse(CheckForUpdates.isServerVersionNewer("001.002.003", "1.2.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "001.002.003")); + v1 = new GwtVersion("1.2.99"); + v2 = new GwtVersion("1.3.0"); + assertTrue(v1.compareTo(v2) < 0); + assertTrue(v2.compareTo(v1) > 0); - assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "2.2.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("2.2.3", "1.2.3")); + v1 = new GwtVersion("001.002.099"); + v2 = new GwtVersion("1.2.99"); + assertEquals(0, v1.compareTo(v2)); - assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "1.3.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.3.3", "1.2.3")); - - assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "1.2.4")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.2.4", "1.2.3")); - - assertTrue(CheckForUpdates.isServerVersionNewer("1000.2000.3000", - "1000.2000.4000")); - assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.4000", - "1000.2000.3000")); - - assertTrue(CheckForUpdates.isServerVersionNewer("1000.2000.3000", - "1000.2000.3001")); - assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.3001", - "1000.2000.3000")); - - assertTrue(CheckForUpdates.isServerVersionNewer("0.2.3", "1.1.3")); - assertFalse(CheckForUpdates.isServerVersionNewer("1.1.3", "0.2.3")); + // TODO: more tests +// assertFalse(CheckForUpdates.isServerVersionNewer("2", "1.2.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "2")); +// +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "2.3.4.5")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3.4", "2.3.4")); +// +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "1.2.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.3000", +// "1000.2000.3000")); +// assertFalse(CheckForUpdates.isServerVersionNewer("001.002.003", "1.2.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.3", "001.002.003")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "2.2.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("2.2.3", "1.2.3")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "1.3.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.3.3", "1.2.3")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("1.2.3", "1.2.4")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.2.4", "1.2.3")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("1000.2000.3000", +// "1000.2000.4000")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.4000", +// "1000.2000.3000")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("1000.2000.3000", +// "1000.2000.3001")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1000.2000.3001", +// "1000.2000.3000")); +// +// assertTrue(CheckForUpdates.isServerVersionNewer("0.2.3", "1.1.3")); +// assertFalse(CheckForUpdates.isServerVersionNewer("1.1.3", "0.2.3")); } - }
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/CheckForUpdatesMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/CheckForUpdatesMoz.java deleted file mode 100644 index a1ba73d..0000000 --- a/dev/linux/src/com/google/gwt/dev/shell/moz/CheckForUpdatesMoz.java +++ /dev/null
@@ -1,31 +0,0 @@ -/* - * Copyright 2007 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.moz; - -import com.google.gwt.dev.shell.CheckForUpdates; - -/** - * Mozilla specific implementation of CheckForUpdates. - */ -public class CheckForUpdatesMoz extends CheckForUpdates { - - @Override - protected byte[] doHttpGet(String userAgent, String url) { - // Don't attempt to support proxies on Linux. - // - return httpGetNonNative(userAgent, url); - } -}
diff --git a/dev/mac/src/com/google/gwt/dev/shell/mac/CheckForUpdatesSaf.java b/dev/mac/src/com/google/gwt/dev/shell/mac/CheckForUpdatesSaf.java deleted file mode 100644 index 34ad6e2..0000000 --- a/dev/mac/src/com/google/gwt/dev/shell/mac/CheckForUpdatesSaf.java +++ /dev/null
@@ -1,31 +0,0 @@ -/* - * Copyright 2007 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.mac; - -import com.google.gwt.dev.shell.CheckForUpdates; - -/** - * Safari specific implementation of CheckForUpdates. - */ -public class CheckForUpdatesSaf extends CheckForUpdates { - - @Override - protected byte[] doHttpGet(String userAgent, String url) { - // Don't attempt to support proxies on Linux. - // - return httpGetNonNative(userAgent, url); - } -}
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/CheckForUpdatesIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/CheckForUpdatesIE6.java index fd71509..cdd1637 100644 --- a/dev/windows/src/com/google/gwt/dev/shell/ie/CheckForUpdatesIE6.java +++ b/dev/windows/src/com/google/gwt/dev/shell/ie/CheckForUpdatesIE6.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.shell.ie; +import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.dev.shell.CheckForUpdates; /** @@ -22,13 +23,15 @@ */ public class CheckForUpdatesIE6 extends CheckForUpdates { - public CheckForUpdatesIE6() { + public CheckForUpdatesIE6(TreeLogger logger, String entryPoint) { + super(logger, entryPoint); LowLevelIE6.init(); } @Override - protected byte[] doHttpGet(String userAgent, String url) { - byte[] response = LowLevelIE6.httpGet(userAgent, url); + protected byte[] doHttpGet(TreeLogger branch, String userAgent, String url) { + byte[] response = LowLevelIE6.httpGet(branch, userAgent, url, + System.getProperty(PROPERTY_DEBUG_HTTP_GET) != null); return response; }
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/LowLevelIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/LowLevelIE6.java index 0a95c60..19b0613 100644 --- a/dev/windows/src/com/google/gwt/dev/shell/ie/LowLevelIE6.java +++ b/dev/windows/src/com/google/gwt/dev/shell/ie/LowLevelIE6.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.shell.ie; +import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.dev.shell.LowLevel; /** @@ -32,15 +33,17 @@ * @return the bytes of the full response (including headers), or * <code>null</code> if there's a problem */ - public static byte[] httpGet(String userAgent, String url) { + public static byte[] httpGet(TreeLogger branch, String userAgent, String url, + boolean debugFlag) { init(); byte[][] out = new byte[1][]; int status = _httpGet(userAgent, url, out); if (status == 0) { return out[0]; } else { - if (System.getProperty("gwt.debugLowLevelHttpGet") != null) { - System.err.println("GET failed with status " + status + " for " + url); + if (debugFlag) { + branch.log(TreeLogger.ERROR, "GET failed with status " + status + + " for " + url); } return null; }
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java index b913922..9e06b9e 100644 --- a/user/src/com/google/gwt/junit/JUnitShell.java +++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -28,6 +28,7 @@ import com.google.gwt.dev.cfg.Properties; import com.google.gwt.dev.cfg.Property; import com.google.gwt.dev.javac.CompilationUnit; +import com.google.gwt.dev.shell.CheckForUpdates; import com.google.gwt.dev.util.arg.ArgHandlerLogLevel; import com.google.gwt.dev.util.log.PrintWriterTreeLogger; import com.google.gwt.junit.client.TimeoutException; @@ -498,11 +499,11 @@ } /** - * Never check for updates in JUnit mode. + * Check for updates once a minute. */ @Override - protected boolean doShouldCheckForUpdates() { - return false; + protected long checkForUpdatesInterval() { + return CheckForUpdates.ONE_MINUTE; } @Override