001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.io;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.io.IOException;
007 import java.net.InetSocketAddress;
008 import java.net.Proxy;
009 import java.net.ProxySelector;
010 import java.net.SocketAddress;
011 import java.net.URI;
012 import java.net.Proxy.Type;
013 import java.util.Collections;
014 import java.util.List;
015
016 import org.openstreetmap.josm.Main;
017 import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
018 import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel.ProxyPolicy;
019
020 /**
021 * This is the default proxy selector used in JOSM.
022 *
023 */
024 public class DefaultProxySelector extends ProxySelector {
025 /**
026 * The {@link ProxySelector} provided by the JDK will retrieve proxy information
027 * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
028 * is defined <strong>at startup</strong>. It has no effect if the property is set
029 * later by the application.
030 *
031 * We therefore read the property at class loading time and remember it's value.
032 */
033 private static boolean JVM_WILL_USE_SYSTEM_PROXIES = false;
034 {
035 String v = System.getProperty("java.net.useSystemProxies");
036 if (v != null && v.equals(Boolean.TRUE.toString())) {
037 JVM_WILL_USE_SYSTEM_PROXIES = true;
038 }
039 }
040
041 /**
042 * The {@link ProxySelector} provided by the JDK will retrieve proxy information
043 * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
044 * is defined <strong>at startup</strong>. If the property is set later by the application,
045 * this has no effect.
046 *
047 * @return true, if <tt>java.net.useSystemProxies</tt> was set to true at class initialization time
048 *
049 */
050 public static boolean willJvmRetrieveSystemProxies() {
051 return JVM_WILL_USE_SYSTEM_PROXIES;
052 }
053
054 private ProxyPolicy proxyPolicy;
055 private InetSocketAddress httpProxySocketAddress;
056 private InetSocketAddress socksProxySocketAddress;
057 private ProxySelector delegate;
058
059 /**
060 * A typical example is:
061 * <pre>
062 * PropertySelector delegate = PropertySelector.getDefault();
063 * PropertySelector.setDefault(new DefaultPropertySelector(delegate));
064 * </pre>
065 *
066 * @param delegate the proxy selector to delegate to if system settings are used. Usually
067 * this is the proxy selector found by ProxySelector.getDefault() before this proxy
068 * selector is installed
069 */
070 public DefaultProxySelector(ProxySelector delegate) {
071 this.delegate = delegate;
072 initFromPreferences();
073 }
074
075 protected int parseProxyPortValue(String property, String value) {
076 if (value == null) return 0;
077 int port = 0;
078 try {
079 port = Integer.parseInt(value);
080 } catch (NumberFormatException e) {
081 System.err.println(tr("Unexpected format for port number in in preference ''{0}''. Got ''{1}''.", property, value));
082 System.err.println(tr("The proxy will not be used."));
083 return 0;
084 }
085 if (port <= 0 || port > 65535) {
086 System.err.println(tr("Illegal port number in preference ''{0}''. Got {1}.", property, port));
087 System.err.println(tr("The proxy will not be used."));
088 return 0;
089 }
090 return port;
091 }
092
093 /**
094 * Initializes the proxy selector from the setting in the preferences.
095 *
096 */
097 public void initFromPreferences() {
098 String value = Main.pref.get(ProxyPreferencesPanel.PROXY_POLICY);
099 if (value.length() == 0) {
100 proxyPolicy = ProxyPolicy.NO_PROXY;
101 } else {
102 proxyPolicy= ProxyPolicy.fromName(value);
103 if (proxyPolicy == null) {
104 System.err.println(tr("Warning: unexpected value for preference ''{0}'' found. Got ''{1}''. Will use no proxy.", ProxyPreferencesPanel.PROXY_POLICY, value));
105 proxyPolicy = ProxyPolicy.NO_PROXY;
106 }
107 }
108 String host = Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_HOST, null);
109 int port = parseProxyPortValue(ProxyPreferencesPanel.PROXY_HTTP_PORT, Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_PORT, null));
110 if (host != null && ! host.trim().equals("") && port > 0) {
111 httpProxySocketAddress = new InetSocketAddress(host,port);
112 } else {
113 httpProxySocketAddress = null;
114 if (proxyPolicy.equals(ProxyPolicy.USE_HTTP_PROXY)) {
115 System.err.println(tr("Warning: Unexpected parameters for HTTP proxy. Got host ''{0}'' and port ''{1}''.", host, port));
116 System.err.println(tr("The proxy will not be used."));
117 }
118 }
119
120 host = Main.pref.get(ProxyPreferencesPanel.PROXY_SOCKS_HOST, null);
121 port = parseProxyPortValue(ProxyPreferencesPanel.PROXY_SOCKS_PORT, Main.pref.get(ProxyPreferencesPanel.PROXY_SOCKS_PORT, null));
122 if (host != null && ! host.trim().equals("") && port > 0) {
123 socksProxySocketAddress = new InetSocketAddress(host,port);
124 } else {
125 socksProxySocketAddress = null;
126 if (proxyPolicy.equals(ProxyPolicy.USE_SOCKS_PROXY)) {
127 System.err.println(tr("Warning: Unexpected parameters for SOCKS proxy. Got host ''{0}'' and port ''{1}''.", host, port));
128 System.err.println(tr("The proxy will not be used."));
129 }
130 }
131 }
132
133 @Override
134 public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
135 // Just log something. The network stack will also throw an exception which will be caught
136 // somewhere else
137 //
138 System.out.println(tr("Error: Connection to proxy ''{0}'' for URI ''{1}'' failed. Exception was: {2}", sa.toString(), uri.toString(), ioe.toString()));
139 }
140
141 @Override
142 public List<Proxy> select(URI uri) {
143 Proxy proxy;
144 switch(proxyPolicy) {
145 case USE_SYSTEM_SETTINGS:
146 if (!JVM_WILL_USE_SYSTEM_PROXIES) {
147 System.err.println(tr("Warning: the JVM is not configured to lookup proxies from the system settings. The property ''java.net.useSystemProxies'' was missing at startup time. Will not use a proxy."));
148 return Collections.singletonList(Proxy.NO_PROXY);
149 }
150 // delegate to the former proxy selector
151 List<Proxy> ret = delegate.select(uri);
152 return ret;
153 case NO_PROXY:
154 return Collections.singletonList(Proxy.NO_PROXY);
155 case USE_HTTP_PROXY:
156 if (httpProxySocketAddress == null)
157 return Collections.singletonList(Proxy.NO_PROXY);
158 proxy = new Proxy(Type.HTTP, httpProxySocketAddress);
159 return Collections.singletonList(proxy);
160 case USE_SOCKS_PROXY:
161 if (socksProxySocketAddress == null)
162 return Collections.singletonList(Proxy.NO_PROXY);
163 proxy = new Proxy(Type.SOCKS, socksProxySocketAddress);
164 return Collections.singletonList(proxy);
165 }
166 // should not happen
167 return null;
168 }
169 }