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 }