001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.oauth;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.Component;
007    import java.awt.GridBagConstraints;
008    import java.awt.GridBagLayout;
009    import java.awt.Insets;
010    import java.awt.event.ItemEvent;
011    import java.awt.event.ItemListener;
012    
013    import javax.swing.BorderFactory;
014    import javax.swing.JCheckBox;
015    import javax.swing.JLabel;
016    import javax.swing.JOptionPane;
017    import javax.swing.JTextField;
018    
019    import org.openstreetmap.josm.data.Preferences;
020    import org.openstreetmap.josm.data.oauth.OAuthParameters;
021    import org.openstreetmap.josm.gui.HelpAwareOptionPane;
022    import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
023    import org.openstreetmap.josm.gui.help.HelpUtil;
024    import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
025    import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
026    import org.openstreetmap.josm.tools.CheckParameterUtil;
027    import org.openstreetmap.josm.tools.ImageProvider;
028    
029    /**
030     * Panel allowing the user to setup advanced OAuth parameters:
031     * <li>Consumer key</li>
032     * <li>Consumer secret</li>
033     * <li>Request token URL</li>
034     * <li>Access token URL</li>
035     * <li>Authorize URL</li>
036     * 
037     * @see OAuthParameters
038     * @since 2746
039     */
040    public class AdvancedOAuthPropertiesPanel extends VerticallyScrollablePanel {
041    
042        private JCheckBox cbUseDefaults;
043        private JTextField tfConsumerKey;
044        private JTextField tfConsumerSecret;
045        private JTextField tfRequestTokenURL;
046        private JTextField tfAccessTokenURL;
047        private JTextField tfAuthoriseURL;
048        private UseDefaultItemListener ilUseDefault;
049        private String apiUrl;
050    
051        protected void build() {
052            setLayout(new GridBagLayout());
053            setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
054            GridBagConstraints gc = new GridBagConstraints();
055    
056            gc.anchor = GridBagConstraints.NORTHWEST;
057            gc.fill = GridBagConstraints.HORIZONTAL;
058            gc.weightx = 1.0;
059            gc.insets = new Insets(0,0, 3, 3);
060            gc.gridwidth = 2;
061            cbUseDefaults = new JCheckBox(tr("Use default settings"));
062            add(cbUseDefaults, gc);
063    
064            // -- consumer key
065            gc.gridy = 1;
066            gc.weightx = 0.0;
067            gc.gridwidth = 1;
068            add(new JLabel(tr("Consumer Key:")), gc);
069    
070            gc.gridx = 1;
071            gc.weightx = 1.0;
072            add(tfConsumerKey = new JTextField(), gc);
073            SelectAllOnFocusGainedDecorator.decorate(tfConsumerKey);
074    
075            // -- consumer secret
076            gc.gridy = 2;
077            gc.gridx = 0;
078            gc.weightx = 0.0;
079            add(new JLabel(tr("Consumer Secret:")), gc);
080    
081            gc.gridx = 1;
082            gc.weightx = 1.0;
083            add(tfConsumerSecret = new JTextField(), gc);
084            SelectAllOnFocusGainedDecorator.decorate(tfConsumerSecret);
085    
086            // -- request token URL
087            gc.gridy = 3;
088            gc.gridx = 0;
089            gc.weightx = 0.0;
090            add(new JLabel(tr("Request Token URL:")), gc);
091    
092            gc.gridx = 1;
093            gc.weightx = 1.0;
094            add(tfRequestTokenURL = new JTextField(), gc);
095            SelectAllOnFocusGainedDecorator.decorate(tfRequestTokenURL);
096    
097            // -- access token URL
098            gc.gridy = 4;
099            gc.gridx = 0;
100            gc.weightx = 0.0;
101            add(new JLabel(tr("Access Token URL:")), gc);
102    
103            gc.gridx = 1;
104            gc.weightx = 1.0;
105            add(tfAccessTokenURL = new JTextField(), gc);
106            SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenURL);
107    
108    
109            // -- authorise URL
110            gc.gridy = 5;
111            gc.gridx = 0;
112            gc.weightx = 0.0;
113            add(new JLabel(tr("Authorize URL:")), gc);
114    
115            gc.gridx = 1;
116            gc.weightx = 1.0;
117            add(tfAuthoriseURL = new JTextField(), gc);
118            SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL);
119    
120            cbUseDefaults.addItemListener(ilUseDefault = new UseDefaultItemListener());
121        }
122    
123        protected boolean hasCustomSettings() {
124            OAuthParameters params = OAuthParameters.createDefault(apiUrl);
125            return
126               ! tfConsumerKey.getText().equals(params.getConsumerKey())
127            || ! tfConsumerSecret.getText().equals(params.getConsumerSecret())
128            || ! tfRequestTokenURL.getText().equals(params.getRequestTokenUrl())
129            || ! tfAccessTokenURL.getText().equals(params.getAccessTokenUrl())
130            || ! tfAuthoriseURL.getText().equals(params.getAuthoriseUrl());
131        }
132    
133        protected boolean confirmOverwriteCustomSettings() {
134            ButtonSpec[] buttons = new ButtonSpec[] {
135                    new ButtonSpec(
136                            tr("Continue"),
137                            ImageProvider.get("ok"),
138                            tr("Click to reset the OAuth settings to default values"),
139                            null /* no dedicated help topic */
140                    ),
141                    new ButtonSpec(
142                            tr("Cancel"),
143                            ImageProvider.get("cancel"),
144                            tr("Click to abort resetting to the OAuth default values"),
145                            null /* no dedicated help topic */
146                    )
147            };
148            int ret = HelpAwareOptionPane.showOptionDialog(
149                    AdvancedOAuthPropertiesPanel.this,
150                    tr(
151                            "<html>JOSM is about to reset the OAuth settings to default values.<br>"
152                            + "The current custom settings are not saved.</html>"
153                    ),
154                    tr("Overwrite custom OAuth settings?"),
155                    JOptionPane.WARNING_MESSAGE,
156                    null, /* no dedicated icon */
157                    buttons,
158                    buttons[0],
159                    HelpUtil.ht("/Dialog/OAuthAuthorisationWizard")
160            );
161    
162            return ret == 0; // OK button clicked
163        }
164    
165        protected void resetToDefaultSettings() {
166            cbUseDefaults.setSelected(true);
167            OAuthParameters params = OAuthParameters.createDefault(apiUrl);
168            tfConsumerKey.setText(params.getConsumerKey());
169            tfConsumerSecret.setText(params.getConsumerSecret());
170            tfRequestTokenURL.setText(params.getRequestTokenUrl());
171            tfAccessTokenURL.setText(params.getAccessTokenUrl());
172            tfAuthoriseURL.setText(params.getAuthoriseUrl());
173    
174            setChildComponentsEnabled(false);
175        }
176    
177        protected void setChildComponentsEnabled(boolean enabled){
178            for (Component c: getComponents()) {
179                if (c instanceof JTextField || c instanceof JLabel) {
180                    c.setEnabled(enabled);
181                }
182            }
183        }
184    
185        /**
186         * Replies the OAuth parameters currently edited in this properties panel.
187         *
188         * @return the OAuth parameters
189         */
190        public OAuthParameters getAdvancedParameters() {
191            if (cbUseDefaults.isSelected())
192                return OAuthParameters.createDefault(apiUrl);
193            OAuthParameters parameters = new OAuthParameters();
194            parameters.setConsumerKey(tfConsumerKey.getText());
195            parameters.setConsumerSecret(tfConsumerSecret.getText());
196            parameters.setRequestTokenUrl(tfRequestTokenURL.getText());
197            parameters.setAccessTokenUrl(tfAccessTokenURL.getText());
198            parameters.setAuthoriseUrl(tfAuthoriseURL.getText());
199            return parameters;
200        }
201    
202        /**
203         * Sets the advanced parameters to be displayed
204         *
205         * @param parameters the advanced parameters. Must not be null.
206         * @throws IllegalArgumentException thrown if parameters is null.
207         */
208        public void setAdvancedParameters(OAuthParameters parameters) throws IllegalArgumentException{
209            CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
210            if (parameters.equals(OAuthParameters.createDefault(apiUrl))) {
211                cbUseDefaults.setSelected(true);
212                setChildComponentsEnabled(false);
213            } else {
214                cbUseDefaults.setSelected(false);
215                setChildComponentsEnabled(true);
216                tfConsumerKey.setText( parameters.getConsumerKey() == null ? "" : parameters.getConsumerKey());
217                tfConsumerSecret.setText( parameters.getConsumerSecret() == null ? "" : parameters.getConsumerSecret());
218                tfRequestTokenURL.setText(parameters.getRequestTokenUrl() == null ? "" : parameters.getRequestTokenUrl());
219                tfAccessTokenURL.setText(parameters.getAccessTokenUrl() == null ? "" : parameters.getAccessTokenUrl());
220                tfAuthoriseURL.setText(parameters.getAuthoriseUrl() == null ? "" : parameters.getAuthoriseUrl());
221            }
222        }
223    
224        /**
225         * Constructs a new {@code AdvancedOAuthPropertiesPanel}.
226         */
227        public AdvancedOAuthPropertiesPanel() {
228            build();
229        }
230    
231        /**
232         * Initializes the panel from the values in the preferences <code>preferences</code>.
233         *
234         * @param pref the preferences. Must not be null.
235         * @throws IllegalArgumentException thrown if pref is null
236         */
237        public void initFromPreferences(Preferences pref) throws IllegalArgumentException {
238            CheckParameterUtil.ensureParameterNotNull(pref, "pref");
239            setApiUrl(pref.get("osm-server-url"));
240            boolean useDefault = pref.getBoolean("oauth.settings.use-default", true);
241            ilUseDefault.setEnabled(false);
242            if (useDefault) {
243                resetToDefaultSettings();
244            } else {
245                cbUseDefaults.setSelected(false);
246                tfConsumerKey.setText(pref.get("oauth.settings.consumer-key", ""));
247                tfConsumerSecret.setText(pref.get("oauth.settings.consumer-secret", ""));
248                tfRequestTokenURL.setText(pref.get("oauth.settings.request-token-url", ""));
249                tfAccessTokenURL.setText(pref.get("oauth.settings.access-token-url", ""));
250                tfAuthoriseURL.setText(pref.get("oauth.settings.authorise-url", ""));
251                setChildComponentsEnabled(true);
252            }
253            ilUseDefault.setEnabled(true);
254        }
255    
256        /**
257         * Remembers the current values in the preferences <code>pref</code>.
258         *
259         * @param pref the preferences. Must not be null.
260         * @throws IllegalArgumentException thrown if pref is null.
261         */
262        public void rememberPreferences(Preferences pref) throws IllegalArgumentException  {
263            CheckParameterUtil.ensureParameterNotNull(pref, "pref");
264            pref.put("oauth.settings.use-default", cbUseDefaults.isSelected());
265            if (cbUseDefaults.isSelected()) {
266                pref.put("oauth.settings.consumer-key", null);
267                pref.put("oauth.settings.consumer-secret", null);
268                pref.put("oauth.settings.request-token-url", null);
269                pref.put("oauth.settings.access-token-url", null);
270                pref.put("oauth.settings.authorise-url", null);
271            } else {
272                pref.put("oauth.settings.consumer-key", tfConsumerKey.getText().trim());
273                pref.put("oauth.settings.consumer-secret", tfConsumerSecret.getText().trim());
274                pref.put("oauth.settings.request-token-url", tfRequestTokenURL.getText().trim());
275                pref.put("oauth.settings.access-token-url", tfAccessTokenURL.getText().trim());
276                pref.put("oauth.settings.authorise-url", tfAuthoriseURL.getText().trim());
277            }
278        }
279    
280        class UseDefaultItemListener implements ItemListener {
281            private boolean enabled;
282    
283            public void itemStateChanged(ItemEvent e) {
284                if (!enabled) return;
285                switch (e.getStateChange()) {
286                case ItemEvent.SELECTED:
287                    if (hasCustomSettings()) {
288                        if (!confirmOverwriteCustomSettings()) {
289                            cbUseDefaults.setSelected(false);
290                            return;
291                        }
292                    }
293                    resetToDefaultSettings();
294                    break;
295                case ItemEvent.DESELECTED:
296                    setChildComponentsEnabled(true);
297                    break;
298                }
299            }
300    
301            public void setEnabled(boolean enabled) {
302                this.enabled = enabled;
303            }
304        }
305    
306        /**
307         * Sets the URL of the OSM API for which this panel is currently displaying OAuth properties.
308         *
309         * @param apiUrl the api URL
310         * @since 5422
311         */
312        public void setApiUrl(String apiUrl) {
313            this.apiUrl = apiUrl;
314            if (cbUseDefaults.isSelected()) {
315                resetToDefaultSettings();
316            }
317        }
318    }