source: josm/trunk/src/org/openstreetmap/josm/gui/io/CredentialDialog.java@ 9078

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

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 15.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Dimension;
8import java.awt.FlowLayout;
9import java.awt.Font;
10import java.awt.GridBagConstraints;
11import java.awt.GridBagLayout;
12import java.awt.Insets;
13import java.awt.event.ActionEvent;
14import java.awt.event.FocusAdapter;
15import java.awt.event.FocusEvent;
16import java.awt.event.KeyEvent;
17import java.awt.event.KeyListener;
18import java.awt.event.WindowAdapter;
19import java.awt.event.WindowEvent;
20import java.util.Objects;
21
22import javax.swing.AbstractAction;
23import javax.swing.BorderFactory;
24import javax.swing.JCheckBox;
25import javax.swing.JComponent;
26import javax.swing.JDialog;
27import javax.swing.JLabel;
28import javax.swing.JPanel;
29import javax.swing.JTextField;
30import javax.swing.KeyStroke;
31
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.gui.SideButton;
34import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
35import org.openstreetmap.josm.gui.help.HelpUtil;
36import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
37import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
38import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
39import org.openstreetmap.josm.gui.widgets.JosmTextField;
40import org.openstreetmap.josm.io.OsmApi;
41import org.openstreetmap.josm.tools.ImageProvider;
42import org.openstreetmap.josm.tools.WindowGeometry;
43
44public class CredentialDialog extends JDialog {
45
46 public static CredentialDialog getOsmApiCredentialDialog(String username, String password, String host,
47 String saveUsernameAndPasswordCheckboxText) {
48 CredentialDialog dialog = new CredentialDialog(saveUsernameAndPasswordCheckboxText);
49 if (Objects.equals(OsmApi.getOsmApi().getHost(), host)) {
50 dialog.prepareForOsmApiCredentials(username, password);
51 } else {
52 dialog.prepareForOtherHostCredentials(username, password, host);
53 }
54 dialog.pack();
55 return dialog;
56 }
57
58 public static CredentialDialog getHttpProxyCredentialDialog(String username, String password, String host,
59 String saveUsernameAndPasswordCheckboxText) {
60 CredentialDialog dialog = new CredentialDialog(saveUsernameAndPasswordCheckboxText);
61 dialog.prepareForProxyCredentials(username, password);
62 dialog.pack();
63 return dialog;
64 }
65
66 private boolean canceled;
67 protected CredentialPanel pnlCredentials;
68 private final String saveUsernameAndPasswordCheckboxText;
69
70 public boolean isCanceled() {
71 return canceled;
72 }
73
74 protected void setCanceled(boolean canceled) {
75 this.canceled = canceled;
76 }
77
78 @Override
79 public void setVisible(boolean visible) {
80 if (visible) {
81 WindowGeometry.centerInWindow(Main.parent, new Dimension(350, 300)).applySafe(this);
82 }
83 super.setVisible(visible);
84 }
85
86 protected JPanel createButtonPanel() {
87 JPanel pnl = new JPanel(new FlowLayout());
88 pnl.add(new SideButton(new OKAction()));
89 pnl.add(new SideButton(new CancelAction()));
90 pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/Password"))));
91 return pnl;
92 }
93
94 protected void build() {
95 getContentPane().setLayout(new BorderLayout());
96 getContentPane().add(createButtonPanel(), BorderLayout.SOUTH);
97
98 addWindowListener(new WindowEventHander());
99 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
100 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
101 getRootPane().getActionMap().put("escape", new CancelAction());
102
103 getRootPane().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
104 }
105
106 public CredentialDialog(String saveUsernameAndPasswordCheckboxText) {
107 this.saveUsernameAndPasswordCheckboxText = saveUsernameAndPasswordCheckboxText;
108 setModalityType(ModalityType.DOCUMENT_MODAL);
109 try {
110 setAlwaysOnTop(true);
111 } catch (SecurityException e) {
112 Main.warn(tr("Failed to put Credential Dialog always on top. Caught security exception."));
113 }
114 build();
115 }
116
117 public void prepareForOsmApiCredentials(String username, String password) {
118 setTitle(tr("Enter credentials for OSM API"));
119 getContentPane().add(pnlCredentials = new OsmApiCredentialsPanel(this), BorderLayout.CENTER);
120 pnlCredentials.init(username, password);
121 validate();
122 }
123
124 public void prepareForOtherHostCredentials(String username, String password, String host) {
125 setTitle(tr("Enter credentials for host"));
126 getContentPane().add(pnlCredentials = new OtherHostCredentialsPanel(this, host), BorderLayout.CENTER);
127 pnlCredentials.init(username, password);
128 validate();
129 }
130
131 public void prepareForProxyCredentials(String username, String password) {
132 setTitle(tr("Enter credentials for HTTP proxy"));
133 getContentPane().add(pnlCredentials = new HttpProxyCredentialsPanel(this), BorderLayout.CENTER);
134 pnlCredentials.init(username, password);
135 validate();
136 }
137
138 public String getUsername() {
139 if (pnlCredentials == null) return null;
140 return pnlCredentials.getUserName();
141 }
142
143 public char[] getPassword() {
144 if (pnlCredentials == null) return null;
145 return pnlCredentials.getPassword();
146 }
147
148 public boolean isSaveCredentials() {
149 if (pnlCredentials == null) return false;
150 return pnlCredentials.isSaveCredentials();
151 }
152
153 protected static class CredentialPanel extends JPanel {
154 protected JosmTextField tfUserName;
155 protected JosmPasswordField tfPassword;
156 protected JCheckBox cbSaveCredentials;
157 protected JMultilineLabel lblHeading;
158 protected JMultilineLabel lblWarning;
159 protected CredentialDialog owner; // owner Dependency Injection to use Key listeners for username and password text fields
160
161 protected void build() {
162 tfUserName = new JosmTextField(20);
163 tfPassword = new JosmPasswordField(20);
164 tfUserName.addFocusListener(new SelectAllOnFocusHandler());
165 tfPassword.addFocusListener(new SelectAllOnFocusHandler());
166 tfUserName.addKeyListener(new TFKeyListener(owner, tfUserName, tfPassword));
167 tfPassword.addKeyListener(new TFKeyListener(owner, tfPassword, tfUserName));
168 cbSaveCredentials = new JCheckBox(owner.saveUsernameAndPasswordCheckboxText);
169
170 setLayout(new GridBagLayout());
171 GridBagConstraints gc = new GridBagConstraints();
172 gc.gridwidth = 2;
173 gc.gridheight = 1;
174 gc.fill = GridBagConstraints.HORIZONTAL;
175 gc.weightx = 1.0;
176 gc.weighty = 0.0;
177 gc.insets = new Insets(0, 0, 10, 0);
178 add(lblHeading = new JMultilineLabel(""), gc);
179
180 gc.gridx = 0;
181 gc.gridy = 1;
182 gc.gridwidth = 1;
183 gc.gridheight = 1;
184 gc.fill = GridBagConstraints.HORIZONTAL;
185 gc.weightx = 0.0;
186 gc.weighty = 0.0;
187 gc.insets = new Insets(0, 0, 10, 10);
188 add(new JLabel(tr("Username")), gc);
189 gc.gridx = 1;
190 gc.gridy = 1;
191 gc.weightx = 1.0;
192 add(tfUserName, gc);
193 gc.gridx = 0;
194 gc.gridy = 2;
195 gc.weightx = 0.0;
196 add(new JLabel(tr("Password")), gc);
197
198 gc.gridx = 1;
199 gc.gridy = 2;
200 gc.weightx = 0.0;
201 add(tfPassword, gc);
202
203 gc.gridx = 0;
204 gc.gridy = 3;
205 gc.gridwidth = 2;
206 gc.gridheight = 1;
207 gc.fill = GridBagConstraints.BOTH;
208 gc.weightx = 1.0;
209 gc.weighty = 0.0;
210 lblWarning = new JMultilineLabel("");
211 lblWarning.setFont(lblWarning.getFont().deriveFont(Font.ITALIC));
212 add(lblWarning, gc);
213
214 gc.gridx = 0;
215 gc.gridy = 4;
216 gc.weighty = 0.0;
217 add(cbSaveCredentials, gc);
218
219 // consume the remaining space
220 gc.gridx = 0;
221 gc.gridy = 5;
222 gc.weighty = 1.0;
223 add(new JPanel(), gc);
224
225 }
226
227 public CredentialPanel(CredentialDialog owner) {
228 this.owner = owner;
229 }
230
231 public void init(String username, String password) {
232 username = username == null ? "" : username;
233 password = password == null ? "" : password;
234 tfUserName.setText(username);
235 tfPassword.setText(password);
236 cbSaveCredentials.setSelected(!username.isEmpty() && !password.isEmpty());
237 }
238
239 public void startUserInput() {
240 tfUserName.requestFocusInWindow();
241 }
242
243 public String getUserName() {
244 return tfUserName.getText();
245 }
246
247 public char[] getPassword() {
248 return tfPassword.getPassword();
249 }
250
251 public boolean isSaveCredentials() {
252 return cbSaveCredentials.isSelected();
253 }
254
255 protected final void updateWarningLabel(String url) {
256 boolean https = url != null && url.startsWith("https");
257 if (https) {
258 lblWarning.setText(null);
259 } else {
260 lblWarning.setText(tr("Warning: The password is transferred unencrypted."));
261 }
262 lblWarning.setVisible(!https);
263 }
264 }
265
266 private static class OsmApiCredentialsPanel extends CredentialPanel {
267
268 @Override
269 protected void build() {
270 super.build();
271 tfUserName.setToolTipText(tr("Please enter the user name of your OSM account"));
272 tfPassword.setToolTipText(tr("Please enter the password of your OSM account"));
273 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
274 lblHeading.setText(
275 "<html>" + tr("Authenticating at the OSM API ''{0}'' failed. Please enter a valid username and a valid password.",
276 apiUrl) + "</html>");
277 updateWarningLabel(apiUrl);
278 }
279
280 OsmApiCredentialsPanel(CredentialDialog owner) {
281 super(owner);
282 build();
283 }
284 }
285
286 private static class OtherHostCredentialsPanel extends CredentialPanel {
287
288 private final String host;
289
290 @Override
291 protected void build() {
292 super.build();
293 tfUserName.setToolTipText(tr("Please enter the user name of your account"));
294 tfPassword.setToolTipText(tr("Please enter the password of your account"));
295 lblHeading.setText(
296 "<html>" + tr("Authenticating at the host ''{0}'' failed. Please enter a valid username and a valid password.",
297 host) + "</html>");
298 updateWarningLabel(host);
299 }
300
301 OtherHostCredentialsPanel(CredentialDialog owner, String host) {
302 super(owner);
303 this.host = host;
304 build();
305 }
306 }
307
308 private static class HttpProxyCredentialsPanel extends CredentialPanel {
309 @Override
310 protected void build() {
311 super.build();
312 tfUserName.setToolTipText(tr("Please enter the user name for authenticating at your proxy server"));
313 tfPassword.setToolTipText(tr("Please enter the password for authenticating at your proxy server"));
314 lblHeading.setText(
315 "<html>" + tr("Authenticating at the HTTP proxy ''{0}'' failed. Please enter a valid username and a valid password.",
316 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_HOST) + ':' +
317 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_PORT)) + "</html>");
318 lblWarning.setText("<html>" +
319 tr("Warning: depending on the authentication method the proxy server uses the password may be transferred unencrypted.")
320 + "</html>");
321 }
322
323 HttpProxyCredentialsPanel(CredentialDialog owner) {
324 super(owner);
325 build();
326 }
327 }
328
329 private static class SelectAllOnFocusHandler extends FocusAdapter {
330 @Override
331 public void focusGained(FocusEvent e) {
332 if (e.getSource() instanceof JTextField) {
333 JTextField tf = (JTextField) e.getSource();
334 tf.selectAll();
335 }
336 }
337 }
338
339 /**
340 * Listener for username and password text fields key events.
341 * When user presses Enter:
342 * If current text field is empty (or just contains a sequence of spaces), nothing happens (or all spaces become selected).
343 * If current text field is not empty, but the next one is (or just contains a sequence of spaces), focuses the next text field.
344 * If both text fields contain characters, submits the form by calling owner's {@link OKAction}.
345 */
346 private static class TFKeyListener implements KeyListener {
347 protected CredentialDialog owner; // owner Dependency Injection to call OKAction
348 protected JTextField currentTF;
349 protected JTextField nextTF;
350
351 TFKeyListener(CredentialDialog owner, JTextField currentTF, JTextField nextTF) {
352 this.owner = owner;
353 this.currentTF = currentTF;
354 this.nextTF = nextTF;
355 }
356
357 @Override
358 public void keyPressed(KeyEvent e) {
359 if (e.getKeyChar() == KeyEvent.VK_ENTER) {
360 if (currentTF.getText().trim().isEmpty()) {
361 currentTF.selectAll();
362 return;
363 } else if (nextTF.getText().trim().isEmpty()) {
364 nextTF.requestFocusInWindow();
365 nextTF.selectAll();
366 return;
367 } else {
368 OKAction okAction = owner.new OKAction();
369 okAction.actionPerformed(null);
370 }
371 }
372 }
373
374 @Override
375 public void keyReleased(KeyEvent e) {
376 }
377
378 @Override
379 public void keyTyped(KeyEvent e) {
380 }
381 }
382
383 class OKAction extends AbstractAction {
384 OKAction() {
385 putValue(NAME, tr("Authenticate"));
386 putValue(SHORT_DESCRIPTION, tr("Authenticate with the supplied username and password"));
387 putValue(SMALL_ICON, ImageProvider.get("ok"));
388 }
389
390 @Override
391 public void actionPerformed(ActionEvent arg0) {
392 setCanceled(false);
393 setVisible(false);
394 }
395 }
396
397 class CancelAction extends AbstractAction {
398 CancelAction() {
399 putValue(NAME, tr("Cancel"));
400 putValue(SHORT_DESCRIPTION, tr("Cancel authentication"));
401 putValue(SMALL_ICON, ImageProvider.get("cancel"));
402 }
403
404 public void cancel() {
405 setCanceled(true);
406 setVisible(false);
407 }
408
409 @Override
410 public void actionPerformed(ActionEvent arg0) {
411 cancel();
412 }
413 }
414
415 class WindowEventHander extends WindowAdapter {
416
417 @Override
418 public void windowActivated(WindowEvent e) {
419 if (pnlCredentials != null) {
420 pnlCredentials.startUserInput();
421 }
422 }
423
424 @Override
425 public void windowClosing(WindowEvent e) {
426 new CancelAction().cancel();
427 }
428 }
429}
Note: See TracBrowser for help on using the repository browser.