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

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

Rework console output:

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