changeset 45:dd77da50a226

integrate basic proxy configuration support 2010-11-23 Omair Majid <omajid@redhat.com> * netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java: Add KEY_PROXY_TYPE, KEY_PROXY_SAME, KEY_PROXY_AUTO_CONFIG_URL, KEY_PROXY_BYPASS_LIST, KEY_PROXY_BYPASS_LOCAL, KEY_PROXY_HTTP_HOST, KEY_PROXY_HTTP_PORT, KEY_PROXY_HTTPS_HOST, KEY_PROXY_HTTPS_PORT, KEY_PROXY_FTP_HOST, KEY_PROXY_FTP_PORT, KEY_PROXY_SOCKS4_HOST, KEY_PROXY_SOCKS4_PORT, and KEY_PROXY_OVERRIDE_HOSTS. (loadDefaultProperties): Use the new constants. * netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: New class. (JNLPProxySelector): New method. (parseConfiguration): New method. Initializes this object by querying the configuration. (getHost): New method. (getPort): New method. (connectFailed): New method. (select): New method. Returns a list of appropriate proxies to use for a given uri. (inBypassList): New method. Return true if the host in the URI should be bypassed for proxy purposes. (isLocalHost): New method. (getFromConfiguration): New method. Finds a proxy based on configuration. (getFromPAC): New method. (getFromBrowser): New method. * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize): Install proxy selector and authenticator. * plugin/icedteanp/java/sun/applet/PluginMain.java (init): Do not install authenticator. (CustomAuthenticator): Moved to... * netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java: Here. * plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java Moved to... * netx/net/sourceforge/jnlp/security /PasswordAuthenticationDialog.java: Here. * plugin/icedteanp/java/sun/applet/PluginProxySelector.java: Extend JNLPProxySelector. (select): Renamed to... (getFromBrowser): New method.
author Omair Majid <omajid@redhat.com>
date Tue, 23 Nov 2010 10:05:06 -0500
parents 5a9f55d67b50
children e1400d406d85
files ChangeLog netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java netx/net/sourceforge/jnlp/security/PasswordAuthenticationDialog.java plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java plugin/icedteanp/java/sun/applet/PluginMain.java plugin/icedteanp/java/sun/applet/PluginProxySelector.java
diffstat 9 files changed, 755 insertions(+), 296 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Nov 19 10:35:27 2010 -0500
+++ b/ChangeLog	Tue Nov 23 10:05:06 2010 -0500
@@ -1,3 +1,44 @@
+2010-11-23  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_PROXY_TYPE, KEY_PROXY_SAME, KEY_PROXY_AUTO_CONFIG_URL,
+	KEY_PROXY_BYPASS_LIST, KEY_PROXY_BYPASS_LOCAL, KEY_PROXY_HTTP_HOST,
+	KEY_PROXY_HTTP_PORT, KEY_PROXY_HTTPS_HOST, KEY_PROXY_HTTPS_PORT,
+	KEY_PROXY_FTP_HOST, KEY_PROXY_FTP_PORT, KEY_PROXY_SOCKS4_HOST,
+	KEY_PROXY_SOCKS4_PORT, and KEY_PROXY_OVERRIDE_HOSTS.
+	(loadDefaultProperties): Use the new constants.
+	* netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: New
+	class.
+	(JNLPProxySelector): New method.
+	(parseConfiguration): New method. Initializes this object by
+	querying the configuration.
+	(getHost): New method.
+	(getPort): New method.
+	(connectFailed): New method.
+	(select): New method. Returns a list of appropriate proxies to use
+	for a given uri.
+	(inBypassList): New method. Return true if the host in the URI
+	should be bypassed for proxy purposes.
+	(isLocalHost): New method.
+	(getFromConfiguration): New method. Finds a proxy based on
+	configuration.
+	(getFromPAC): New method.
+	(getFromBrowser): New method.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Install proxy selector and authenticator.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java
+	(init): Do not install authenticator.
+	(CustomAuthenticator): Moved to...
+	* netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java: Here.
+	* plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java
+	Moved to...
+	* netx/net/sourceforge/jnlp/security
+	/PasswordAuthenticationDialog.java: Here.
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java: Extend
+	JNLPProxySelector.
+	(select): Renamed to...
+	(getFromBrowser): New method.
+
 2010-11-19  Omair Majid  <omajid@redhat.com>
 
 	* Makefile.am (EXTRA_DIST): Replace javaws.desktop with
--- a/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java	Fri Nov 19 10:35:27 2010 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java	Tue Nov 23 10:05:06 2010 -0500
@@ -120,13 +120,6 @@
     public static final String CONSOLE_SHOW = "SHOW";
     public static final String CONSOLE_DISABLE = "DISABLE";
 
-    /* FIXME these should be moved into the proxy class */
-    public static final int PROXY_TYPE_UNKNOWN = -1;
-    public static final int PROXY_TYPE_NONE = 0;
-    public static final int PROXY_TYPE_MANUAL = 1;
-    public static final int PROXY_TYPE_AUTO = 2;
-    public static final int PROXY_TYPE_BROWSER = 3;
-
     public static final String KEY_USER_CACHE_DIR = "deployment.user.cachedir";
     public static final String KEY_USER_PERSISTENCE_CACHE_DIR = "deployment.user.pcachedir";
     public static final String KEY_SYSTEM_CACHE_DIR = "deployment.system.cachedir";
@@ -172,6 +165,24 @@
     public static final String KEY_SECURITY_INSTALL_AUTHENTICATOR = "deployment.security.authenticator";
 
     /*
+     * Networking
+     */
+    public static final String KEY_PROXY_TYPE = "deployment.proxy.type";
+    public static final String KEY_PROXY_SAME = "deployment.proxy.same";
+    public static final String KEY_PROXY_AUTO_CONFIG_URL = "deployment.proxy.auto.config.url";
+    public static final String KEY_PROXY_BYPASS_LIST = "deployment.proxy.bypass.list";
+    public static final String KEY_PROXY_BYPASS_LOCAL = "deployment.proxy.bypass.local";
+    public static final String KEY_PROXY_HTTP_HOST = "deployment.proxy.http.host";
+    public static final String KEY_PROXY_HTTP_PORT = "deployment.proxy.http.port";
+    public static final String KEY_PROXY_HTTPS_HOST = "deployment.proxy.https.host";
+    public static final String KEY_PROXY_HTTPS_PORT = "deployment.proxy.https.port";
+    public static final String KEY_PROXY_FTP_HOST = "deployment.proxy.ftp.host";
+    public static final String KEY_PROXY_FTP_PORT = "deployment.proxy.ftp.port";
+    public static final String KEY_PROXY_SOCKS4_HOST = "deployment.proxy.socks.host";
+    public static final String KEY_PROXY_SOCKS4_PORT = "deployment.proxy.socks.port";
+    public static final String KEY_PROXY_OVERRIDE_HOSTS = "deployment.proxy.override.hosts";
+
+    /*
      * Tracing and Logging
      */
 
@@ -380,20 +391,20 @@
             { KEY_SECURITY_PROMPT_USER_FOR_JNLP, String.valueOf(true) },
             { KEY_SECURITY_INSTALL_AUTHENTICATOR, String.valueOf(true) },
             /* networking */
-            { "deployment.proxy.type", String.valueOf(PROXY_TYPE_BROWSER) },
-            { "deployment.proxy.same", String.valueOf(false) },
-            { "deployment.proxy.auto.config.url", null },
-            { "deployment.proxy.bypass.list", null },
-            { "deployment.proxy.bypass.local", null },
-            { "deployment.proxy.http.host", null },
-            { "deployment.proxy.http.port", null },
-            { "deployment.proxy.https.host", null },
-            { "deployment.proxy.https.port", null },
-            { "deployment.proxy.ftp.host", null },
-            { "deployment.proxy.ftp.port", null },
-            { "deployment.proxy.socks.host", null },
-            { "deployment.proxy.socks.port", null },
-            { "deployment.proxy.override.hosts", null },
+            { KEY_PROXY_TYPE, String.valueOf(JNLPProxySelector.PROXY_TYPE_BROWSER) },
+            { KEY_PROXY_SAME, String.valueOf(false) },
+            { KEY_PROXY_AUTO_CONFIG_URL, null },
+            { KEY_PROXY_BYPASS_LIST, null },
+            { KEY_PROXY_BYPASS_LOCAL, null },
+            { KEY_PROXY_HTTP_HOST, null },
+            { KEY_PROXY_HTTP_PORT, null },
+            { KEY_PROXY_HTTPS_HOST, null },
+            { KEY_PROXY_HTTPS_PORT, null },
+            { KEY_PROXY_FTP_HOST, null },
+            { KEY_PROXY_FTP_PORT, null },
+            { KEY_PROXY_SOCKS4_HOST, null },
+            { KEY_PROXY_SOCKS4_PORT, null },
+            { KEY_PROXY_OVERRIDE_HOSTS, null },
             /* cache and optional package repository */
             { "deployment.cache.max.size", String.valueOf("-1") },
             { "deployment.cache.jarcompression", String.valueOf(0) },
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java	Tue Nov 23 10:05:06 2010 -0500
@@ -0,0 +1,360 @@
+// Copyright (C) 2010 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.net.Proxy.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * A ProxySelector specific to JNLPs. This proxy uses the deployment
+ * configuration to determine what to do.
+ *
+ * @see java.net.ProxySelector
+ */
+public class JNLPProxySelector extends ProxySelector {
+
+    public static final int PROXY_TYPE_UNKNOWN = -1;
+    public static final int PROXY_TYPE_NONE = 0;
+    public static final int PROXY_TYPE_MANUAL = 1;
+    public static final int PROXY_TYPE_AUTO = 2;
+    public static final int PROXY_TYPE_BROWSER = 3;
+
+    /** The default port to use as a fallback. Currently squid's default port */
+    public static final int FALLBACK_PROXY_PORT = 3128;
+
+    /** The proxy type. See PROXY_TYPE_* constants */
+    private int proxyType = PROXY_TYPE_UNKNOWN;
+
+    /** the URL to the PAC file */
+    private URL autoConfigUrl = null;
+
+    /** a list of URLs that should be bypassed for proxy purposes */
+    private List<String> bypassList = null;
+
+    /** whether localhost should be bypassed for proxy purposes */
+    private boolean bypassLocal = false;
+
+    /**
+     * whether the http proxy should be used for https and ftp protocols as well
+     */
+    private boolean sameProxy = false;
+
+    private String proxyHttpHost;
+    private int proxyHttpPort;
+    private String proxyHttpsHost;
+    private int proxyHttpsPort;
+    private String proxyFtpHost;
+    private int proxyFtpPort;
+    private String proxySocks4Host;
+    private int proxySocks4Port;
+
+    // FIXME what is this? where should it be used?
+    private String overrideHosts = null;
+
+    /**
+     * Creates a new JNLPProxySelector.
+     */
+    public JNLPProxySelector() {
+        parseConfiguration();
+    }
+
+    /**
+     * Initialize this ProxySelector by reading the configuration
+     */
+    private void parseConfiguration() {
+        DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+
+        proxyType = Integer.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_TYPE));
+
+        String autoConfigString = config
+                .getProperty(DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL);
+        if (autoConfigString != null) {
+            try {
+                autoConfigUrl = new URL(autoConfigString);
+            } catch (MalformedURLException e) {
+                e.printStackTrace();
+            }
+        }
+
+        bypassList = new ArrayList<String>();
+        String proxyBypass = config.getProperty(DeploymentConfiguration.KEY_PROXY_BYPASS_LIST);
+        if (proxyBypass != null) {
+            StringTokenizer tokenizer = new StringTokenizer(proxyBypass, ",");
+            while (tokenizer.hasMoreTokens()) {
+                String host = tokenizer.nextToken();
+                if (host != null && host.trim().length() != 0) {
+                    bypassList.add(host);
+                }
+            }
+        }
+
+        bypassLocal = Boolean.valueOf(config
+                .getProperty(DeploymentConfiguration.KEY_PROXY_BYPASS_LOCAL));
+
+        sameProxy = Boolean.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_SAME));
+
+        proxyHttpHost = getHost(config, DeploymentConfiguration.KEY_PROXY_HTTP_HOST);
+        proxyHttpPort = getPort(config, DeploymentConfiguration.KEY_PROXY_HTTP_PORT);
+
+        proxyHttpsHost = getHost(config, DeploymentConfiguration.KEY_PROXY_HTTPS_HOST);
+        proxyHttpsPort = getPort(config, DeploymentConfiguration.KEY_PROXY_HTTPS_PORT);
+
+        proxyFtpHost = getHost(config, DeploymentConfiguration.KEY_PROXY_FTP_HOST);
+        proxyFtpPort = getPort(config, DeploymentConfiguration.KEY_PROXY_FTP_PORT);
+
+        proxySocks4Host = getHost(config, DeploymentConfiguration.KEY_PROXY_SOCKS4_HOST);
+        proxySocks4Port = getPort(config, DeploymentConfiguration.KEY_PROXY_SOCKS4_PORT);
+
+        overrideHosts = config.getProperty(DeploymentConfiguration.KEY_PROXY_OVERRIDE_HOSTS);
+    }
+
+    /**
+     * Uses the given key to get a host from the configuraion
+     */
+    private String getHost(DeploymentConfiguration config, String key) {
+        String proxyHost = config.getProperty(key);
+        if (proxyHost != null) {
+            proxyHost = proxyHost.trim();
+        }
+        return proxyHost;
+    }
+
+    /**
+     * Uses the given key to get a port from the configuration
+     */
+    private int getPort(DeploymentConfiguration config, String key) {
+        int proxyPort = FALLBACK_PROXY_PORT;
+        String port;
+        port = config.getProperty(key);
+        if (port != null && port.trim().length() != 0) {
+            try {
+                proxyPort = Integer.valueOf(port);
+            } catch (NumberFormatException e) {
+                e.printStackTrace();
+            }
+        }
+        return proxyPort;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+        ioe.printStackTrace();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<Proxy> select(URI uri) {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Selecting proxy for: " + uri);
+        }
+
+        if (inBypassList(uri)) {
+            List<Proxy> proxies = Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray()));
+            }
+            return proxies;
+        }
+
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        switch (proxyType) {
+            case PROXY_TYPE_MANUAL:
+                proxies.addAll(getFromConfiguration(uri));
+                break;
+            case PROXY_TYPE_AUTO:
+                proxies.addAll(getFromPAC(uri));
+                break;
+            case PROXY_TYPE_BROWSER:
+                proxies.addAll(getFromBrowser(uri));
+                break;
+            case PROXY_TYPE_UNKNOWN:
+                // fall through
+            case PROXY_TYPE_NONE:
+                // fall through
+            default:
+                proxies.add(Proxy.NO_PROXY);
+                break;
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray()));
+        }
+        return proxies;
+    }
+
+    /**
+     * Returns true if the uri should be bypassed for proxy purposes
+     */
+    private boolean inBypassList(URI uri) {
+        try {
+            String scheme = uri.getScheme();
+            /* scheme can be http/https/ftp/socket */
+
+            if (scheme.equals("http") || scheme.equals("https") || scheme.equals("ftp")) {
+                URL url = uri.toURL();
+                if (bypassLocal && isLocalHost(url.getHost())) {
+                    return true;
+                }
+
+                if (bypassList.contains(url.getHost())) {
+                    return true;
+                }
+            } else if (scheme.equals("socket")) {
+                String host = uri.getSchemeSpecificPart().split(":")[0];
+
+                if (bypassLocal && isLocalHost(host)) {
+                    return true;
+                }
+
+                if (bypassList.contains(host)) {
+                    return true;
+                }
+            }
+        } catch (MalformedURLException e) {
+            return false;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns true if the host is the hostname or the IP address of the
+     * localhost
+     */
+    private boolean isLocalHost(String host) {
+
+        try {
+            if (InetAddress.getByName(host).isLoopbackAddress()) {
+                return true;
+            }
+        } catch (UnknownHostException e1) {
+            // continue
+        }
+
+        try {
+            if (host.equals(InetAddress.getLocalHost().getHostName())) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            // continue
+        }
+
+        try {
+            if (host.equals(InetAddress.getLocalHost().getHostAddress())) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            // continue
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a list of proxies by using the information in the deployment
+     * configuration
+     *
+     * @param uri
+     * @return a List of Proxy objects
+     */
+    private List<Proxy> getFromConfiguration(URI uri) {
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        String scheme = uri.getScheme();
+
+        if (sameProxy) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort);
+            Proxy proxy;
+            if (scheme.equals("socket")) {
+                proxy = new Proxy(Type.SOCKS, sa);
+            } else {
+                proxy = new Proxy(Type.HTTP, sa);
+            }
+            proxies.add(proxy);
+        } else if (scheme.equals("http")) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("https")) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpsHost, proxyHttpsPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("ftp")) {
+            SocketAddress sa = new InetSocketAddress(proxyFtpHost, proxyFtpPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("socket")) {
+            SocketAddress sa = new InetSocketAddress(proxySocks4Host, proxySocks4Port);
+            proxies.add(new Proxy(Type.SOCKS, sa));
+        } else {
+            proxies.add(Proxy.NO_PROXY);
+        }
+
+        return proxies;
+    }
+
+    /**
+     * Returns a list of proxies by using the Proxy Auto Config (PAC) file. See
+     * http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file for more
+     * information.
+     *
+     * @return a List of valid Proxy objects
+     */
+    private List<Proxy> getFromPAC(URI uri) {
+        if (autoConfigUrl == null) {
+            return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+        }
+        // TODO implement this by reading and using the PAC file
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("WARNING: Using a Proxy Auto Config file is not implemented yet");
+        }
+
+        return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+    }
+
+    /**
+     * Returns a list of proxies by querying the browser
+     *
+     * @param uri the uri to get proxies for
+     * @return a list of proxies
+     */
+    protected List<Proxy> getFromBrowser(URI uri) {
+        // TODO implement this by parsing mozilla config
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("WARNING: Using proxy settings from the browser is not implemented yet");
+        }
+
+        return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+    }
+
+}
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Nov 19 10:35:27 2010 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Tue Nov 23 10:05:06 2010 -0500
@@ -18,6 +18,8 @@
 package net.sourceforge.jnlp.runtime;
 
 import java.io.*;
+import java.net.Authenticator;
+import java.net.ProxySelector;
 import java.nio.channels.FileLock;
 import java.awt.*;
 import java.text.*;
@@ -35,6 +37,7 @@
 
 import net.sourceforge.jnlp.*;
 import net.sourceforge.jnlp.cache.*;
+import net.sourceforge.jnlp.security.JNLPAuthenticator;
 import net.sourceforge.jnlp.security.SecurityDialogMessageHandler;
 import net.sourceforge.jnlp.security.VariableX509TrustManager;
 import net.sourceforge.jnlp.services.*;
@@ -250,6 +253,10 @@
             e.printStackTrace();
         }
 
+        // plug in a custom authenticator and proxy selector
+        Authenticator.setDefault(new JNLPAuthenticator());
+        ProxySelector.setDefault(new JNLPProxySelector());
+
         initialized = true;
 
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java	Tue Nov 23 10:05:06 2010 -0500
@@ -0,0 +1,61 @@
+/* JNLPAuthenticator
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.security;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+
+public class JNLPAuthenticator extends Authenticator {
+
+    public PasswordAuthentication getPasswordAuthentication() {
+
+        // No security check is required here, because the only way to set
+        // parameters for which auth info is needed
+        // (Authenticator:requestPasswordAuthentication()), has a security check
+
+        String type = this.getRequestorType() == RequestorType.PROXY ? "proxy" : "web";
+
+        // request auth info from user
+        PasswordAuthenticationDialog pwDialog = new PasswordAuthenticationDialog();
+        PasswordAuthentication auth = pwDialog.askUser(this.getRequestingHost(), this.getRequestingPort(), this.getRequestingPrompt(), type);
+
+        // send it along
+        return auth;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/PasswordAuthenticationDialog.java	Tue Nov 23 10:05:06 2010 -0500
@@ -0,0 +1,247 @@
+/* PasswordAuthenticationDialog -- requests authentication information from users
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.PasswordAuthentication;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * Modal non-minimizable dialog to request http authentication credentials
+ */
+
+public class PasswordAuthenticationDialog extends JDialog {
+
+    private JLabel jlInfo = new JLabel("");
+    private JTextField jtfUserName = new JTextField();
+    private JPasswordField jpfPassword = new JPasswordField();
+    private boolean userCancelled;
+
+    public PasswordAuthenticationDialog() {
+        initialize();
+    }
+
+    /**
+     * Initialized the dialog components
+     */
+
+    public void initialize() {
+
+        setTitle("IcedTea Java Plugin - Authorization needed to proceed");
+
+        setLayout(new GridBagLayout());
+
+        JLabel jlUserName = new JLabel("Username: ");
+        JLabel jlPassword = new JLabel("Password: ");
+        JButton jbOK = new JButton("OK");
+        JButton jbCancel = new JButton("Cancel");
+
+        jtfUserName.setSize(20, 10);
+        jpfPassword.setSize(20, 10);
+
+        GridBagConstraints c;
+
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 0;
+        c.gridy = 0;
+        c.gridwidth = 2;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlInfo, c);
+
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlUserName, c);
+
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jtfUserName, c);
+
+
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        add(jlPassword, c);
+
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jpfPassword, c);
+
+        c = new GridBagConstraints();
+        c.anchor = c.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 70);
+        c.weightx = 0.0;
+        add(jbCancel, c);
+
+        c = new GridBagConstraints();
+        c.anchor = c.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 0.0;
+        add(jbOK, c);
+
+        setMinimumSize(new Dimension(400,150));
+        setMaximumSize(new Dimension(1024,150));
+        setAlwaysOnTop(true);
+
+        setSize(400,150);
+        setLocationRelativeTo(null);
+
+        // OK => read supplied info and pass it on
+        jbOK.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+
+        // Cancel => discard supplied info and pass on an empty auth
+        jbCancel.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = true;
+                dispose();
+            }
+        });
+
+        // "return" key in either user or password field => OK
+
+        jtfUserName.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+
+        jpfPassword.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+    }
+
+    /**
+     * Present a dialog to the user asking them for authentication information
+     * 
+     * @param hostThe host for with authentication is needed
+     * @param port The port being accessed
+     * @param prompt The prompt (realm) as presented by the server
+     * @param type The type of server (proxy/web)
+     * @return PasswordAuthentication containing the credentials (empty credentials if user cancelled)
+     */
+    protected PasswordAuthentication askUser(String host, int port, String prompt, String type) {
+        PasswordAuthentication auth = null;
+
+        host += port != -1 ? ":" + port : "";
+
+        // This frame is reusable. So reset everything first.
+        userCancelled = true;
+        jlInfo.setText("<html>The " + type + " server at " + host + " is requesting authentication. It says \"" + prompt + "\"</html>");
+
+        try {
+            SwingUtilities.invokeAndWait( new Runnable() {
+                public void run() {
+                    // show dialog to user
+                    setVisible(true);
+                }
+            });
+
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("password dialog shown");
+            }
+
+            // wait until dialog is gone
+            while (this.isShowing()) {
+                try {
+                    Thread.sleep(200);
+                } catch (InterruptedException ie) {
+                }
+            }
+
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("password dialog closed");
+            }
+
+            if (!userCancelled) {
+                auth = new PasswordAuthentication(jtfUserName.getText(), jpfPassword.getText().toCharArray());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+
+            // Nothing else we can do. Empty auth will be returned
+        }
+
+        return auth;
+    }
+
+    public static void main(String[] args) {
+        PasswordAuthenticationDialog frame = new PasswordAuthenticationDialog();
+
+        PasswordAuthentication auth = frame.askUser("127.0.0.1", 3128, "Password for local proxy", "proxy");
+
+        System.err.println("Auth info: " + auth.getUserName() + ":" + new String(auth.getPassword()));
+        System.exit(0);
+    }
+}
--- a/plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java	Fri Nov 19 10:35:27 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/* PasswordAuthenticationDialog -- requests authentication information from users
-   Copyright (C) 2009  Red Hat
-
-This file is part of IcedTea.
-
-IcedTea is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-IcedTea is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with IcedTea; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
-
-package sun.applet;
-
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.net.PasswordAuthentication;
-
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-import javax.swing.SwingUtilities;
-
-/**
- * Modal non-minimizable dialog to request http authentication credentials
- */
-
-public class PasswordAuthenticationDialog extends JDialog {
-    
-    private JLabel jlInfo = new JLabel("");
-    private JTextField jtfUserName = new JTextField();
-    private JPasswordField jpfPassword = new JPasswordField();
-    private boolean userCancelled;
-
-    public PasswordAuthenticationDialog() {
-        initialize();
-    }
-
-    /**
-     * Initialized the dialog components
-     */
-    
-    public void initialize() {
-
-        setTitle("IcedTea Java Plugin - Authorization needed to proceed");
-
-        setLayout(new GridBagLayout());
-
-        JLabel jlUserName = new JLabel("Username: ");
-        JLabel jlPassword = new JLabel("Password: ");
-        JButton jbOK = new JButton("OK");
-        JButton jbCancel = new JButton("Cancel");
-
-        jtfUserName.setSize(20, 10);
-        jpfPassword.setSize(20, 10);
-
-        GridBagConstraints c;
-        
-        c = new GridBagConstraints();
-        c.fill = c.HORIZONTAL;
-        c.gridx = 0;
-        c.gridy = 0;
-        c.gridwidth = 2;
-        c.insets = new Insets(10, 5, 3, 3);
-        add(jlInfo, c);
-        
-        c = new GridBagConstraints();
-        c.gridx = 0;
-        c.gridy = 1;
-        c.insets = new Insets(10, 5, 3, 3);
-        add(jlUserName, c);
-        
-        c = new GridBagConstraints();
-        c.fill = c.HORIZONTAL;
-        c.gridx = 1;
-        c.gridy = 1;
-        c.insets = new Insets(10, 5, 3, 3);
-        c.weightx = 1.0;
-        add(jtfUserName, c);
-
-
-        c = new GridBagConstraints();
-        c.gridx = 0;
-        c.gridy = 2;
-        c.insets = new Insets(5, 5, 3, 3);
-        add(jlPassword, c);
-        
-        c = new GridBagConstraints();
-        c.fill = c.HORIZONTAL;
-        c.gridx = 1;
-        c.gridy = 2;
-        c.insets = new Insets(5, 5, 3, 3);
-        c.weightx = 1.0;
-        add(jpfPassword, c);
-
-        c = new GridBagConstraints();
-        c.anchor = c.SOUTHEAST;
-        c.gridx = 1;
-        c.gridy = 3;
-        c.insets = new Insets(5, 5, 3, 70);
-        c.weightx = 0.0;
-        add(jbCancel, c);
-        
-        c = new GridBagConstraints();
-        c.anchor = c.SOUTHEAST;
-        c.gridx = 1;
-        c.gridy = 3;
-        c.insets = new Insets(5, 5, 3, 3);
-        c.weightx = 0.0;
-        add(jbOK, c);
-        
-        setMinimumSize(new Dimension(400,150));
-        setMaximumSize(new Dimension(1024,150));
-        setAlwaysOnTop(true);
-        
-        setSize(400,150);
-        setLocationRelativeTo(null);
-
-        // OK => read supplied info and pass it on
-        jbOK.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                userCancelled = false;
-                dispose();
-            }
-        });
-        
-        // Cancel => discard supplied info and pass on an empty auth
-        jbCancel.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                userCancelled = true;
-                dispose();
-            }
-        });
-        
-        // "return" key in either user or password field => OK
-
-        jtfUserName.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                userCancelled = false;
-                dispose();
-            }
-        });
-        
-        jpfPassword.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                userCancelled = false;
-                dispose();
-            }
-        });
-    }
-
-    /**
-     * Present a dialog to the user asking them for authentication information
-     * 
-     * @param hostThe host for with authentication is needed
-     * @param port The port being accessed
-     * @param prompt The prompt (realm) as presented by the server
-     * @param type The type of server (proxy/web)
-     * @return PasswordAuthentication containing the credentials (empty credentials if user cancelled)
-     */
-    protected PasswordAuthentication askUser(String host, int port, String prompt, String type) {
-        PasswordAuthentication auth = null;
-
-        host += port != -1 ? ":" + port : "";
-
-        // This frame is reusable. So reset everything first.
-        userCancelled = true;
-        jlInfo.setText("<html>The " + type + " server at " + host + " is requesting authentication. It says \"" + prompt + "\"</html>");
-
-        try {
-            SwingUtilities.invokeAndWait( new Runnable() {
-                public void run() {
-                    // show dialog to user
-                    setVisible(true);
-                }
-            });
-        
-            PluginDebug.debug("password dialog shown");
-            
-            // wait until dialog is gone
-            while (this.isShowing()) {
-                try {
-                    Thread.sleep(200);
-                } catch (InterruptedException ie) {
-                }
-            }
-            
-            PluginDebug.debug("password dialog closed");
-
-            if (!userCancelled) {
-                auth = new PasswordAuthentication(jtfUserName.getText(), jpfPassword.getText().toCharArray());
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            
-            // Nothing else we can do. Empty auth will be returned
-        }
-
-        return auth;
-    }
-
-    public static void main(String[] args) {
-        PasswordAuthenticationDialog frame = new PasswordAuthenticationDialog();
-
-        PasswordAuthentication auth = frame.askUser("127.0.0.1", 3128, "Password for local proxy", "proxy");
-
-        System.err.println("Auth info: " + auth.getUserName() + ":" + new String(auth.getPassword()));
-        System.exit(0);
-    }
-}
--- a/plugin/icedteanp/java/sun/applet/PluginMain.java	Fri Nov 19 10:35:27 2010 -0500
+++ b/plugin/icedteanp/java/sun/applet/PluginMain.java	Tue Nov 23 10:05:06 2010 -0500
@@ -77,6 +77,7 @@
 
 import net.sourceforge.jnlp.runtime.DeploymentConfiguration;
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.JNLPAuthenticator;
 
 /**
  * The main entry point into PluginAppletViewer.
@@ -202,8 +203,9 @@
 		boolean installAuthenticator = Boolean.valueOf(JNLPRuntime.getConfiguration()
 		        .getProperty(DeploymentConfiguration.KEY_SECURITY_INSTALL_AUTHENTICATOR));
 		if (installAuthenticator) {
-		    Authenticator.setDefault(new CustomAuthenticator());
+		    Authenticator.setDefault(new JNLPAuthenticator());
 		}
+        // override the proxy selector set by JNLPRuntime
         ProxySelector.setDefault(new PluginProxySelector());
         
         CookieManager ckManager = new PluginCookieManager();
@@ -218,24 +220,4 @@
     	return streamHandler.getMessage();
     }
     
-    static class CustomAuthenticator extends Authenticator {
-        
-        public PasswordAuthentication getPasswordAuthentication() {
-
-            // No security check is required here, because the only way to 
-            // set parameters for which auth info is needed 
-            // (Authenticator:requestPasswordAuthentication()), has a security 
-            // check
-
-            String type = this.getRequestorType() == RequestorType.PROXY ? "proxy" : "web"; 
-
-            // request auth info from user
-            PasswordAuthenticationDialog pwDialog = new PasswordAuthenticationDialog();
-            PasswordAuthentication auth = pwDialog.askUser(this.getRequestingHost(), this.getRequestingPort(), this.getRequestingPrompt(), type);
-            
-            // send it along
-            return auth;
-        }
-    }
-    
 }
--- a/plugin/icedteanp/java/sun/applet/PluginProxySelector.java	Fri Nov 19 10:35:27 2010 -0500
+++ b/plugin/icedteanp/java/sun/applet/PluginProxySelector.java	Tue Nov 23 10:05:06 2010 -0500
@@ -37,18 +37,16 @@
 
 package sun.applet;
 
-import java.io.IOException;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
-import java.net.ProxySelector;
-import java.net.SocketAddress;
 import java.net.URI;
 import java.util.Date;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import net.sourceforge.jnlp.runtime.JNLPProxySelector;
+
 /**
  * Proxy selector implementation for plugin network functions.
  * 
@@ -58,17 +56,10 @@
  * 
  */
 
-public class PluginProxySelector extends ProxySelector {
+public class PluginProxySelector extends JNLPProxySelector {
 
     private TimedHashMap<String, Proxy> proxyCache = new TimedHashMap<String, Proxy>(); 
 
-
-    @Override
-    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
-        // If the connection fails, there is little we can do here. Just print the exception
-        ioe.printStackTrace();
-    }
-
     /**
      * Selects the appropriate proxy (or DIRECT connection method) for the given URI
      * 
@@ -76,7 +67,7 @@
      * @return A list of Proxy objects that are usable for this URI
      */
     @Override
-    public List<Proxy> select(URI uri) {
+    protected List<Proxy> getFromBrowser(URI uri) {
 
         List<Proxy> proxyList = new ArrayList<Proxy>();