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