Consolidate & enhance "environment config" handling.

The new code is more careful about how it obtains config info, and issues
warnings when sources of info conflict. It does not abort in such circumstances
as Getdown's prime directive is to do the best it can to get the app updated
and launched. But the warnings will hopefully allow accidental conflicts to be
detected and avoided before being deployed to customers.

We also now allow bootstrap.properties to provide an appid; that matches what
was possible via system properties and command line arguments. We also avoid
"communicating" environment configuration through the Java system properties
mechanism. We now read from sysprops but do not write back to them.

Lastly, this includes some name tidying (like appdir -> appDir and
getAppdir -> getAppDir).
This commit is contained in:
Michael Bayne
2018-09-17 13:08:25 -07:00
parent ed22142488
commit 883954c3e5
11 changed files with 277 additions and 168 deletions
@@ -43,22 +43,11 @@ import ca.beq.util.win32.registry.RootKey;
import com.samskivert.swing.util.SwingUtil;
import com.threerings.getdown.data.Application.UpdateInterface.Step;
import com.threerings.getdown.data.Application;
import com.threerings.getdown.data.Build;
import com.threerings.getdown.data.Resource;
import com.threerings.getdown.data.SysProps;
import com.threerings.getdown.data.*;
import com.threerings.getdown.net.Downloader;
import com.threerings.getdown.net.HTTPDownloader;
import com.threerings.getdown.tools.Patcher;
import com.threerings.getdown.util.Config;
import com.threerings.getdown.util.ConnectionUtil;
import com.threerings.getdown.util.FileUtil;
import com.threerings.getdown.util.LaunchUtil;
import com.threerings.getdown.util.MessageUtil;
import com.threerings.getdown.util.ProgressAggregator;
import com.threerings.getdown.util.ProgressObserver;
import com.threerings.getdown.util.StringUtil;
import com.threerings.getdown.util.VersionUtil;
import com.threerings.getdown.util.*;
import static com.threerings.getdown.Log.log;
@@ -68,13 +57,7 @@ import static com.threerings.getdown.Log.log;
public abstract class Getdown extends Thread
implements Application.StatusDisplay, RotatingBackgrounds.ImageLoader
{
public Getdown (File appDir, String appId)
{
this(appDir, appId, null, null, null);
}
public Getdown (File appDir, String appId, List<Certificate> signers,
String[] jvmargs, String[] appargs)
public Getdown (EnvConfig envc)
{
super("Getdown");
try {
@@ -94,7 +77,7 @@ public abstract class Getdown extends Thread
} catch (Exception e) {
// welcome to hell, where java can't cope with a classpath that contains jars that live
// in a directory that contains a !, at least the same bug happens on all platforms
String dir = appDir.toString();
String dir = envc.appDir.toString();
if (dir.equals(".")) {
dir = System.getProperty("user.dir");
}
@@ -103,7 +86,7 @@ public abstract class Getdown extends Thread
"contains the '!' character, this will trigger this error.";
fail(errmsg);
}
_app = new Application(appDir, appId, signers, jvmargs, appargs);
_app = new Application(envc);
_startup = System.currentTimeMillis();
}
@@ -14,24 +14,18 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
import com.samskivert.swing.util.SwingUtil;
import com.threerings.getdown.data.Digest;
import com.threerings.getdown.data.EnvConfig;
import com.threerings.getdown.data.SysProps;
import com.threerings.getdown.util.LaunchUtil;
import com.threerings.getdown.util.StringUtil;
@@ -42,11 +36,10 @@ import static com.threerings.getdown.Log.log;
*/
public class GetdownApp
{
private static final String USER_HOME = "${user.home}";
public static void main (String[] argv)
{
/**
* The main entry point of the Getdown launcher application.
*/
public static void main (String[] argv) {
try {
start(argv);
} catch (Exception e) {
@@ -61,58 +54,17 @@ public class GetdownApp
* @throws Exception if anything goes wrong starting Getdown.
*/
public static Getdown start (String[] argv) throws Exception {
int aidx = 0;
List<String> args = Arrays.asList(argv);
// check for app dir in a sysprop and then via argv
String adarg = SysProps.appDir();
if (StringUtil.isBlank(adarg)) {
loadBootstrapResource();
if (args.isEmpty() && SysProps.appDir() == null) {
System.err.println("Usage: java -jar getdown.jar app_dir [app_id] [app args]");
System.exit(-1);
}
if (!args.isEmpty()) {
adarg = args.get(aidx++);
} else {
adarg = SysProps.appDir();
}
}
// check for an app identifier in a sysprop and then via argv
String appId = SysProps.appId();
if (StringUtil.isBlank(appId) && aidx < args.size()) {
appId = args.get(aidx++);
}
// pass along anything after that as app args
String[] appArgs = (aidx >= args.size()) ? null :
args.subList(aidx, args.size()).toArray(new String[0]);
// ensure a valid directory was supplied
File appDir = new File(adarg);
if (!appDir.exists() || !appDir.isDirectory()) {
log.warning("Invalid app_dir '" + adarg + "'.");
List<EnvConfig.Note> notes = new ArrayList<>();
EnvConfig envc = EnvConfig.create(argv, notes);
if (envc == null) {
if (!notes.isEmpty()) for (EnvConfig.Note n : notes) System.err.println(n.message);
else System.err.println("Usage: java -jar getdown.jar [app_dir] [app_id] [app args]");
System.exit(-1);
}
// load X.509 certificate if it exists
File crtFile = new File(appDir, Digest.digestFile(Digest.VERSION) + ".crt");
List<Certificate> crts = new ArrayList<>();
if (crtFile.exists()) {
try (FileInputStream fis = new FileInputStream(crtFile)) {
X509Certificate certificate = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(fis);
crts.add(certificate);
} catch (Exception e) {
log.warning("Certificate error: " + e.getMessage());
System.exit(-1);
}
}
// pipe our output into a file in the application directory
if (!SysProps.noLogRedir()) {
File logFile = new File(appDir, "launcher.log");
File logFile = new File(envc.appDir, "launcher.log");
try {
PrintStream logOut = new PrintStream(
new BufferedOutputStream(new FileOutputStream(logFile)), true);
@@ -123,6 +75,17 @@ public class GetdownApp
}
}
// report any notes from reading our env config, and abort if necessary
boolean abort = false;
for (EnvConfig.Note note : notes) {
switch (note.level) {
case INFO: log.info(note.message); break;
case WARN: log.warning(note.message); break;
case ERROR: log.error(note.message); abort = true; break;
}
}
if (abort) System.exit(-1);
// record a few things for posterity
log.info("------------------ VM Info ------------------");
log.info("-- OS Name: " + System.getProperty("os.name"));
@@ -135,7 +98,7 @@ public class GetdownApp
log.info("-- Cur dir: " + System.getProperty("user.dir"));
log.info("---------------------------------------------");
Getdown app = new Getdown(appDir, appId, crts, null, appArgs) {
Getdown app = new Getdown(envc) {
@Override
protected Container createContainer () {
// create our user interface, and display it
@@ -270,25 +233,4 @@ public class GetdownApp
app.start();
return app;
}
private static void loadBootstrapResource() {
try {
ResourceBundle bundle = ResourceBundle.getBundle("bootstrap");
if (bundle.containsKey("appbase")) {
System.setProperty("appbase", bundle.getString("appbase"));
}
if (bundle.containsKey("appdir")) {
String appDir = bundle.getString("appdir");
appDir = appDir.replace(USER_HOME, System.getProperty("user.home"));
File appDirFile = new File(appDir);
if (!appDirFile.exists()) {
appDirFile.mkdirs();
}
System.setProperty("appdir", appDir);
}
log.info("bootstrap.properties found using:", "_appdir", System.getProperty("appdir"), "appbase", System.getProperty("appbase"));
} catch (MissingResourceException e) {
log.info("bootstrap.properties not found in resource bundle, starting without bootstrapping");
}
}
}