source: josm/trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java@ 13194

Last change on this file since 13194 was 12846, checked in by bastiK, 7 years ago

see #15229 - use Config.getPref() wherever possible

  • Property svn:eol-style set to native
File size: 9.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.net.InetSocketAddress;
8import java.net.Proxy;
9import java.net.Proxy.Type;
10import java.net.ProxySelector;
11import java.net.SocketAddress;
12import java.net.URI;
13import java.util.Arrays;
14import java.util.Collections;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Set;
18import java.util.TreeSet;
19
20import org.openstreetmap.josm.spi.preferences.Config;
21import org.openstreetmap.josm.tools.Logging;
22
23/**
24 * This is the default proxy selector used in JOSM.
25 * @since 2641
26 */
27public class DefaultProxySelector extends ProxySelector {
28
29 /** Property key for proxy policy */
30 public static final String PROXY_POLICY = "proxy.policy";
31 /** Property key for HTTP proxy host */
32 public static final String PROXY_HTTP_HOST = "proxy.http.host";
33 /** Property key for HTTP proxy port */
34 public static final String PROXY_HTTP_PORT = "proxy.http.port";
35 /** Property key for SOCKS proxy host */
36 public static final String PROXY_SOCKS_HOST = "proxy.socks.host";
37 /** Property key for SOCKS proxy port */
38 public static final String PROXY_SOCKS_PORT = "proxy.socks.port";
39 /** Property key for proxy username */
40 public static final String PROXY_USER = "proxy.user";
41 /** Property key for proxy password */
42 public static final String PROXY_PASS = "proxy.pass";
43 /** Property key for proxy exceptions list */
44 public static final String PROXY_EXCEPTIONS = "proxy.exceptions";
45
46 private static final List<Proxy> NO_PROXY_LIST = Collections.singletonList(Proxy.NO_PROXY);
47
48 private static final String IPV4_LOOPBACK = "127.0.0.1";
49 private static final String IPV6_LOOPBACK = "::1";
50
51 /**
52 * The {@link ProxySelector} provided by the JDK will retrieve proxy information
53 * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
54 * is defined <strong>at startup</strong>. It has no effect if the property is set
55 * later by the application.
56 *
57 * We therefore read the property at class loading time and remember it's value.
58 */
59 private static boolean jvmWillUseSystemProxies;
60 static {
61 String v = System.getProperty("java.net.useSystemProxies");
62 if (v != null && v.equals(Boolean.TRUE.toString())) {
63 jvmWillUseSystemProxies = true;
64 }
65 }
66
67 /**
68 * The {@link ProxySelector} provided by the JDK will retrieve proxy information
69 * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
70 * is defined <strong>at startup</strong>. If the property is set later by the application,
71 * this has no effect.
72 *
73 * @return true, if <tt>java.net.useSystemProxies</tt> was set to true at class initialization time
74 *
75 */
76 public static boolean willJvmRetrieveSystemProxies() {
77 return jvmWillUseSystemProxies;
78 }
79
80 private ProxyPolicy proxyPolicy;
81 private InetSocketAddress httpProxySocketAddress;
82 private InetSocketAddress socksProxySocketAddress;
83 private final ProxySelector delegate;
84
85 private final Set<String> errorResources = new HashSet<>();
86 private final Set<String> errorMessages = new HashSet<>();
87 private Set<String> proxyExceptions;
88
89 /**
90 * A typical example is:
91 * <pre>
92 * PropertySelector delegate = PropertySelector.getDefault();
93 * PropertySelector.setDefault(new DefaultPropertySelector(delegate));
94 * </pre>
95 *
96 * @param delegate the proxy selector to delegate to if system settings are used. Usually
97 * this is the proxy selector found by ProxySelector.getDefault() before this proxy
98 * selector is installed
99 */
100 public DefaultProxySelector(ProxySelector delegate) {
101 this.delegate = delegate;
102 initFromPreferences();
103 }
104
105 protected int parseProxyPortValue(String property, String value) {
106 if (value == null) return 0;
107 int port = 0;
108 try {
109 port = Integer.parseInt(value);
110 } catch (NumberFormatException e) {
111 Logging.error(tr("Unexpected format for port number in preference ''{0}''. Got ''{1}''.", property, value));
112 Logging.error(tr("The proxy will not be used."));
113 return 0;
114 }
115 if (port <= 0 || port > 65_535) {
116 Logging.error(tr("Illegal port number in preference ''{0}''. Got {1}.", property, port));
117 Logging.error(tr("The proxy will not be used."));
118 return 0;
119 }
120 return port;
121 }
122
123 /**
124 * Initializes the proxy selector from the setting in the preferences.
125 *
126 */
127 public final void initFromPreferences() {
128 String value = Config.getPref().get(PROXY_POLICY);
129 if (value.isEmpty()) {
130 proxyPolicy = ProxyPolicy.NO_PROXY;
131 } else {
132 proxyPolicy = ProxyPolicy.fromName(value);
133 if (proxyPolicy == null) {
134 Logging.warn(tr("Unexpected value for preference ''{0}'' found. Got ''{1}''. Will use no proxy.",
135 PROXY_POLICY, value));
136 proxyPolicy = ProxyPolicy.NO_PROXY;
137 }
138 }
139 String host = Config.getPref().get(PROXY_HTTP_HOST, null);
140 int port = parseProxyPortValue(PROXY_HTTP_PORT, Config.getPref().get(PROXY_HTTP_PORT, null));
141 httpProxySocketAddress = null;
142 if (proxyPolicy.equals(ProxyPolicy.USE_HTTP_PROXY)) {
143 if (host != null && !host.trim().isEmpty() && port > 0) {
144 httpProxySocketAddress = new InetSocketAddress(host, port);
145 } else {
146 Logging.warn(tr("Unexpected parameters for HTTP proxy. Got host ''{0}'' and port ''{1}''.", host, port));
147 Logging.warn(tr("The proxy will not be used."));
148 }
149 }
150
151 host = Config.getPref().get(PROXY_SOCKS_HOST, null);
152 port = parseProxyPortValue(PROXY_SOCKS_PORT, Config.getPref().get(PROXY_SOCKS_PORT, null));
153 socksProxySocketAddress = null;
154 if (proxyPolicy.equals(ProxyPolicy.USE_SOCKS_PROXY)) {
155 if (host != null && !host.trim().isEmpty() && port > 0) {
156 socksProxySocketAddress = new InetSocketAddress(host, port);
157 } else {
158 Logging.warn(tr("Unexpected parameters for SOCKS proxy. Got host ''{0}'' and port ''{1}''.", host, port));
159 Logging.warn(tr("The proxy will not be used."));
160 }
161 }
162 proxyExceptions = new HashSet<>(
163 Config.getPref().getList(PROXY_EXCEPTIONS,
164 Arrays.asList("localhost", IPV4_LOOPBACK, IPV6_LOOPBACK))
165 );
166 }
167
168 @Override
169 public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
170 // Just log something. The network stack will also throw an exception which will be caught somewhere else
171 Logging.error(tr("Connection to proxy ''{0}'' for URI ''{1}'' failed. Exception was: {2}",
172 sa.toString(), uri.toString(), ioe.toString()));
173 // Remember errors to give a friendly user message asking to review proxy configuration
174 errorResources.add(uri.toString());
175 errorMessages.add(ioe.toString());
176 }
177
178 /**
179 * Returns the set of current proxy resources that failed to be retrieved.
180 * @return the set of current proxy resources that failed to be retrieved
181 * @since 6523
182 */
183 public final Set<String> getErrorResources() {
184 return new TreeSet<>(errorResources);
185 }
186
187 /**
188 * Returns the set of current proxy error messages.
189 * @return the set of current proxy error messages
190 * @since 6523
191 */
192 public final Set<String> getErrorMessages() {
193 return new TreeSet<>(errorMessages);
194 }
195
196 /**
197 * Clear the sets of failed resources and error messages.
198 * @since 6523
199 */
200 public final void clearErrors() {
201 errorResources.clear();
202 errorMessages.clear();
203 }
204
205 /**
206 * Determines if proxy errors have occured.
207 * @return {@code true} if errors have occured, {@code false} otherwise.
208 * @since 6523
209 */
210 public final boolean hasErrors() {
211 return !errorResources.isEmpty();
212 }
213
214 @Override
215 public List<Proxy> select(URI uri) {
216 if (uri != null && proxyExceptions.contains(uri.getHost())) {
217 return NO_PROXY_LIST;
218 }
219 switch(proxyPolicy) {
220 case USE_SYSTEM_SETTINGS:
221 if (!jvmWillUseSystemProxies) {
222 Logging.warn(tr("The JVM is not configured to lookup proxies from the system settings. "+
223 "The property ''java.net.useSystemProxies'' was missing at startup time. Will not use a proxy."));
224 return NO_PROXY_LIST;
225 }
226 // delegate to the former proxy selector
227 return delegate.select(uri);
228 case NO_PROXY:
229 return NO_PROXY_LIST;
230 case USE_HTTP_PROXY:
231 if (httpProxySocketAddress == null)
232 return NO_PROXY_LIST;
233 return Collections.singletonList(new Proxy(Type.HTTP, httpProxySocketAddress));
234 case USE_SOCKS_PROXY:
235 if (socksProxySocketAddress == null)
236 return NO_PROXY_LIST;
237 return Collections.singletonList(new Proxy(Type.SOCKS, socksProxySocketAddress));
238 }
239 // should not happen
240 return null;
241 }
242}
Note: See TracBrowser for help on using the repository browser.