source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java@ 11553

Last change on this file since 11553 was 11553, checked in by Don-vip, 7 years ago

refactor handling of null values - use Java 8 Optional where possible

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.server;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trc;
6
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.GridBagConstraints;
10import java.awt.GridBagLayout;
11import java.awt.Insets;
12import java.awt.event.ItemEvent;
13import java.awt.event.ItemListener;
14import java.net.Authenticator.RequestorType;
15import java.net.PasswordAuthentication;
16import java.net.ProxySelector;
17import java.util.EnumMap;
18import java.util.Locale;
19import java.util.Map;
20import java.util.Optional;
21
22import javax.swing.BorderFactory;
23import javax.swing.ButtonGroup;
24import javax.swing.JLabel;
25import javax.swing.JPanel;
26import javax.swing.JRadioButton;
27
28import org.openstreetmap.josm.Main;
29import org.openstreetmap.josm.gui.help.HelpUtil;
30import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
31import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
32import org.openstreetmap.josm.gui.widgets.JosmTextField;
33import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
34import org.openstreetmap.josm.io.DefaultProxySelector;
35import org.openstreetmap.josm.io.auth.CredentialsAgent;
36import org.openstreetmap.josm.io.auth.CredentialsAgentException;
37import org.openstreetmap.josm.io.auth.CredentialsManager;
38import org.openstreetmap.josm.tools.GBC;
39
40/**
41 * Component allowing input of proxy settings.
42 */
43public class ProxyPreferencesPanel extends VerticallyScrollablePanel {
44
45 static final class AutoSizePanel extends JPanel {
46 AutoSizePanel() {
47 super(new GridBagLayout());
48 }
49
50 @Override
51 public Dimension getMinimumSize() {
52 return getPreferredSize();
53 }
54 }
55
56 /**
57 * The proxy policy is how JOSM will use proxy information.
58 */
59 public enum ProxyPolicy {
60 /** No proxy: JOSM will access Internet resources directly */
61 NO_PROXY("no-proxy"),
62 /** Use system settings: JOSM will use system proxy settings */
63 USE_SYSTEM_SETTINGS("use-system-settings"),
64 /** Use HTTP proxy: JOSM will use the given HTTP proxy, configured manually */
65 USE_HTTP_PROXY("use-http-proxy"),
66 /** Use HTTP proxy: JOSM will use the given SOCKS proxy */
67 USE_SOCKS_PROXY("use-socks-proxy");
68
69 private final String policyName;
70
71 ProxyPolicy(String policyName) {
72 this.policyName = policyName;
73 }
74
75 /**
76 * Replies the policy name, to be stored in proxy preferences.
77 * @return the policy unique name
78 */
79 public String getName() {
80 return policyName;
81 }
82
83 /**
84 * Retrieves a proxy policy from its name found in preferences.
85 * @param policyName The policy name
86 * @return The proxy policy matching the given name, or {@code null}
87 */
88 public static ProxyPolicy fromName(String policyName) {
89 if (policyName == null) return null;
90 policyName = policyName.trim().toLowerCase(Locale.ENGLISH);
91 for (ProxyPolicy pp: values()) {
92 if (pp.getName().equals(policyName))
93 return pp;
94 }
95 return null;
96 }
97 }
98
99 /** Property key for proxy policy */
100 public static final String PROXY_POLICY = "proxy.policy";
101 /** Property key for HTTP proxy host */
102 public static final String PROXY_HTTP_HOST = "proxy.http.host";
103 /** Property key for HTTP proxy port */
104 public static final String PROXY_HTTP_PORT = "proxy.http.port";
105 /** Property key for SOCKS proxy host */
106 public static final String PROXY_SOCKS_HOST = "proxy.socks.host";
107 /** Property key for SOCKS proxy port */
108 public static final String PROXY_SOCKS_PORT = "proxy.socks.port";
109 /** Property key for proxy username */
110 public static final String PROXY_USER = "proxy.user";
111 /** Property key for proxy password */
112 public static final String PROXY_PASS = "proxy.pass";
113 /** Property key for proxy exceptions list */
114 public static final String PROXY_EXCEPTIONS = "proxy.exceptions";
115
116 private transient Map<ProxyPolicy, JRadioButton> rbProxyPolicy;
117 private final JosmTextField tfProxyHttpHost = new JosmTextField();
118 private final JosmTextField tfProxyHttpPort = new JosmTextField(5);
119 private final JosmTextField tfProxySocksHost = new JosmTextField(20);
120 private final JosmTextField tfProxySocksPort = new JosmTextField(5);
121 private final JosmTextField tfProxyHttpUser = new JosmTextField(20);
122 private final JosmPasswordField tfProxyHttpPassword = new JosmPasswordField(20);
123
124 private JPanel pnlHttpProxyConfigurationPanel;
125 private JPanel pnlSocksProxyConfigurationPanel;
126
127 /**
128 * Builds the panel for the HTTP proxy configuration
129 *
130 * @return panel with HTTP proxy configuration
131 */
132 protected final JPanel buildHttpProxyConfigurationPanel() {
133 JPanel pnl = new AutoSizePanel();
134 GridBagConstraints gc = new GridBagConstraints();
135
136 gc.anchor = GridBagConstraints.WEST;
137 gc.insets = new Insets(5, 5, 0, 0);
138 gc.fill = GridBagConstraints.HORIZONTAL;
139 gc.weightx = 0.0;
140 pnl.add(new JLabel(tr("Host:")), gc);
141
142 gc.gridx = 1;
143 gc.weightx = 1.0;
144 pnl.add(tfProxyHttpHost, gc);
145
146 gc.gridy = 1;
147 gc.gridx = 0;
148 gc.fill = GridBagConstraints.NONE;
149 gc.weightx = 0.0;
150 pnl.add(new JLabel(trc("server", "Port:")), gc);
151
152 gc.gridx = 1;
153 gc.weightx = 1.0;
154 pnl.add(tfProxyHttpPort, gc);
155 tfProxyHttpPort.setMinimumSize(tfProxyHttpPort.getPreferredSize());
156
157 gc.gridy = 2;
158 gc.gridx = 0;
159 gc.gridwidth = 2;
160 gc.fill = GridBagConstraints.HORIZONTAL;
161 gc.weightx = 1.0;
162 pnl.add(new JMultilineLabel(tr("Please enter a username and a password if your proxy requires authentication.")), gc);
163
164 gc.gridy = 3;
165 gc.gridx = 0;
166 gc.gridwidth = 1;
167 gc.fill = GridBagConstraints.NONE;
168 gc.weightx = 0.0;
169 pnl.add(new JLabel(tr("User:")), gc);
170
171 gc.gridy = 3;
172 gc.gridx = 1;
173 gc.weightx = 1.0;
174 pnl.add(tfProxyHttpUser, gc);
175 tfProxyHttpUser.setMinimumSize(tfProxyHttpUser.getPreferredSize());
176
177 gc.gridy = 4;
178 gc.gridx = 0;
179 gc.weightx = 0.0;
180 pnl.add(new JLabel(tr("Password:")), gc);
181
182 gc.gridx = 1;
183 gc.weightx = 1.0;
184 pnl.add(tfProxyHttpPassword, gc);
185 tfProxyHttpPassword.setMinimumSize(tfProxyHttpPassword.getPreferredSize());
186
187 // add an extra spacer, otherwise the layout is broken
188 gc.gridy = 5;
189 gc.gridx = 0;
190 gc.gridwidth = 2;
191 gc.fill = GridBagConstraints.BOTH;
192 gc.weightx = 1.0;
193 gc.weighty = 1.0;
194 pnl.add(new JPanel(), gc);
195 return pnl;
196 }
197
198 /**
199 * Builds the panel for the SOCKS proxy configuration
200 *
201 * @return panel with SOCKS proxy configuration
202 */
203 protected final JPanel buildSocksProxyConfigurationPanel() {
204 JPanel pnl = new AutoSizePanel();
205 GridBagConstraints gc = new GridBagConstraints();
206 gc.anchor = GridBagConstraints.WEST;
207 gc.insets = new Insets(5, 5, 0, 0);
208 gc.fill = GridBagConstraints.HORIZONTAL;
209 gc.weightx = 0.0;
210 pnl.add(new JLabel(tr("Host:")), gc);
211
212 gc.gridx = 1;
213 gc.weightx = 1.0;
214 pnl.add(tfProxySocksHost, gc);
215
216 gc.gridy = 1;
217 gc.gridx = 0;
218 gc.weightx = 0.0;
219 gc.fill = GridBagConstraints.NONE;
220 pnl.add(new JLabel(trc("server", "Port:")), gc);
221
222 gc.gridx = 1;
223 gc.weightx = 1.0;
224 pnl.add(tfProxySocksPort, gc);
225 tfProxySocksPort.setMinimumSize(tfProxySocksPort.getPreferredSize());
226
227 // add an extra spacer, otherwise the layout is broken
228 gc.gridy = 2;
229 gc.gridx = 0;
230 gc.gridwidth = 2;
231 gc.fill = GridBagConstraints.BOTH;
232 gc.weightx = 1.0;
233 gc.weighty = 1.0;
234 pnl.add(new JPanel(), gc);
235 return pnl;
236 }
237
238 protected final JPanel buildProxySettingsPanel() {
239 JPanel pnl = new JPanel(new GridBagLayout());
240 GridBagConstraints gc = new GridBagConstraints();
241
242 ButtonGroup bgProxyPolicy = new ButtonGroup();
243 rbProxyPolicy = new EnumMap<>(ProxyPolicy.class);
244 ProxyPolicyChangeListener policyChangeListener = new ProxyPolicyChangeListener();
245 for (ProxyPolicy pp: ProxyPolicy.values()) {
246 rbProxyPolicy.put(pp, new JRadioButton());
247 bgProxyPolicy.add(rbProxyPolicy.get(pp));
248 rbProxyPolicy.get(pp).addItemListener(policyChangeListener);
249 }
250
251 // radio button "No proxy"
252 gc.gridx = 0;
253 gc.gridy = 0;
254 gc.fill = GridBagConstraints.HORIZONTAL;
255 gc.anchor = GridBagConstraints.NORTHWEST;
256 gc.weightx = 0.0;
257 pnl.add(rbProxyPolicy.get(ProxyPolicy.NO_PROXY), gc);
258
259 gc.gridx = 1;
260 gc.weightx = 1.0;
261 pnl.add(new JLabel(tr("No proxy")), gc);
262
263 // radio button "System settings"
264 gc.gridx = 0;
265 gc.gridy = 1;
266 gc.weightx = 0.0;
267 pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_SYSTEM_SETTINGS), gc);
268
269 gc.gridx = 1;
270 gc.weightx = 1.0;
271 String msg;
272 if (DefaultProxySelector.willJvmRetrieveSystemProxies()) {
273 msg = tr("Use standard system settings");
274 } else {
275 msg = tr("Use standard system settings (disabled. Start JOSM with <tt>-Djava.net.useSystemProxies=true</tt> to enable)");
276 }
277 pnl.add(new JMultilineLabel("<html>" + msg + "</html>"), gc);
278
279 // radio button http proxy
280 gc.gridx = 0;
281 gc.gridy = 2;
282 gc.weightx = 0.0;
283 pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY), gc);
284
285 gc.gridx = 1;
286 gc.weightx = 1.0;
287 pnl.add(new JLabel(tr("Manually configure a HTTP proxy")), gc);
288
289 // the panel with the http proxy configuration parameters
290 gc.gridx = 1;
291 gc.gridy = 3;
292 gc.fill = GridBagConstraints.HORIZONTAL;
293 gc.weightx = 1.0;
294 gc.weighty = 0.0;
295 pnlHttpProxyConfigurationPanel = buildHttpProxyConfigurationPanel();
296 pnl.add(pnlHttpProxyConfigurationPanel, gc);
297
298 // radio button SOCKS proxy
299 gc.gridx = 0;
300 gc.gridy = 4;
301 gc.weightx = 0.0;
302 pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_SOCKS_PROXY), gc);
303
304 gc.gridx = 1;
305 gc.weightx = 1.0;
306 pnl.add(new JLabel(tr("Use a SOCKS proxy")), gc);
307
308 // the panel with the SOCKS configuration parameters
309 gc.gridx = 1;
310 gc.gridy = 5;
311 gc.fill = GridBagConstraints.BOTH;
312 gc.anchor = GridBagConstraints.WEST;
313 gc.weightx = 1.0;
314 gc.weighty = 0.0;
315 pnlSocksProxyConfigurationPanel = buildSocksProxyConfigurationPanel();
316 pnl.add(pnlSocksProxyConfigurationPanel, gc);
317
318 return pnl;
319 }
320
321 /**
322 * Initializes the panel with the values from the preferences
323 */
324 public final void initFromPreferences() {
325 ProxyPolicy pp = Optional.ofNullable(ProxyPolicy.fromName(Main.pref.get(PROXY_POLICY, null))).orElse(ProxyPolicy.NO_PROXY);
326 rbProxyPolicy.get(pp).setSelected(true);
327 String value = Main.pref.get("proxy.host", null);
328 if (value != null) {
329 // legacy support
330 tfProxyHttpHost.setText(value);
331 Main.pref.put("proxy.host", null);
332 } else {
333 tfProxyHttpHost.setText(Main.pref.get(PROXY_HTTP_HOST, ""));
334 }
335 value = Main.pref.get("proxy.port", null);
336 if (value != null) {
337 // legacy support
338 tfProxyHttpPort.setText(value);
339 Main.pref.put("proxy.port", null);
340 } else {
341 tfProxyHttpPort.setText(Main.pref.get(PROXY_HTTP_PORT, ""));
342 }
343 tfProxySocksHost.setText(Main.pref.get(PROXY_SOCKS_HOST, ""));
344 tfProxySocksPort.setText(Main.pref.get(PROXY_SOCKS_PORT, ""));
345
346 if (pp.equals(ProxyPolicy.USE_SYSTEM_SETTINGS) && !DefaultProxySelector.willJvmRetrieveSystemProxies()) {
347 Main.warn(tr("JOSM is configured to use proxies from the system setting, but the JVM is not configured to retrieve them. " +
348 "Resetting preferences to ''No proxy''"));
349 pp = ProxyPolicy.NO_PROXY;
350 rbProxyPolicy.get(pp).setSelected(true);
351 }
352
353 // save the proxy user and the proxy password to a credentials store managed by
354 // the credentials manager
355 CredentialsAgent cm = CredentialsManager.getInstance();
356 try {
357 PasswordAuthentication pa = cm.lookup(RequestorType.PROXY, tfProxyHttpHost.getText());
358 if (pa == null) {
359 tfProxyHttpUser.setText("");
360 tfProxyHttpPassword.setText("");
361 } else {
362 tfProxyHttpUser.setText(pa.getUserName() == null ? "" : pa.getUserName());
363 tfProxyHttpPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
364 }
365 } catch (CredentialsAgentException e) {
366 Main.error(e);
367 tfProxyHttpUser.setText("");
368 tfProxyHttpPassword.setText("");
369 }
370 }
371
372 protected final void updateEnabledState() {
373 boolean isHttpProxy = rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY).isSelected();
374 for (Component c: pnlHttpProxyConfigurationPanel.getComponents()) {
375 c.setEnabled(isHttpProxy);
376 }
377
378 boolean isSocksProxy = rbProxyPolicy.get(ProxyPolicy.USE_SOCKS_PROXY).isSelected();
379 for (Component c: pnlSocksProxyConfigurationPanel.getComponents()) {
380 c.setEnabled(isSocksProxy);
381 }
382
383 rbProxyPolicy.get(ProxyPolicy.USE_SYSTEM_SETTINGS).setEnabled(DefaultProxySelector.willJvmRetrieveSystemProxies());
384 }
385
386 class ProxyPolicyChangeListener implements ItemListener {
387 @Override
388 public void itemStateChanged(ItemEvent arg0) {
389 updateEnabledState();
390 }
391 }
392
393 /**
394 * Constructs a new {@code ProxyPreferencesPanel}.
395 */
396 public ProxyPreferencesPanel() {
397 setLayout(new GridBagLayout());
398 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
399 add(buildProxySettingsPanel(), GBC.eop().anchor(GridBagConstraints.NORTHWEST).fill(GridBagConstraints.BOTH));
400
401 initFromPreferences();
402 updateEnabledState();
403
404 HelpUtil.setHelpContext(this, HelpUtil.ht("/Preferences/Connection#ProxySettings"));
405 }
406
407 /**
408 * Saves the current values to the preferences
409 */
410 public void saveToPreferences() {
411 ProxyPolicy policy = null;
412 for (ProxyPolicy pp: ProxyPolicy.values()) {
413 if (rbProxyPolicy.get(pp).isSelected()) {
414 policy = pp;
415 break;
416 }
417 }
418 Main.pref.put(PROXY_POLICY, Optional.ofNullable(policy).orElse(ProxyPolicy.NO_PROXY).getName());
419 Main.pref.put(PROXY_HTTP_HOST, tfProxyHttpHost.getText());
420 Main.pref.put(PROXY_HTTP_PORT, tfProxyHttpPort.getText());
421 Main.pref.put(PROXY_SOCKS_HOST, tfProxySocksHost.getText());
422 Main.pref.put(PROXY_SOCKS_PORT, tfProxySocksPort.getText());
423
424 // update the proxy selector
425 ProxySelector selector = ProxySelector.getDefault();
426 if (selector instanceof DefaultProxySelector) {
427 ((DefaultProxySelector) selector).initFromPreferences();
428 }
429
430 CredentialsAgent cm = CredentialsManager.getInstance();
431 try {
432 PasswordAuthentication pa = new PasswordAuthentication(
433 tfProxyHttpUser.getText().trim(),
434 tfProxyHttpPassword.getPassword()
435 );
436 cm.store(RequestorType.PROXY, tfProxyHttpHost.getText(), pa);
437 } catch (CredentialsAgentException e) {
438 Main.error(e);
439 }
440 }
441}
Note: See TracBrowser for help on using the repository browser.