Further progress on proxy handling. The first time we run, we attempt to

detect the need for a proxy and if there is a need, the actual settings.
If we detect a need, but can't detect the proxy, we pop up a UI asking the
user if they know what it might be.
This commit is contained in:
Michael Bayne
2004-07-30 21:45:28 +00:00
parent 9176da3c85
commit e18d279b3b
4 changed files with 348 additions and 27 deletions
@@ -1,5 +1,5 @@
//
// $Id: Application.java,v 1.24 2004/07/30 02:23:52 mdb Exp $
// $Id: Application.java,v 1.25 2004/07/30 21:45:28 mdb Exp $
package com.threerings.getdown.data;
@@ -65,7 +65,7 @@ public class Application
public Color progressBar = new Color(0x6699CC);
/** The dimensions of the status display. */
public Rectangle status = new Rectangle(5, 25, 300, 100);
public Rectangle status = new Rectangle(5, 25, 500, 100);
/** The color of the status text. */
public Color statusText = Color.black;
@@ -105,7 +105,7 @@ public class Application
try {
return createResource(CONFIG_FILE);
} catch (Exception e) {
throw new RuntimeException("Booched appbase '" + _vappbase + "'!?");
throw new RuntimeException("Invalid appbase '" + _vappbase + "'.");
}
}
@@ -1,5 +1,5 @@
//
// $Id: Getdown.java,v 1.27 2004/07/30 18:14:21 mdb Exp $
// $Id: Getdown.java,v 1.28 2004/07/30 21:45:28 mdb Exp $
package com.threerings.getdown.launcher;
@@ -21,9 +21,12 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ResourceBundle;
@@ -37,6 +40,7 @@ import com.threerings.getdown.Log;
import com.threerings.getdown.data.Application;
import com.threerings.getdown.data.Resource;
import com.threerings.getdown.tools.Patcher;
import com.threerings.getdown.util.ConfigUtil;
import com.threerings.getdown.util.ProgressObserver;
import com.threerings.getdown.util.ProxyUtil;
@@ -78,6 +82,177 @@ public class Getdown extends Thread
return;
}
try {
_dead = false;
if (detectProxy()) {
getdown();
} else {
// create a panel they can use to configure the proxy settings
_frame.getContentPane().removeAll();
_frame.getContentPane().add(
new ProxyPanel(this, _msgs), BorderLayout.CENTER);
_frame.pack();
SwingUtil.centerWindow(_frame);
_frame.show();
// allow them to close the window to abort the proxy
// configuration
_dead = true;
}
} catch (Exception e) {
Log.logStackTrace(e);
String msg = e.getMessage();
if (msg == null) {
msg = "m.unknown_error";
} else if (!msg.startsWith("m.")) {
// try to do something sensible based on the type of error
if (e instanceof FileNotFoundException) {
msg = MessageUtil.tcompose("m.missing_resource", msg);
} else {
msg = MessageUtil.tcompose("m.init_error", msg);
}
}
updateStatus(msg);
_dead = true;
}
}
/**
* Configures our proxy settings (called by {@link ProxyPanel}) and
* fires up the launcher.
*/
public void configureProxy (String host, String port)
{
Log.info("User configured proxy [host=" + host +
", port=" + port + "].");
// if we're provided with valid values, create a proxy.txt file
if (!StringUtil.blank(host)) {
File pfile = _app.getLocalPath("proxy.txt");
try {
PrintStream pout = new PrintStream(new FileOutputStream(pfile));
pout.println("host = " + host);
if (!StringUtil.blank(port)) {
pout.println("port = " + port);
}
pout.close();
} catch (IOException ioe) {
Log.warning("Error creating proxy file '" + pfile +
"': " + ioe);
}
// also configure them in the JVM
System.setProperty("http.proxyHost", host);
if (!StringUtil.blank(port)) {
System.setProperty("http.proxyPort", port);
}
}
// clear out our UI
_frame.dispose();
_status = null;
_frame = null;
// fire up a new thread
new Thread(this).start();
}
/**
* Reads and/or autodetects our proxy settings.
*
* @return true if we should proceed with running the launcher, false
* if we need to wait for the user to enter proxy settings.
*/
protected boolean detectProxy ()
{
// we may already have a proxy configured
if (System.getProperty("http.proxyHost") != null) {
return true;
}
// TODO: look in the Vinders registry
// otherwise look for and read our proxy.txt file
File pfile = _app.getLocalPath("proxy.txt");
if (pfile.exists()) {
try {
HashMap pconf = ConfigUtil.parseConfig(pfile, false);
String proxyHost = (String)pconf.get("host");
String proxyPort = (String)pconf.get("port");
if (!StringUtil.blank(proxyHost)) {
System.setProperty("http.proxyHost", proxyHost);
if (!StringUtil.blank(proxyPort)) {
System.setProperty("http.proxyPort", proxyPort);
}
Log.info("Using proxy [host=" + proxyHost +
", port=" + proxyPort + "].");
}
// now we can get on with getting down
return true;
} catch (IOException ioe) {
Log.warning("Failed to read '" + pfile + "': " + ioe);
}
}
// otherwise we'll need to try to detect our proxy settings; first
// we have to initialize our application to get some sort of
// interface configuration and the appbase URL
Log.info("Attempting to detect proxy settings...");
try {
_ifc = _app.init(true);
} catch (IOException ioe) {
// no worries
}
updateStatus("m.detecting_proxy");
URL rurl = _app.getConfigResource().getRemote();
try {
// try to make a HEAD request for this URL
HttpURLConnection ucon = (HttpURLConnection)
rurl.openConnection();
ucon.setRequestMethod("HEAD");
ucon.connect();
// make sure we got a satisfactory response code
if (ucon.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.warning("Got a non-200 response but assuming we're OK " +
"because we got something... [url=" + rurl +
", rsp=" + ucon.getResponseCode() + "].");
}
// we got through, so we appear not to require a proxy; make a
// blank proxy config and get on gettin' down
Log.info("No proxy appears to be needed.");
try {
pfile.createNewFile();
} catch (IOException ioe) {
Log.warning("Failed to create blank proxy file '" +
pfile + "': " + ioe);
}
return true;
} catch (IOException ioe) {
Log.info("Failed to HEAD " + rurl + ": " + ioe);
Log.info("We probably need a proxy. Attempting to auto-detect...");
}
// let the caller know that we need a proxy but can't detect it
return false;
}
/**
* Does the actual application validation, update and launching
* business.
*/
protected void getdown ()
{
Log.info("---------------- Proxy Info -----------------");
Log.info("-- Proxy Host: " + System.getProperty("http.proxyHost"));
Log.info("-- Proxy Port: " + System.getProperty("http.proxyPort"));
Log.info("---------------------------------------------");
try {
// first parses our application deployment file
try {
@@ -371,27 +546,15 @@ public class Getdown extends Thread
}
// pipe our output into a file in the application directory
File log = new File(appDir, "launcher.log");
try {
FileOutputStream fout = new FileOutputStream(log);
System.setOut(new PrintStream(fout));
System.setErr(new PrintStream(fout));
} catch (IOException ioe) {
Log.warning("Unable to redirect output to '" + log + "': " + ioe);
}
// attempt to obtain our proxy information; it may be specified
// via system properties or we can autodetect it
if (System.getProperty("http.proxyHost") == null) {
if (System.getProperty("no_log_redir") == null) {
File log = new File(appDir, "launcher.log");
try {
URL sample = new URL("http://www.threerings.net/");
if (ProxyUtil.detectProxy(sample)) {
String host = ProxyUtil.getProxyIP();
String port = ProxyUtil.getProxyPort();
ProxyUtil.configureProxy(host, port);
}
} catch (Exception e) {
Log.warning("Failed to detect proxy: " + e);
FileOutputStream fout = new FileOutputStream(log);
System.setOut(new PrintStream(fout));
System.setErr(new PrintStream(fout));
} catch (IOException ioe) {
Log.warning("Unable to redirect output to '" + log +
"': " + ioe);
}
}
@@ -405,8 +568,6 @@ public class Getdown extends Thread
Log.info("-- User Name: " + System.getProperty("user.name"));
Log.info("-- User Home: " + System.getProperty("user.home"));
Log.info("-- Cur dir: " + System.getProperty("user.dir"));
Log.info("-- Proxy Host: " + System.getProperty("http.proxyHost"));
Log.info("-- Proxy Port: " + System.getProperty("http.proxyPort"));
Log.info("---------------------------------------------");
try {
@@ -0,0 +1,139 @@
//
// $Id: ProxyPanel.java,v 1.1 2004/07/30 21:45:28 mdb Exp $
package com.threerings.getdown.launcher;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.samskivert.swing.GroupLayout;
import com.samskivert.swing.Spacer;
import com.samskivert.swing.VGroupLayout;
import com.samskivert.text.MessageUtil;
import com.threerings.getdown.Log;
/**
* Displays an interface with which the user can configure their proxy
* settings.
*/
public class ProxyPanel extends JPanel
implements ActionListener
{
public ProxyPanel (Getdown getdown, ResourceBundle msgs)
{
_getdown = getdown;
_msgs = msgs;
setLayout(new VGroupLayout());
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(new JLabel(get("m.configure_proxy")));
add(new Spacer(5, 5));
JPanel row = new JPanel(new BorderLayout(5, 5));
row.add(new JLabel(get("m.proxy_host")), BorderLayout.WEST);
row.add(_host = new SaneTextField());
add(row);
row = new JPanel(new BorderLayout(5, 5));
row.add(new JLabel(get("m.proxy_port")), BorderLayout.WEST);
row.add(_port = new SaneTextField());
add(row);
add(new Spacer(5, 5));
add(new JLabel(get("m.proxy_extra")));
row = GroupLayout.makeButtonBox(GroupLayout.CENTER);
JButton button;
row.add(button = new JButton(get("m.proxy_ok")));
button.setActionCommand("ok");
button.addActionListener(this);
row.add(button = new JButton(get("m.proxy_cancel")));
button.setActionCommand("cancel");
button.addActionListener(this);
add(row);
// set up any existing proxy defaults
String host = System.getProperty("http.proxyHost");
if (host != null) {
_host.setText(host);
}
String port = System.getProperty("http.proxyPort");
if (port != null) {
_port.setText(port);
}
}
// documentation inherited
public void addNotify ()
{
super.addNotify();
_host.requestFocusInWindow();
}
// documentation inherited
public Dimension getPreferredSize ()
{
// this is annoyingly hardcoded, but we can't just force the width
// or the JLabel will claim a bogus height thinking it can lay its
// text out all on one line which will booch the whole UI's
// preferred size
return new Dimension(500, 350);
}
// documentation inherited from interface
public void actionPerformed (ActionEvent e)
{
String cmd = e.getActionCommand();
if (cmd.equals("ok")) {
// communicate this info back to getdown
_getdown.configureProxy(_host.getText(), _port.getText());
} else {
// they canceled, we're outta here
System.exit(0);
}
}
/** Used to look up localized messages. */
protected String get (String key)
{
// if this string is tainted, we don't translate it, instead we
// simply remove the taint character and return it to the caller
if (key.startsWith(MessageUtil.TAINT_CHAR)) {
return key.substring(1);
}
try {
return _msgs.getString(key);
} catch (MissingResourceException mre) {
Log.warning("Missing translation message '" + key + "'.");
return key;
}
}
protected static class SaneTextField extends JTextField
{
public Dimension getPreferredSize () {
Dimension d = super.getPreferredSize();
d.width = Math.max(d.width, 150);
return d;
}
}
protected Getdown _getdown;
protected ResourceBundle _msgs;
protected JTextField _host;
protected JTextField _port;
}
@@ -1,8 +1,29 @@
#
# $Id: messages.properties,v 1.6 2004/07/26 18:05:55 mdb Exp $
# $Id: messages.properties,v 1.7 2004/07/30 21:45:28 mdb Exp $
#
# Getdown translation messages
m.detecting_proxy = Trying to auto-detect proxy settings...
m.configure_proxy = <html>We were unable to connect to our servers to \
download the game data. This may be because your computer accesses 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.</html>
m.proxy_extra = <html>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 \
installing again later.<br><br> \
If you are not sure whether or not you are using a proxy, please visit \
the support section of our website to find instructions on how to \
determine your proxy settings.</html>
m.proxy_host = Proxy IP
m.proxy_port = Proxy port
m.proxy_ok = OK
m.proxy_cancel = Cancel
m.resolving = Resolving downloads...
m.downloading = Downloading data...
m.failure = Download failed: {0}