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

Last change on this file since 18821 was 18801, checked in by taylor.smock, 11 months ago

Fix #22832: Code cleanup and some simplification, documentation fixes (patch by gaben)

There should not be any functional changes in this patch; it is intended to do
the following:

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