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

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

sonar - squid:AssignmentInSubExpressionCheck - Assignments should not be made from within sub-expressions

  • 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.KeyAdapter;
17import java.awt.event.KeyEvent;
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 pnlCredentials = new OsmApiCredentialsPanel(this);
120 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
121 pnlCredentials.init(username, password);
122 validate();
123 }
124
125 public void prepareForOtherHostCredentials(String username, String password, String host) {
126 setTitle(tr("Enter credentials for host"));
127 pnlCredentials = new OtherHostCredentialsPanel(this, host);
128 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
129 pnlCredentials.init(username, password);
130 validate();
131 }
132
133 public void prepareForProxyCredentials(String username, String password) {
134 setTitle(tr("Enter credentials for HTTP proxy"));
135 pnlCredentials = new HttpProxyCredentialsPanel(this);
136 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
137 pnlCredentials.init(username, password);
138 validate();
139 }
140
141 public String getUsername() {
142 if (pnlCredentials == null)
143 return null;
144 return pnlCredentials.getUserName();
145 }
146
147 public char[] getPassword() {
148 if (pnlCredentials == null)
149 return null;
150 return pnlCredentials.getPassword();
151 }
152
153 public boolean isSaveCredentials() {
154 if (pnlCredentials == null)
155 return false;
156 return pnlCredentials.isSaveCredentials();
157 }
158
159 protected static class CredentialPanel extends JPanel {
160 protected JosmTextField tfUserName;
161 protected JosmPasswordField tfPassword;
162 protected JCheckBox cbSaveCredentials;
163 protected final JMultilineLabel lblHeading = new JMultilineLabel("");
164 protected final JMultilineLabel lblWarning = new JMultilineLabel("");
165 protected CredentialDialog owner; // owner Dependency Injection to use Key listeners for username and password text fields
166
167 protected void build() {
168 tfUserName = new JosmTextField(20);
169 tfPassword = new JosmPasswordField(20);
170 tfUserName.addFocusListener(new SelectAllOnFocusHandler());
171 tfPassword.addFocusListener(new SelectAllOnFocusHandler());
172 tfUserName.addKeyListener(new TFKeyListener(owner, tfUserName, tfPassword));
173 tfPassword.addKeyListener(new TFKeyListener(owner, tfPassword, tfUserName));
174 cbSaveCredentials = new JCheckBox(owner != null ? owner.saveUsernameAndPasswordCheckboxText : "");
175
176 setLayout(new GridBagLayout());
177 GridBagConstraints gc = new GridBagConstraints();
178 gc.gridwidth = 2;
179 gc.gridheight = 1;
180 gc.fill = GridBagConstraints.HORIZONTAL;
181 gc.weightx = 1.0;
182 gc.weighty = 0.0;
183 gc.insets = new Insets(0, 0, 10, 0);
184 add(lblHeading, gc);
185
186 gc.gridx = 0;
187 gc.gridy = 1;
188 gc.gridwidth = 1;
189 gc.gridheight = 1;
190 gc.fill = GridBagConstraints.HORIZONTAL;
191 gc.weightx = 0.0;
192 gc.weighty = 0.0;
193 gc.insets = new Insets(0, 0, 10, 10);
194 add(new JLabel(tr("Username")), gc);
195 gc.gridx = 1;
196 gc.gridy = 1;
197 gc.weightx = 1.0;
198 add(tfUserName, gc);
199 gc.gridx = 0;
200 gc.gridy = 2;
201 gc.weightx = 0.0;
202 add(new JLabel(tr("Password")), gc);
203
204 gc.gridx = 1;
205 gc.gridy = 2;
206 gc.weightx = 0.0;
207 add(tfPassword, gc);
208
209 gc.gridx = 0;
210 gc.gridy = 3;
211 gc.gridwidth = 2;
212 gc.gridheight = 1;
213 gc.fill = GridBagConstraints.BOTH;
214 gc.weightx = 1.0;
215 gc.weighty = 0.0;
216 lblWarning.setFont(lblWarning.getFont().deriveFont(Font.ITALIC));
217 add(lblWarning, gc);
218
219 gc.gridx = 0;
220 gc.gridy = 4;
221 gc.weighty = 0.0;
222 add(cbSaveCredentials, gc);
223
224 // consume the remaining space
225 gc.gridx = 0;
226 gc.gridy = 5;
227 gc.weighty = 1.0;
228 add(new JPanel(), gc);
229
230 }
231
232 public CredentialPanel(CredentialDialog owner) {
233 this.owner = owner;
234 }
235
236 public void init(String username, String password) {
237 username = username == null ? "" : username;
238 password = password == null ? "" : password;
239 tfUserName.setText(username);
240 tfPassword.setText(password);
241 cbSaveCredentials.setSelected(!username.isEmpty() && !password.isEmpty());
242 }
243
244 public void startUserInput() {
245 tfUserName.requestFocusInWindow();
246 }
247
248 public String getUserName() {
249 return tfUserName.getText();
250 }
251
252 public char[] getPassword() {
253 return tfPassword.getPassword();
254 }
255
256 public boolean isSaveCredentials() {
257 return cbSaveCredentials.isSelected();
258 }
259
260 protected final void updateWarningLabel(String url) {
261 boolean https = url != null && url.startsWith("https");
262 if (https) {
263 lblWarning.setText(null);
264 } else {
265 lblWarning.setText(tr("Warning: The password is transferred unencrypted."));
266 }
267 lblWarning.setVisible(!https);
268 }
269 }
270
271 private static class OsmApiCredentialsPanel extends CredentialPanel {
272
273 @Override
274 protected void build() {
275 super.build();
276 tfUserName.setToolTipText(tr("Please enter the user name of your OSM account"));
277 tfPassword.setToolTipText(tr("Please enter the password of your OSM account"));
278 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
279 lblHeading.setText(
280 "<html>" + tr("Authenticating at the OSM API ''{0}'' failed. Please enter a valid username and a valid password.",
281 apiUrl) + "</html>");
282 updateWarningLabel(apiUrl);
283 }
284
285 OsmApiCredentialsPanel(CredentialDialog owner) {
286 super(owner);
287 build();
288 }
289 }
290
291 private static class OtherHostCredentialsPanel extends CredentialPanel {
292
293 private final String host;
294
295 @Override
296 protected void build() {
297 super.build();
298 tfUserName.setToolTipText(tr("Please enter the user name of your account"));
299 tfPassword.setToolTipText(tr("Please enter the password of your account"));
300 lblHeading.setText(
301 "<html>" + tr("Authenticating at the host ''{0}'' failed. Please enter a valid username and a valid password.",
302 host) + "</html>");
303 updateWarningLabel(host);
304 }
305
306 OtherHostCredentialsPanel(CredentialDialog owner, String host) {
307 super(owner);
308 this.host = host;
309 build();
310 }
311 }
312
313 private static class HttpProxyCredentialsPanel extends CredentialPanel {
314 @Override
315 protected void build() {
316 super.build();
317 tfUserName.setToolTipText(tr("Please enter the user name for authenticating at your proxy server"));
318 tfPassword.setToolTipText(tr("Please enter the password for authenticating at your proxy server"));
319 lblHeading.setText(
320 "<html>" + tr("Authenticating at the HTTP proxy ''{0}'' failed. Please enter a valid username and a valid password.",
321 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_HOST) + ':' +
322 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_PORT)) + "</html>");
323 lblWarning.setText("<html>" +
324 tr("Warning: depending on the authentication method the proxy server uses the password may be transferred unencrypted.")
325 + "</html>");
326 }
327
328 HttpProxyCredentialsPanel(CredentialDialog owner) {
329 super(owner);
330 build();
331 }
332 }
333
334 private static class SelectAllOnFocusHandler extends FocusAdapter {
335 @Override
336 public void focusGained(FocusEvent e) {
337 if (e.getSource() instanceof JTextField) {
338 JTextField tf = (JTextField) e.getSource();
339 tf.selectAll();
340 }
341 }
342 }
343
344 /**
345 * Listener for username and password text fields key events.
346 * When user presses Enter:
347 * If current text field is empty (or just contains a sequence of spaces), nothing happens (or all spaces become selected).
348 * If current text field is not empty, but the next one is (or just contains a sequence of spaces), focuses the next text field.
349 * If both text fields contain characters, submits the form by calling owner's {@link OKAction}.
350 */
351 private static class TFKeyListener extends KeyAdapter {
352 protected CredentialDialog owner; // owner Dependency Injection to call OKAction
353 protected JTextField currentTF;
354 protected JTextField nextTF;
355
356 TFKeyListener(CredentialDialog owner, JTextField currentTF, JTextField nextTF) {
357 this.owner = owner;
358 this.currentTF = currentTF;
359 this.nextTF = nextTF;
360 }
361
362 @Override
363 public void keyPressed(KeyEvent e) {
364 if (e.getKeyChar() == KeyEvent.VK_ENTER) {
365 if (currentTF.getText().trim().isEmpty()) {
366 currentTF.selectAll();
367 return;
368 } else if (nextTF.getText().trim().isEmpty()) {
369 nextTF.requestFocusInWindow();
370 nextTF.selectAll();
371 return;
372 } else {
373 OKAction okAction = owner.new OKAction();
374 okAction.actionPerformed(null);
375 }
376 }
377 }
378 }
379
380 class OKAction extends AbstractAction {
381 OKAction() {
382 putValue(NAME, tr("Authenticate"));
383 putValue(SHORT_DESCRIPTION, tr("Authenticate with the supplied username and password"));
384 putValue(SMALL_ICON, ImageProvider.get("ok"));
385 }
386
387 @Override
388 public void actionPerformed(ActionEvent arg0) {
389 setCanceled(false);
390 setVisible(false);
391 }
392 }
393
394 class CancelAction extends AbstractAction {
395 CancelAction() {
396 putValue(NAME, tr("Cancel"));
397 putValue(SHORT_DESCRIPTION, tr("Cancel authentication"));
398 putValue(SMALL_ICON, ImageProvider.get("cancel"));
399 }
400
401 public void cancel() {
402 setCanceled(true);
403 setVisible(false);
404 }
405
406 @Override
407 public void actionPerformed(ActionEvent arg0) {
408 cancel();
409 }
410 }
411
412 class WindowEventHander extends WindowAdapter {
413
414 @Override
415 public void windowActivated(WindowEvent e) {
416 if (pnlCredentials != null) {
417 pnlCredentials.startUserInput();
418 }
419 }
420
421 @Override
422 public void windowClosing(WindowEvent e) {
423 new CancelAction().cancel();
424 }
425 }
426}
Note: See TracBrowser for help on using the repository browser.