digest.txt for a Getdown
+ * An ant task used to create a {@code digest.txt} for a Getdown
* application deployment.
*/
public class DigesterTask extends Task
diff --git a/core/src/it/java/com/threerings/getdown/tests/DigesterIT.java b/core/src/it/java/com/threerings/getdown/tests/DigesterIT.java
index 52b4b5e..d2ddaf2 100644
--- a/core/src/it/java/com/threerings/getdown/tests/DigesterIT.java
+++ b/core/src/it/java/com/threerings/getdown/tests/DigesterIT.java
@@ -5,16 +5,16 @@
package com.threerings.getdown.tests;
-import java.io.File;
import java.nio.charset.StandardCharsets;
-import java.nio.file.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
-import org.junit.*;
-import static org.junit.Assert.*;
-
import com.threerings.getdown.tools.Digester;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
public class DigesterIT {
@@ -32,23 +32,23 @@ public class DigesterIT {
Files.delete(digest2);
assertEquals(Arrays.asList(
- "getdown.txt = 779c74fb4b251e18faf6e240a0667964",
+ "getdown.txt = 9c9b2494929c99d44ae51034d59e1a1b",
"testapp.jar = 404dafa55e78b25ec0e3a936357b1883",
"funny%test dir/some=file.txt = d8e8fca2dc0f896fd7cb4cb0031ba249",
"crazyhashfile#txt = f29d23fd5ab1781bd8d0760b3a516f16",
"foo.jar = 46ca4cc9079d9d019bb30cd21ebbc1ec",
"script.sh = f66e8ea25598e67e99c47d9b0b2a2cdf",
- "digest.txt = f5561d85e4d80cc85883963897e58ff6"
+ "digest.txt = 11f9ba349cf9edacac4d72a3158447e5"
), digestLines);
assertEquals(Arrays.asList(
- "getdown.txt = 4f0c657895c3c3a35fa55bf5951c64fa9b0694f8fc685af3f1d8635c639e066b",
+ "getdown.txt = 1efecfae2a189002a6658f17d162b1922c7bde978944949276dc038a0df2461f",
"testapp.jar = c9cb1906afbf48f8654b416c3f831046bd3752a76137e5bf0a9af2f790bf48e0",
"funny%test dir/some=file.txt = f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2",
"crazyhashfile#txt = 6816889f922de38f145db215a28ad7c5e1badf7354b5cdab225a27486789fa3b",
"foo.jar = ea188b872e0496debcbe00aaadccccb12a8aa9b025bb62c130cd3d9b8540b062",
"script.sh = cca1c5c7628d9bf7533f655a9cfa6573d64afb8375f81960d1d832dc5135c988",
- "digest2.txt = 70b442c9f56660561921da3368e1a206f05c379182fab3062750b7ddcf303407"
+ "digest2.txt = 41eacdabda8909bdbbf61e4f980867f4003c16a12f6770e6fc619b6af100e05b"
), digest2Lines);
}
}
diff --git a/core/src/it/resources/testapp/getdown.txt b/core/src/it/resources/testapp/getdown.txt
index 3e0e538..ab0e473 100644
--- a/core/src/it/resources/testapp/getdown.txt
+++ b/core/src/it/resources/testapp/getdown.txt
@@ -13,6 +13,18 @@ apparg = %APPDIR%
# test the %env% mechanism
jvmarg = -Dusername=\%ENV.USER%
+# test various java_*** configs, they are not interesting for digester
+java_local_dir = jre
+java_max_version = 1089999
+java_min_version = [windows] 1080111
+java_min_version = [!windows] 1080192
+java_exact_version_required = [linux] true
+java_location = [linux-amd64] /files/java/java_linux_64.zip
+java_location = [linux-i386] /files/java/java_linux_32.zip
+java_location = [mac] /files/java/java_mac_64.zip
+java_location = [windows-amd64] /files/java/java_windows_64.zip
+java_location = [windows-x86] /files/java/java_windows_32.zip
+
strict_comments = true
resource = funny%test dir/some=file.txt
resource = crazyhashfile#txt
diff --git a/core/src/main/java/com/threerings/getdown/Log.java b/core/src/main/java/com/threerings/getdown/Log.java
index d00a131..da98c90 100644
--- a/core/src/main/java/com/threerings/getdown/Log.java
+++ b/core/src/main/java/com/threerings/getdown/Log.java
@@ -15,7 +15,7 @@ import java.util.logging.*;
/**
* A placeholder class that contains a reference to the log object used by the Getdown code.
*/
-public class Log
+public final class Log
{
public static class Shim {
/**
@@ -143,6 +143,5 @@ public class Log
protected FieldPosition _fpos = new FieldPosition(SimpleDateFormat.DATE_FIELD);
}
- protected static final String DATE_FORMAT = "{0,date} {0,time}";
protected static final Level[] LEVELS = {Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE};
}
diff --git a/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java b/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java
index ae18990..7e01e87 100644
--- a/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java
+++ b/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java
@@ -96,6 +96,6 @@ public class GarbageCollector
private static File getCachedFile (File file)
{
return !isLastAccessedFile(file) ? file : new File(
- file.getParentFile(), file.getName().substring(0, file.getName().lastIndexOf(".")));
+ file.getParentFile(), file.getName().substring(0, file.getName().lastIndexOf('.')));
}
}
diff --git a/core/src/main/java/com/threerings/getdown/cache/ResourceCache.java b/core/src/main/java/com/threerings/getdown/cache/ResourceCache.java
index 0210e9a..41f0c5f 100644
--- a/core/src/main/java/com/threerings/getdown/cache/ResourceCache.java
+++ b/core/src/main/java/com/threerings/getdown/cache/ResourceCache.java
@@ -69,7 +69,7 @@ public class ResourceCache
private String getFileSuffix (File fileToCache) {
String fileName = fileToCache.getName();
- int index = fileName.lastIndexOf(".");
+ int index = fileName.lastIndexOf('.');
return index > -1 ? fileName.substring(index) : "";
}
diff --git a/core/src/main/java/com/threerings/getdown/data/Application.java b/core/src/main/java/com/threerings/getdown/data/Application.java
index 06eab4d..a1deca4 100644
--- a/core/src/main/java/com/threerings/getdown/data/Application.java
+++ b/core/src/main/java/com/threerings/getdown/data/Application.java
@@ -7,7 +7,6 @@ package com.threerings.getdown.data;
import java.io.*;
import java.lang.reflect.Method;
-import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
@@ -23,8 +22,8 @@ import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.zip.GZIPInputStream;
+import com.threerings.getdown.net.Connector;
import com.threerings.getdown.util.*;
// avoid ambiguity with java.util.Base64 which we can't use as it's 1.8+
import com.threerings.getdown.util.Base64;
@@ -33,7 +32,7 @@ import static com.threerings.getdown.Log.log;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
- * Parses and provide access to the information contained in the getdown.txt
+ * Parses and provide access to the information contained in the {@code getdown.txt}
* configuration file.
*/
public class Application
@@ -212,10 +211,10 @@ public class Application
* Used by {@link #verifyMetadata} to communicate status in circumstances where it needs to
* take network actions.
*/
- public static interface StatusDisplay
+ public interface StatusDisplay
{
/** Requests that the specified status message be displayed. */
- public void updateStatus (String message);
+ void updateStatus (String message);
}
/**
@@ -233,19 +232,56 @@ public class Application
}
}
- /** The proxy that should be used to do HTTP downloads. This must be configured prior to using
- * the application instance. Yes this is a public mutable field, no I'm not going to create a
+ /**
+ * Reads the {@code getdown.txt} config file into a {@code Config} object and returns it.
+ */
+ public static Config readConfig (EnvConfig envc, boolean checkPlatform) throws IOException {
+ Config config = null;
+ File cfgfile = new File(envc.appDir, CONFIG_FILE);
+ Config.ParseOpts opts = Config.createOpts(checkPlatform);
+ try {
+ // if we have a configuration file, read the data from it
+ if (cfgfile.exists()) {
+ config = Config.parseConfig(cfgfile, opts);
+ }
+ // otherwise, try reading data from our backup config file; thanks to funny windows
+ // bullshit, we have to do this backup file fiddling in case we got screwed while
+ // updating getdown.txt during normal operation
+ else if ((cfgfile = new File(envc.appDir, Application.CONFIG_FILE + "_old")).exists()) {
+ config = Config.parseConfig(cfgfile, opts);
+ }
+ // otherwise, issue a warning that we found no getdown file
+ else {
+ log.info("Found no getdown.txt file", "appdir", envc.appDir);
+ }
+ } catch (Exception e) {
+ log.warning("Failure reading config file", "file", config, e);
+ }
+
+ // if we failed to read our config file, check for an appbase specified via a system
+ // property; we can use that to bootstrap ourselves back into operation
+ if (config == null) {
+ log.info("Using 'appbase' from bootstrap config", "appbase", envc.appBase);
+ Mapgetdown.txt
+ * Creates an application instance which records the location of the {@code getdown.txt}
* configuration file from the supplied application directory.
*
*/
public Application (EnvConfig envc) {
_envc = envc;
- _config = new File(envc.appDir, CONFIG_FILE);
}
/**
@@ -369,8 +405,7 @@ public class Application
*/
public Listgetdown.txt file based on information parsed from a
+ * Attempts to redownload the {@code getdown.txt} file based on information parsed from a
* previous call to {@link #init}.
*/
public void attemptRecovery (StatusDisplay status)
@@ -893,7 +920,7 @@ public class Application
}
/**
- * Downloads and replaces the getdown.txt and digest.txt files with
+ * Downloads and replaces the {@code getdown.txt} and {@code digest.txt} files with
* those for the target version of our application.
*/
public void updateMetadata ()
@@ -904,7 +931,7 @@ public class Application
_vappbase = createVAppBase(_targetVersion);
} catch (MalformedURLException mue) {
String err = MessageUtil.tcompose("m.invalid_appbase", _appbase);
- throw (IOException) new IOException(err).initCause(mue);
+ throw new IOException(err, mue);
}
try {
@@ -961,16 +988,8 @@ public class Application
args.add("-Xdock:name=" + _dockName);
}
- // pass along our proxy settings
- if (proxy.type() == Proxy.Type.HTTP && proxy.address() instanceof InetSocketAddress) {
- InetSocketAddress proxyAddr = (InetSocketAddress) proxy.address();
- String proxyHost = proxyAddr.getHostString();
- int proxyPort = proxyAddr.getPort();
- args.add("-Dhttp.proxyHost=" + proxyHost);
- args.add("-Dhttp.proxyPort=" + proxyPort);
- args.add("-Dhttps.proxyHost=" + proxyHost);
- args.add("-Dhttps.proxyPort=" + proxyPort);
- }
+ // forward our proxy settings
+ conn.addProxyArgs(args);
// add the marker indicating the app is running in getdown
args.add("-D" + Properties.GETDOWN + "=true");
@@ -1080,7 +1099,7 @@ public class Application
for (String jvmarg : _jvmargs) {
if (jvmarg.startsWith("-D")) {
jvmarg = processArg(jvmarg.substring(2));
- int eqidx = jvmarg.indexOf("=");
+ int eqidx = jvmarg.indexOf('=');
if (eqidx == -1) {
log.warning("Bogus system property: '" + jvmarg + "'?");
} else {
@@ -1121,10 +1140,6 @@ public class Application
/** Replaces the application directory and version in any argument. */
protected String processArg (String arg)
{
- if (arg == null) {
- return null;
- }
-
arg = arg.replace("%APPDIR%", getAppDir().getAbsolutePath());
arg = arg.replace("%VERSION%", String.valueOf(_version));
@@ -1146,8 +1161,8 @@ public class Application
}
/**
- * Loads the digest.txt file and verifies the contents of both that file and the
- * getdown.text file. Then it loads the version.txt and decides
+ * Loads the {@code digest.txt} file and verifies the contents of both that file and the
+ * {@code getdown.text} file. Then it loads the {@code version.txt} and decides
* whether or not the application needs to be updated or whether we can proceed to verification
* and execution.
*
@@ -1234,11 +1249,11 @@ public class Application
}
if (_latest != null) {
- try (InputStream in = ConnectionUtil.open(proxy, _latest, 0, 0).getInputStream();
- InputStreamReader reader = new InputStreamReader(in, UTF_8);
- BufferedReader bin = new BufferedReader(reader)) {
- for (String[] pair : Config.parsePairs(bin, Config.createOpts(false))) {
- if (pair[0].equals("version")) {
+ try {
+ Listdigest.txt file and the computing and processing of digests for an
+ * Manages the {@code digest.txt} file and the computing and processing of digests for an
* application.
*/
public class Digest
@@ -72,8 +72,7 @@ public class Digest
digests.put(rsrc, rsrc.computeDigest(fversion, md, null));
completed.add(rsrc);
} catch (Throwable t) {
- completed.add(new IOException("Error computing digest for: " + rsrc).
- initCause(t));
+ completed.add(new IOException("Error computing digest for: " + rsrc, t));
}
}
});
@@ -88,7 +87,7 @@ public class Digest
if (done instanceof IOException) {
throw (IOException)done;
} else if (done instanceof Resource) {
- pending.remove((Resource)done);
+ pending.remove(done);
} else {
throw new AssertionError("What is this? " + done);
}
diff --git a/core/src/main/java/com/threerings/getdown/data/EnvConfig.java b/core/src/main/java/com/threerings/getdown/data/EnvConfig.java
index 1d66ebb..a14b02c 100644
--- a/core/src/main/java/com/threerings/getdown/data/EnvConfig.java
+++ b/core/src/main/java/com/threerings/getdown/data/EnvConfig.java
@@ -19,7 +19,7 @@ public final class EnvConfig {
/** Used to report problems or feedback by {@link #create}. */
public static final class Note {
- public static enum Level { INFO, WARN, ERROR };
+ public enum Level { INFO, WARN, ERROR }
public static Note info (String msg) { return new Note(Level.INFO, msg); }
public static Note warn (String msg) { return new Note(Level.WARN, msg); }
public static Note error (String msg) { return new Note(Level.ERROR, msg); }
diff --git a/core/src/main/java/com/threerings/getdown/data/Resource.java b/core/src/main/java/com/threerings/getdown/data/Resource.java
index c7c380c..d1ccba3 100644
--- a/core/src/main/java/com/threerings/getdown/data/Resource.java
+++ b/core/src/main/java/com/threerings/getdown/data/Resource.java
@@ -23,7 +23,7 @@ import static com.threerings.getdown.Log.log;
public class Resource implements Comparablenvdir directory with name
- * patchV.dat where V is the old application version.
+ * created in the {@code nvdir} directory with name
+ * {@code patchV.dat} where V is the old application version.
*/
public void createDiff (File nvdir, File ovdir, boolean verbose)
throws IOException
@@ -53,13 +60,13 @@ public class Differ
Application oapp = new Application(new EnvConfig(ovdir));
oapp.init(false);
- ArrayListos.
+ * Creates a patch from the two passed in files, writing the result to {@code os}.
*/
public static void createPatch (String oldPath, String newPath,
OutputStream os, boolean minimal) throws IOException
@@ -83,10 +83,10 @@ public class JarDiff implements JarDiffCodes
try (ZipFile2 oldArchive = new ZipFile2(oldPath);
ZipFile2 newArchive = new ZipFile2(newPath)) {
- HashMapjos.
- * oldEntries gives the names of the files that were removed,
- * movedMap maps from the new name to the old name.
+ * Writes the index file out to {@code jos}.
+ * {@code oldEntries} gives the names of the files that were removed,
+ * {@code movedMap} maps from the new name to the old name.
*/
private static void createIndex (ZipOutputStream jos, ListString[] instances containing the key/value pairs in the
+ * @return a list of {@code String[]} instances containing the key/value pairs in the
* order they were parsed from the file.
*/
public static Listversion.txt file into the specified application directory and
+ * Writes a {@code version.txt} file into the specified application directory and
* attempts to relaunch Getdown in that directory which will cause it to upgrade to the newly
* specified version and relaunch the application.
*
* @param appdir the directory in which the application is installed.
* @param getdownJarName the name of the getdown jar file in the application directory. This is
- * probably getdown-pro.jar or getdown-retro-pro.jar if you are using
+ * probably {@code getdown-pro.jar} or {@code getdown-retro-pro.jar} if you are using
* the results of the standard build.
* @param newVersion the new version to which Getdown will update when it is executed.
* @param javaLocalDir the name of the directory (inside {@code appdir}) that contains a
@@ -41,7 +41,7 @@ public class LaunchUtil
* after making this call as it will be upgraded and restarted. If false is returned, the
* application should tell the user that they must restart the application manually.
*
- * @exception IOException thrown if we were unable to create the version.txt file
+ * @exception IOException thrown if we were unable to create the {@code version.txt} file
* in the supplied application directory. If the version.txt file cannot be created, restarting
* Getdown will not cause the application to be upgraded, so the application will have to
* resort to telling the user that it is in a bad way.
@@ -177,23 +177,23 @@ public class LaunchUtil
public static boolean mustMonitorChildren ()
{
String osname = System.getProperty("os.name", "").toLowerCase(Locale.ROOT);
- return (osname.indexOf("windows 98") != -1 || osname.indexOf("windows me") != -1);
+ return (osname.contains("windows 98") || osname.contains("windows me"));
}
/**
* Returns true if we're running in a JVM that identifies its operating system as Windows.
*/
- public static final boolean isWindows () { return _isWindows; }
+ public static boolean isWindows () { return _isWindows; }
/**
* Returns true if we're running in a JVM that identifies its operating system as MacOS.
*/
- public static final boolean isMacOS () { return _isMacOS; }
+ public static boolean isMacOS () { return _isMacOS; }
/**
* Returns true if we're running in a JVM that identifies its operating system as Linux.
*/
- public static final boolean isLinux () { return _isLinux; }
+ public static boolean isLinux () { return _isLinux; }
/**
* Checks whether a Java Virtual Machine can be located in the supplied path.
@@ -232,10 +232,9 @@ public class LaunchUtil
try {
String osname = System.getProperty("os.name");
osname = (osname == null) ? "" : osname;
- _isWindows = (osname.indexOf("Windows") != -1);
- _isMacOS = (osname.indexOf("Mac OS") != -1 ||
- osname.indexOf("MacOS") != -1);
- _isLinux = (osname.indexOf("Linux") != -1);
+ _isWindows = (osname.contains("Windows"));
+ _isMacOS = (osname.contains("Mac OS") || osname.contains("MacOS"));
+ _isLinux = (osname.contains("Linux"));
} catch (Exception e) {
// can't grab system properties; we'll just pretend we're not on any of these OSes
}
diff --git a/core/src/main/java/com/threerings/getdown/util/MessageUtil.java b/core/src/main/java/com/threerings/getdown/util/MessageUtil.java
index 28dbdcf..f2ee9a2 100644
--- a/core/src/main/java/com/threerings/getdown/util/MessageUtil.java
+++ b/core/src/main/java/com/threerings/getdown/util/MessageUtil.java
@@ -5,7 +5,7 @@
package com.threerings.getdown.util;
-public class MessageUtil {
+public final class MessageUtil {
/**
* Returns whether or not the provided string is tainted. See {@link #taint}. Null strings
@@ -101,11 +101,11 @@ public class MessageUtil {
}
/**
- * Used to escape single quotes so that they are not interpreted by MessageFormat.
+ * Used to escape single quotes so that they are not interpreted by {@code MessageFormat}.
* As we assume all single quotes are to be escaped, we cannot use the characters
* { and } in our translation strings, but this is a small price to
* pay to have to differentiate between messages that will and won't eventually be parsed by a
- * MessageFormat instance.
+ * {@code MessageFormat} instance.
*/
public static String escape (String message)
{
diff --git a/core/src/main/java/com/threerings/getdown/util/ProgressObserver.java b/core/src/main/java/com/threerings/getdown/util/ProgressObserver.java
index ad4c560..ac3e0a3 100644
--- a/core/src/main/java/com/threerings/getdown/util/ProgressObserver.java
+++ b/core/src/main/java/com/threerings/getdown/util/ProgressObserver.java
@@ -14,5 +14,5 @@ public interface ProgressObserver
* Informs the observer that we have completed the specified
* percentage of the process.
*/
- public void progress (int percent);
+ void progress (int percent);
}
diff --git a/core/src/main/java/com/threerings/getdown/util/StreamUtil.java b/core/src/main/java/com/threerings/getdown/util/StreamUtil.java
index 373cfff..5cb1a40 100644
--- a/core/src/main/java/com/threerings/getdown/util/StreamUtil.java
+++ b/core/src/main/java/com/threerings/getdown/util/StreamUtil.java
@@ -11,11 +11,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
-import java.nio.charset.Charset;
import static com.threerings.getdown.Log.log;
-public class StreamUtil {
+public final class StreamUtil {
/**
* Convenient close for a stream. Use in a finally clause and love life.
*/
diff --git a/core/src/main/java/com/threerings/getdown/util/StringUtil.java b/core/src/main/java/com/threerings/getdown/util/StringUtil.java
index 03d3c9c..86277c8 100644
--- a/core/src/main/java/com/threerings/getdown/util/StringUtil.java
+++ b/core/src/main/java/com/threerings/getdown/util/StringUtil.java
@@ -7,14 +7,14 @@ package com.threerings.getdown.util;
import java.util.StringTokenizer;
-public class StringUtil {
+public final class StringUtil {
/**
* @return true if the specified string could be a valid URL (contains no illegal characters)
*/
public static boolean couldBeValidUrl (String url)
{
- return url.matches("[A-Za-z0-9\\-\\._~:/\\?#\\[\\]@!$&'\\(\\)\\*\\+,;=%]+");
+ return url.matches("[A-Za-z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=%]+");
}
/**
@@ -84,7 +84,7 @@ public class StringUtil {
source = source.replace(",,", "%COMMA%");
// count up the number of tokens
- while ((tpos = source.indexOf(",", tpos+1)) != -1) {
+ while ((tpos = source.indexOf(',', tpos+1)) != -1) {
tcount++;
}
@@ -92,7 +92,7 @@ public class StringUtil {
tpos = -1; tcount = 0;
// do the split
- while ((tpos = source.indexOf(",", tpos+1)) != -1) {
+ while ((tpos = source.indexOf(',', tpos+1)) != -1) {
tokens[tcount] = source.substring(tstart, tpos);
tokens[tcount] = tokens[tcount].trim().replace("%COMMA%", ",");
if (intern) {
@@ -119,7 +119,7 @@ public class StringUtil {
/**
* Generates a string from the supplied bytes that is the HEX encoded representation of those
- * bytes. Returns the empty string for a null or empty byte array.
+ * bytes. Returns the empty string for a {@code null} or empty byte array.
*
* @param bytes the bytes for which we want a string representation.
* @param count the number of bytes to stop at (which will be coerced into being {@code <=} the
@@ -185,7 +185,7 @@ public class StringUtil {
}
/**
- * Helper function for the various join methods.
+ * Helper function for the various {@code join} methods.
*/
protected static String join (Object[] values, String separator, boolean escape)
{
@@ -201,6 +201,6 @@ public class StringUtil {
return buf.toString();
}
- /** Used by {@link #hexlate} and {@link #unhexlate}. */
+ /** Used by {@link #hexlate}. */
protected static final String XLATE = "0123456789abcdef";
}
diff --git a/core/src/main/java/com/threerings/getdown/util/VersionUtil.java b/core/src/main/java/com/threerings/getdown/util/VersionUtil.java
index 49e4e6e..b2f2894 100644
--- a/core/src/main/java/com/threerings/getdown/util/VersionUtil.java
+++ b/core/src/main/java/com/threerings/getdown/util/VersionUtil.java
@@ -22,7 +22,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Version related utilities.
*/
-public class VersionUtil
+public final class VersionUtil
{
/**
* Reads a version number from a file.
diff --git a/launcher/pom.xml b/launcher/pom.xml
index 8b32172..3b14aba 100644
--- a/launcher/pom.xml
+++ b/launcher/pom.xml
@@ -38,6 +38,12 @@
message.
+ * Update the status to indicate getdown has failed for the reason in {@code message}.
*/
protected void fail (String message)
{
@@ -930,14 +956,14 @@ public abstract class Getdown extends Thread
do {
URL url = _app.getTrackingProgressURL(++_reportedProgress);
if (url != null) {
- new ProgressReporter(url).start();
+ reportProgress(url);
}
} while (_reportedProgress <= progress);
} else {
URL url = _app.getTrackingURL(event);
if (url != null) {
- new ProgressReporter(url).start();
+ reportProgress(url);
}
}
}
@@ -1000,44 +1026,40 @@ public abstract class Getdown extends Thread
}
/** Used to fetch a progress report URL. */
- protected class ProgressReporter extends Thread
- {
- public ProgressReporter (URL url) {
- setDaemon(true);
- _url = url;
- }
-
- @Override
- public void run () {
- try {
- HttpURLConnection ucon = ConnectionUtil.openHttp(_app.proxy, _url, 0, 0);
-
- // if we have a tracking cookie configured, configure the request with it
- if (_app.getTrackingCookieName() != null &&
- _app.getTrackingCookieProperty() != null) {
- String val = System.getProperty(_app.getTrackingCookieProperty());
- if (val != null) {
- ucon.setRequestProperty("Cookie", _app.getTrackingCookieName() + "=" + val);
- }
- }
-
- // now request our tracking URL and ensure that we get a non-error response
- ucon.connect();
+ protected void reportProgress (final URL url) {
+ Thread reporter = new Thread("Progress reporter") {
+ public void run () {
try {
- if (ucon.getResponseCode() != HttpURLConnection.HTTP_OK) {
- log.warning("Failed to report tracking event",
- "url", _url, "rcode", ucon.getResponseCode());
+ HttpURLConnection ucon = _app.conn.openHttp(url, 0, 0);
+
+ // if we have a tracking cookie configured, configure the request with it
+ if (_app.getTrackingCookieName() != null &&
+ _app.getTrackingCookieProperty() != null) {
+ String val = System.getProperty(_app.getTrackingCookieProperty());
+ if (val != null) {
+ ucon.setRequestProperty(
+ "Cookie", _app.getTrackingCookieName() + "=" + val);
+ }
}
- } finally {
- ucon.disconnect();
+
+ // now request our tracking URL and ensure that we get a non-error response
+ ucon.connect();
+ try {
+ if (ucon.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ log.warning("Failed to report tracking event",
+ "url", url, "rcode", ucon.getResponseCode());
+ }
+ } finally {
+ ucon.disconnect();
+ }
+
+ } catch (IOException ioe) {
+ log.warning("Failed to report tracking event", "url", url, "error", ioe);
}
-
- } catch (IOException ioe) {
- log.warning("Failed to report tracking event", "url", _url, "error", ioe);
}
- }
-
- protected URL _url;
+ };
+ reporter.setDaemon(true);
+ reporter.start();
}
/** Used to pass progress on to our user interface. */
diff --git a/launcher/src/main/java/com/threerings/getdown/launcher/GetdownApp.java b/launcher/src/main/java/com/threerings/getdown/launcher/GetdownApp.java
index fde79f3..e4e3320 100644
--- a/launcher/src/main/java/com/threerings/getdown/launcher/GetdownApp.java
+++ b/launcher/src/main/java/com/threerings/getdown/launcher/GetdownApp.java
@@ -101,7 +101,7 @@ public class GetdownApp
log.info("-- Cur dir: " + System.getProperty("user.dir"));
log.info("---------------------------------------------");
- Getdown app = new Getdown(envc) {
+ Getdown getdown = new Getdown(envc) {
@Override
protected Container createContainer () {
// create our user interface, and display it
@@ -146,7 +146,7 @@ public class GetdownApp
}
if (_ifc.iconImages != null) {
- ArrayListbackgrounds.
+ * Create a sequence of images to be rotated through from {@code backgrounds}.
*
* Each String in backgrounds should be the path to the image, a semicolon, and the minimum
* amount of time to display the image in seconds. Each image will be active for an equal
diff --git a/launcher/src/main/java/com/threerings/getdown/launcher/StatusPanel.java b/launcher/src/main/java/com/threerings/getdown/launcher/StatusPanel.java
index 99f44ca..197dc91 100644
--- a/launcher/src/main/java/com/threerings/getdown/launcher/StatusPanel.java
+++ b/launcher/src/main/java/com/threerings/getdown/launcher/StatusPanel.java
@@ -26,12 +26,9 @@ import com.samskivert.swing.Label;
import com.samskivert.swing.LabelStyleConstants;
import com.samskivert.swing.util.SwingUtil;
import com.samskivert.util.Throttle;
-
import com.threerings.getdown.data.Application.UpdateInterface;
import com.threerings.getdown.util.MessageUtil;
import com.threerings.getdown.util.Rectangle;
-import com.threerings.getdown.util.StringUtil;
-
import static com.threerings.getdown.Log.log;
/**
@@ -344,7 +341,7 @@ public final class StatusPanel extends JComponent
{
String msg = get(key);
if (msg != null) return MessageFormat.format(MessageUtil.escape(msg), (Object[])args);
- return key + String.valueOf(Arrays.asList(args));
+ return key + Arrays.asList(args);
}
/** Used by {@link #setStatus}, and {@link #setProgress}. */
diff --git a/launcher/src/main/resources/com/threerings/getdown/launcher/PacUtils.js b/launcher/src/main/resources/com/threerings/getdown/launcher/PacUtils.js
new file mode 100644
index 0000000..96a644e
--- /dev/null
+++ b/launcher/src/main/resources/com/threerings/getdown/launcher/PacUtils.js
@@ -0,0 +1,168 @@
+/**
+ * Extracted from Mozilla Firefox 3.0.4, \mozilla\netwerk\base\src\nsProxyAutoConfig.js
+ */
+function dnsDomainIs (host, domain) {
+ return (host.length >= domain.length &&
+ host.substring(host.length - domain.length) == domain);
+}
+
+function dnsDomainLevels (host) {
+ return host.split('.').length-1;
+}
+
+function convert_addr (ipchars) {
+ var bytes = ipchars.split('.');
+ var result = (((bytes[0] & 0xff) << 24) |
+ ((bytes[1] & 0xff) << 16) |
+ ((bytes[2] & 0xff) << 8) |
+ ( bytes[3] & 0xff ));
+ return result;
+}
+
+function dnsResolve (host) {
+ return resolver.dnsResolve(host)
+}
+
+function isInNet (addrOrHost, pattern, maskstr) {
+ var testRE = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+ var test = testRE.exec(addrOrHost);
+ if (test == null) {
+ addrOrHost = dnsResolve(addrOrHost);
+ if (addrOrHost == null) {
+ return false;
+ }
+ } else if (test[1] > 255 || test[2] > 255 || test[3] > 255 || test[4] > 255) {
+ return false; // not an IP address
+ }
+ var host = convert_addr(addrOrHost);
+ var pat = convert_addr(pattern);
+ var mask = convert_addr(maskstr);
+ return ((host & mask) == (pat & mask));
+}
+
+function isPlainHostName (host) {
+ return (host.search('\\.') == -1);
+}
+
+function isResolvable (host) {
+ var ip = dnsResolve(host);
+ return (ip != null);
+}
+
+function localHostOrDomainIs (host, hostdom) {
+ return (host == hostdom) || (hostdom.lastIndexOf(host + '.', 0) == 0);
+}
+
+function shExpMatch (url, pattern) {
+ pattern = pattern.replace(/\./g, '\\.');
+ pattern = pattern.replace(/\*/g, '.*');
+ pattern = pattern.replace(/\?/g, '.');
+ var newRe = new RegExp('^'+pattern+'$');
+ return newRe.test(url);
+}
+
+var wdays = {
+ SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6
+};
+
+var months = {
+ JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11
+};
+
+function weekdayRange () {
+ function getDay (weekday) {
+ if (weekday in wdays) {
+ return wdays[weekday];
+ }
+ return -1;
+ }
+ var date = new Date();
+ var argc = arguments.length;
+ var wday;
+ if (argc < 1) {
+ return false;
+ }
+ if (arguments[argc - 1] == 'GMT') {
+ argc--;
+ wday = date.getUTCDay();
+ } else {
+ wday = date.getDay();
+ }
+ var wd1 = getDay(arguments[0]);
+ var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;
+ return (wd1 == -1 || wd2 == -1) ? false : (wd1 <= wday && wday <= wd2);
+}
+
+function dateRange () {
+ function getMonth (name) {
+ if (name in months) {
+ return months[name];
+ }
+ return -1;
+ }
+ var date = new Date();
+ var argc = arguments.length;
+ if (argc < 1) {
+ return false;
+ }
+ var isGMT = (arguments[argc - 1] == 'GMT');
+ if (isGMT) {
+ argc--;
+ }
+
+ // function will work even without explict handling of this case
+ if (argc == 1) {
+ var tmp = parseInt(arguments[0]);
+ if (isNaN(tmp)) {
+ return ((isGMT ? date.getUTCMonth() : date.getMonth()) == getMonth(arguments[0]));
+ } else if (tmp < 32) {
+ return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);
+ } else {
+ return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) == tmp);
+ }
+ }
+
+ var year = date.getFullYear();
+ var date1, date2;
+ date1 = new Date(year, 0, 1, 0, 0, 0);
+ date2 = new Date(year, 11, 31, 23, 59, 59);
+ var adjustMonth = false;
+ for (var i = 0; i < (argc >> 1); i++) {
+ var tmp = parseInt(arguments[i]);
+ if (isNaN(tmp)) {
+ var mon = getMonth(arguments[i]);
+ date1.setMonth(mon);
+ } else if (tmp < 32) {
+ adjustMonth = (argc <= 2);
+ date1.setDate(tmp);
+ } else {
+ date1.setFullYear(tmp);
+ }
+ }
+ for (var i = (argc >> 1); i < argc; i++) {
+ var tmp = parseInt(arguments[i]);
+ if (isNaN(tmp)) {
+ var mon = getMonth(arguments[i]);
+ date2.setMonth(mon);
+ } else if(tmp < 32) {
+ date2.setDate(tmp);
+ } else {
+ date2.setFullYear(tmp);
+ }
+ }
+ if (adjustMonth) {
+ date1.setMonth(date.getMonth());
+ date2.setMonth(date.getMonth());
+ }
+ if (isGMT) {
+ var tmp = date;
+ tmp.setFullYear(date.getUTCFullYear());
+ tmp.setMonth(date.getUTCMonth());
+ tmp.setDate(date.getUTCDate());
+ tmp.setHours(date.getUTCHours());
+ tmp.setMinutes(date.getUTCMinutes());
+ tmp.setSeconds(date.getUTCSeconds());
+ date = tmp;
+ }
+ return ((date1 <= date) && (date <= date2));
+}
diff --git a/launcher/src/main/resources/com/threerings/getdown/messages.properties b/launcher/src/main/resources/com/threerings/getdown/messages.properties
index 92e13ee..b113c8e 100644
--- a/launcher/src/main/resources/com/threerings/getdown/messages.properties
+++ b/launcher/src/main/resources/com/threerings/getdown/messages.properties
@@ -17,6 +17,9 @@ m.configure_proxy = We were unable to connect to the application server to
Your computer may access the Internet through a proxy and we were unable to automatically \ detect your proxy settings. If you know your proxy settings, you can enter them below. +m.update_proxy_auth = The stored proxy user/password is wrong or obsolete. \ +
Please provide an updated user/password combination. + m.proxy_extra = If you are sure that you don't use a proxy then \ perhaps there is a temporary Internet outage that is preventing us from \ communicating with the servers. In this case, you can cancel and try \ diff --git a/launcher/src/main/resources/com/threerings/getdown/messages_de.properties b/launcher/src/main/resources/com/threerings/getdown/messages_de.properties index b013f15..1c3af16 100644 --- a/launcher/src/main/resources/com/threerings/getdown/messages_de.properties +++ b/launcher/src/main/resources/com/threerings/getdown/messages_de.properties @@ -16,6 +16,9 @@ m.configure_proxy = Es konnte keine Verbindung zum Applikations-Server auf Wenn kein Proxy verwendet werden soll, löschen Sie bitte alle Einträge in den unten \ stehenden Feldern und klicken sie auf OK. +m.update_proxy_auth = Gespeicherte Proxy User/Passwort Kombination ungültig oder obsolet. \ +
Bitte geben Sie die korrekte User/Passwort Kombination ein. + m.proxy_extra = Sollten Sie keine Proxyeinstellungen gesetzt haben wenden Sie sich bitte \ an Ihren Administrator. diff --git a/launcher/src/main/resources/com/threerings/getdown/messages_it.properties b/launcher/src/main/resources/com/threerings/getdown/messages_it.properties index 1328650..c2481ea 100644 --- a/launcher/src/main/resources/com/threerings/getdown/messages_it.properties +++ b/launcher/src/main/resources/com/threerings/getdown/messages_it.properties @@ -20,7 +20,11 @@ m.configure_proxy = Impossibile collegarsi al server per \ questo potrebbe non essere stato riconosciuto automaticamente. Se conosci le \ tue impostazioni del proxy, puoi inserirle di seguito. -m.proxy_extra = Se sei sicuro di non usare proxy \ +m.update_proxy_auth = Combinazione User/Password salvata per il proxy non è valida \ + oppure obsoleta. \ +
Perfavore inserire una combinazione User/Password valida. + +m.proxy_extra = Se sei sicuro di non usare proxy \ potrebbe essere un problema di internet o di collegamento con il server. \ In questo caso puoi annullare e ripetere l'installazione più tardi. diff --git a/launcher/src/test/java/com/threerings/getdown/launcher/ProxyUtilTest.java b/launcher/src/test/java/com/threerings/getdown/launcher/ProxyUtilTest.java new file mode 100644 index 0000000..e60ab90 --- /dev/null +++ b/launcher/src/test/java/com/threerings/getdown/launcher/ProxyUtilTest.java @@ -0,0 +1,137 @@ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2018 Getdown authors +// https://github.com/threerings/getdown/blob/master/LICENSE + +package com.threerings.getdown.launcher; + +import java.io.StringReader; +import java.net.URL; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class ProxyUtilTest { + + static String[] strs (String... strs) { return strs; } + + static String[] findPAC (String code, String url) throws Exception { + return ProxyUtil.findPACProxiesForURL(new StringReader(code), new URL(url)); + } + + static void testPAC (String code, String url, String... expectedProxies) throws Exception { + assertArrayEquals(expectedProxies, findPAC(code, url)); + } + + @Test public void testPACProxy () throws Exception { + String EXAMPLE0 = + "function FindProxyForURL(url, host) {\n" + + " if (shExpMatch(host, '*.example.com')) { return 'DIRECT'; }\n" + + " if (isInNet(host, '10.0.0.0', '255.255.248.0')) {\n" + + " return 'PROXY fastproxy.example.com:8080';\n" + + " }\n" + + " return 'PROXY proxy.example.com:8080; DIRECT';\n" + + "}\n"; + + testPAC(EXAMPLE0, "http://test.example.com/", "DIRECT"); + testPAC(EXAMPLE0, "http://10.0.1.1/", "PROXY fastproxy.example.com:8080"); + testPAC(EXAMPLE0, "http://chicken.gov/", "PROXY proxy.example.com:8080", "DIRECT"); + + String EXAMPLE1 = + "function FindProxyForURL(url, host) {" + + " if (isPlainHostName(host) || dnsDomainIs(host, '.mozilla.org')) {" + + " return 'DIRECT';" + + " } else {" + + " return 'PROXY w3proxy.mozilla.org:8080; DIRECT';" + + " }" + + "}"; + testPAC(EXAMPLE1, "http://test.example.com/", "PROXY w3proxy.mozilla.org:8080", "DIRECT"); + testPAC(EXAMPLE1, "http://www.mozilla.org/", "DIRECT"); + testPAC(EXAMPLE1, "http://foo.mozilla.org/", "DIRECT"); + testPAC(EXAMPLE1, "http://localhost/", "DIRECT"); + + String EXAMPLE2 = + " function FindProxyForURL(url, host) {\n" + + " if ((isPlainHostName(host) || dnsDomainIs(host, '.mozilla.org')) &&\n" + + " !localHostOrDomainIs(host, 'www.mozilla.org') &&\n" + + " !localHostOrDomainIs(host, 'merchant.mozilla.org')) {\n" + + " return 'DIRECT';\n" + + " } else {\n" + + " return 'PROXY w3proxy.mozilla.org:8080; DIRECT';\n" + + " }\n" + + " }"; + testPAC(EXAMPLE2, "http://test.example.com/", "PROXY w3proxy.mozilla.org:8080", "DIRECT"); + testPAC(EXAMPLE2, "http://www.mozilla.org/", "PROXY w3proxy.mozilla.org:8080", "DIRECT"); + testPAC(EXAMPLE2, "http://www/", "PROXY w3proxy.mozilla.org:8080", "DIRECT"); + testPAC(EXAMPLE2, "http://foo.mozilla.org/", "DIRECT"); + testPAC(EXAMPLE2, "http://localhost/", "DIRECT"); + + String EXAMPLE3A = + "function FindProxyForURL(url, host) {\n" + + " if (isResolvable(host)) return 'DIRECT';\n" + + " else return 'PROXY proxy.mydomain.com:8080';\n" + + "}"; + testPAC(EXAMPLE3A, "http://www.mozilla.org/", "DIRECT"); + testPAC(EXAMPLE3A, "http://doesnotexist.mozilla.org/", "PROXY proxy.mydomain.com:8080"); + + String EXAMPLE3B = + "function FindProxyForURL(url, host) {\n" + + " if (isPlainHostName(host) ||\n" + + " dnsDomainIs(host, '.mydomain.com') ||\n" + + " isResolvable(host)) {\n" + + " return 'DIRECT';\n" + + " } else {\n" + + " return 'PROXY proxy.mydomain.com:8080';\n" + + " }\n" + + "}"; + testPAC(EXAMPLE3B, "http://plain/", "DIRECT"); + testPAC(EXAMPLE3B, "http://foo.mydomain.com/", "DIRECT"); + testPAC(EXAMPLE3B, "http://www.mozilla.org/", "DIRECT"); + testPAC(EXAMPLE3B, "http://doesnotexist.mozilla.org/", "PROXY proxy.mydomain.com:8080"); + + // example 4 + // function FindProxyForURL(url, host) { + // if (isInNet(host, '198.95.0.0', '255.255.0.0')) return 'DIRECT'; + // else return 'PROXY proxy.mydomain.com:8080'; + // } + // function FindProxyForURL(url, host) { + // if (isPlainHostName(host) || + // dnsDomainIs(host, '.mydomain.com') || + // isInNet(host, '198.95.0.0', '255.255.0.0')) { + // return 'DIRECT'; + // } else { + // return 'PROXY proxy.mydomain.com:8080'; + // } + // } + + // example 5 + // function FindProxyForURL(url, host) { + // if (isPlainHostName(host) || dnsDomainIs(host, '.mydomain.com')) return 'DIRECT'; + // else if (shExpMatch(host, '*.com')) return 'PROXY proxy1.mydomain.com:8080; ' + + // 'PROXY proxy4.mydomain.com:8080'; + // else if (shExpMatch(host, '*.edu')) return 'PROXY proxy2.mydomain.com:8080; ' + + // 'PROXY proxy4.mydomain.com:8080'; + // else return 'PROXY proxy3.mydomain.com:8080; ' + + // 'PROXY proxy4.mydomain.com:8080'; + // } + + // example 6 + // function FindProxyForURL(url, host) { + // if (url.substring(0, 5) == 'http:') { + // return 'PROXY http-proxy.mydomain.com:8080'; + // } + // else if (url.substring(0, 4) == 'ftp:') { + // return 'PROXY ftp-proxy.mydomain.com:8080'; + // } + // else if (url.substring(0, 7) == 'gopher:') { + // return 'PROXY gopher-proxy.mydomain.com:8080'; + // } + // else if (url.substring(0, 6) == 'https:' || + // url.substring(0, 6) == 'snews:') { + // return 'PROXY security-proxy.mydomain.com:8080'; + // } else { + // return 'DIRECT'; + // } + // } + } +}