source: josm/trunk/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java@ 10183

Last change on this file since 10183 was 10183, 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: 16.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.oauth;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Color;
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.ItemEvent;
15import java.awt.event.ItemListener;
16import java.util.concurrent.Executor;
17
18import javax.swing.AbstractAction;
19import javax.swing.BorderFactory;
20import javax.swing.JCheckBox;
21import javax.swing.JLabel;
22import javax.swing.JPanel;
23
24import org.openstreetmap.josm.data.oauth.OAuthToken;
25import org.openstreetmap.josm.gui.SideButton;
26import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
27import org.openstreetmap.josm.gui.util.GuiHelper;
28import org.openstreetmap.josm.gui.widgets.HtmlPanel;
29import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
30import org.openstreetmap.josm.gui.widgets.JosmTextField;
31import org.openstreetmap.josm.tools.ImageProvider;
32import org.openstreetmap.josm.tools.OpenBrowser;
33
34/**
35 * This is the UI for running a semic-automic authorisation procedure.
36 *
37 * In contrast to the fully-automatic procedure the user is dispatched to an
38 * external browser for login and authorisation.
39 *
40 * @since 2746
41 */
42public class SemiAutomaticAuthorizationUI extends AbstractAuthorizationUI {
43 private final AccessTokenInfoPanel pnlAccessTokenInfo = new AccessTokenInfoPanel();
44 private transient OAuthToken requestToken;
45
46 private RetrieveRequestTokenPanel pnlRetrieveRequestToken;
47 private RetrieveAccessTokenPanel pnlRetrieveAccessToken;
48 private ShowAccessTokenPanel pnlShowAccessToken;
49 private final transient Executor executor;
50
51 /**
52 * build the UI
53 */
54 protected final void build() {
55 setLayout(new BorderLayout());
56 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
57 pnlRetrieveRequestToken = new RetrieveRequestTokenPanel();
58 pnlRetrieveAccessToken = new RetrieveAccessTokenPanel();
59 pnlShowAccessToken = new ShowAccessTokenPanel();
60 add(pnlRetrieveRequestToken, BorderLayout.CENTER);
61 }
62
63 /**
64 * Constructs a new {@code SemiAutomaticAuthorizationUI} for the given API URL.
65 * @param apiUrl The OSM API URL
66 * @param executor the executor used for running the HTTP requests for the authorization
67 * @since 5422
68 */
69 public SemiAutomaticAuthorizationUI(String apiUrl, Executor executor) {
70 super(apiUrl);
71 this.executor = executor;
72 build();
73 }
74
75 @Override
76 public boolean isSaveAccessTokenToPreferences() {
77 return pnlAccessTokenInfo.isSaveToPreferences();
78 }
79
80 protected void transitionToRetrieveAccessToken() {
81 OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(
82 getAdvancedPropertiesPanel().getAdvancedParameters()
83 );
84 String authoriseUrl = client.getAuthoriseUrl(requestToken);
85 OpenBrowser.displayUrl(authoriseUrl);
86
87 removeAll();
88 pnlRetrieveAccessToken.setAuthoriseUrl(authoriseUrl);
89 add(pnlRetrieveAccessToken, BorderLayout.CENTER);
90 pnlRetrieveAccessToken.invalidate();
91 validate();
92 repaint();
93 }
94
95 protected void transitionToRetrieveRequestToken() {
96 requestToken = null;
97 setAccessToken(null);
98 removeAll();
99 add(pnlRetrieveRequestToken, BorderLayout.CENTER);
100 pnlRetrieveRequestToken.invalidate();
101 validate();
102 repaint();
103 }
104
105 protected void transitionToShowAccessToken() {
106 removeAll();
107 add(pnlShowAccessToken, BorderLayout.CENTER);
108 pnlShowAccessToken.invalidate();
109 validate();
110 repaint();
111 pnlShowAccessToken.setAccessToken(getAccessToken());
112 }
113
114 static class StepLabel extends JLabel {
115 StepLabel(String text) {
116 super(text);
117 setFont(getFont().deriveFont(16f));
118 }
119 }
120
121 /**
122 * This is the panel displayed in the first step of the semi-automatic authorisation process.
123 */
124 private class RetrieveRequestTokenPanel extends JPanel {
125
126 /**
127 * Constructs a new {@code RetrieveRequestTokenPanel}.
128 */
129 RetrieveRequestTokenPanel() {
130 build();
131 }
132
133 protected JPanel buildAdvancedParametersPanel() {
134 JPanel pnl = new JPanel(new GridBagLayout());
135 GridBagConstraints gc = new GridBagConstraints();
136
137 gc.anchor = GridBagConstraints.NORTHWEST;
138 gc.fill = GridBagConstraints.HORIZONTAL;
139 gc.weightx = 0.0;
140 gc.insets = new Insets(0, 0, 0, 3);
141 JCheckBox cbShowAdvancedParameters = new JCheckBox();
142 pnl.add(cbShowAdvancedParameters, gc);
143 cbShowAdvancedParameters.setSelected(false);
144 cbShowAdvancedParameters.addItemListener(
145 new ItemListener() {
146 @Override
147 public void itemStateChanged(ItemEvent evt) {
148 getAdvancedPropertiesPanel().setVisible(evt.getStateChange() == ItemEvent.SELECTED);
149 }
150 }
151 );
152
153 gc.gridx = 1;
154 gc.weightx = 1.0;
155 JMultilineLabel lbl = new JMultilineLabel(tr("Display Advanced OAuth Parameters"));
156 lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
157 pnl.add(lbl, gc);
158
159 gc.gridy = 1;
160 gc.gridx = 1;
161 gc.insets = new Insets(3, 0, 3, 0);
162 gc.fill = GridBagConstraints.BOTH;
163 gc.weightx = 1.0;
164 gc.weighty = 1.0;
165 pnl.add(getAdvancedPropertiesPanel(), gc);
166 getAdvancedPropertiesPanel().setBorder(
167 BorderFactory.createCompoundBorder(
168 BorderFactory.createLineBorder(Color.GRAY, 1),
169 BorderFactory.createEmptyBorder(3, 3, 3, 3)
170 )
171 );
172 getAdvancedPropertiesPanel().setVisible(false);
173 return pnl;
174 }
175
176 protected JPanel buildCommandPanel() {
177 JPanel pnl = new JPanel(new GridBagLayout());
178 GridBagConstraints gc = new GridBagConstraints();
179
180 gc.anchor = GridBagConstraints.NORTHWEST;
181 gc.fill = GridBagConstraints.BOTH;
182 gc.weightx = 1.0;
183 gc.weighty = 1.0;
184 gc.insets = new Insets(0, 0, 0, 3);
185
186
187 HtmlPanel h = new HtmlPanel();
188 h.setText(tr("<html>"
189 + "Please click on <strong>{0}</strong> to retrieve an OAuth Request Token from "
190 + "''{1}''.</html>",
191 tr("Retrieve Request Token"),
192 getAdvancedPropertiesPanel().getAdvancedParameters().getRequestTokenUrl()
193 ));
194 pnl.add(h, gc);
195
196 JPanel pnl1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
197 pnl1.add(new SideButton(new RetrieveRequestTokenAction()));
198 gc.fill = GridBagConstraints.HORIZONTAL;
199 gc.weightx = 1.0;
200 gc.gridy = 1;
201 pnl.add(pnl1, gc);
202 return pnl;
203
204 }
205
206 protected final void build() {
207 setLayout(new BorderLayout(0, 5));
208 add(new StepLabel(tr("<html>Step 1/3: Retrieve an OAuth Request Token</html>")), BorderLayout.NORTH);
209 add(buildAdvancedParametersPanel(), BorderLayout.CENTER);
210 add(buildCommandPanel(), BorderLayout.SOUTH);
211 }
212 }
213
214 /**
215 * This is the panel displayed in the second step of the semi-automatic authorization process.
216 */
217 private class RetrieveAccessTokenPanel extends JPanel {
218
219 private final JosmTextField tfAuthoriseUrl = new JosmTextField();
220
221 /**
222 * Constructs a new {@code RetrieveAccessTokenPanel}.
223 */
224 RetrieveAccessTokenPanel() {
225 build();
226 }
227
228 protected JPanel buildTitlePanel() {
229 JPanel pnl = new JPanel(new BorderLayout());
230 pnl.add(new StepLabel(tr("<html>Step 2/3: Authorize and retrieve an Access Token</html>")), BorderLayout.CENTER);
231 return pnl;
232 }
233
234 protected JPanel buildContentPanel() {
235 JPanel pnl = new JPanel(new GridBagLayout());
236 GridBagConstraints gc = new GridBagConstraints();
237
238 gc.anchor = GridBagConstraints.NORTHWEST;
239 gc.fill = GridBagConstraints.HORIZONTAL;
240 gc.weightx = 1.0;
241 gc.gridwidth = 2;
242 HtmlPanel html = new HtmlPanel();
243 html.setText(tr("<html>"
244 + "JOSM successfully retrieved a Request Token. "
245 + "JOSM is now launching an authorization page in an external browser. "
246 + "Please login with your OSM username and password and follow the instructions "
247 + "to authorize the Request Token. Then switch back to this dialog and click on "
248 + "<strong>{0}</strong><br><br>"
249 + "If launching the external browser fails you can copy the following authorize URL "
250 + "and paste it into the address field of your browser.</html>",
251 tr("Request Access Token")
252 ));
253 pnl.add(html, gc);
254
255 gc.gridx = 0;
256 gc.gridy = 1;
257 gc.weightx = 0.0;
258 gc.gridwidth = 1;
259 pnl.add(new JLabel(tr("Authorize URL:")), gc);
260
261 gc.gridx = 1;
262 gc.weightx = 1.0;
263 pnl.add(tfAuthoriseUrl, gc);
264 tfAuthoriseUrl.setEditable(false);
265
266 return pnl;
267 }
268
269 protected JPanel buildActionPanel() {
270 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
271 pnl.add(new SideButton(new BackAction()));
272 pnl.add(new SideButton(new RetrieveAccessTokenAction()));
273 return pnl;
274 }
275
276 protected final void build() {
277 setLayout(new BorderLayout());
278 add(buildTitlePanel(), BorderLayout.NORTH);
279 add(buildContentPanel(), BorderLayout.CENTER);
280 add(buildActionPanel(), BorderLayout.SOUTH);
281 }
282
283 public void setAuthoriseUrl(String url) {
284 tfAuthoriseUrl.setText(url);
285 }
286
287 /**
288 * Action to go back to step 1 in the process
289 */
290 class BackAction extends AbstractAction {
291 BackAction() {
292 putValue(NAME, tr("Back"));
293 putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
294 putValue(SMALL_ICON, ImageProvider.get("dialogs", "previous"));
295 }
296
297 @Override
298 public void actionPerformed(ActionEvent arg0) {
299 transitionToRetrieveRequestToken();
300 }
301 }
302 }
303
304 /**
305 * Displays the retrieved Access Token in step 3.
306 */
307 class ShowAccessTokenPanel extends JPanel {
308
309 /**
310 * Constructs a new {@code ShowAccessTokenPanel}.
311 */
312 ShowAccessTokenPanel() {
313 build();
314 }
315
316 protected JPanel buildTitlePanel() {
317 JPanel pnl = new JPanel(new BorderLayout());
318 pnl.add(new StepLabel(tr("<html>Step 3/3: Successfully retrieved an Access Token</html>")), BorderLayout.CENTER);
319 return pnl;
320 }
321
322 protected JPanel buildContentPanel() {
323 JPanel pnl = new JPanel(new GridBagLayout());
324 GridBagConstraints gc = new GridBagConstraints();
325
326 gc.anchor = GridBagConstraints.NORTHWEST;
327 gc.fill = GridBagConstraints.HORIZONTAL;
328 gc.weightx = 1.0;
329 HtmlPanel html = new HtmlPanel();
330 html.setText(tr("<html>"
331 + "JOSM has successfully retrieved an Access Token. "
332 + "You can now accept this token. JOSM will use it in the future for authentication "
333 + "and authorization to the OSM server.<br><br>"
334 + "The access token is: </html>"
335 ));
336 pnl.add(html, gc);
337
338 gc.gridx = 0;
339 gc.gridy = 1;
340 gc.weightx = 1.0;
341 gc.gridwidth = 1;
342 pnl.add(pnlAccessTokenInfo, gc);
343 pnlAccessTokenInfo.setSaveToPreferences(
344 OAuthAccessTokenHolder.getInstance().isSaveToPreferences()
345 );
346 return pnl;
347 }
348
349 protected JPanel buildActionPanel() {
350 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
351 pnl.add(new SideButton(new RestartAction()));
352 pnl.add(new SideButton(new TestAccessTokenAction()));
353 return pnl;
354 }
355
356 protected final void build() {
357 setLayout(new BorderLayout());
358 add(buildTitlePanel(), BorderLayout.NORTH);
359 add(buildContentPanel(), BorderLayout.CENTER);
360 add(buildActionPanel(), BorderLayout.SOUTH);
361 }
362
363 /**
364 * Action to go back to step 1 in the process
365 */
366 class RestartAction extends AbstractAction {
367 RestartAction() {
368 putValue(NAME, tr("Restart"));
369 putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
370 putValue(SMALL_ICON, ImageProvider.get("dialogs", "previous"));
371 }
372
373 @Override
374 public void actionPerformed(ActionEvent arg0) {
375 transitionToRetrieveRequestToken();
376 }
377 }
378
379 public void setAccessToken(OAuthToken accessToken) {
380 pnlAccessTokenInfo.setAccessToken(accessToken);
381 }
382 }
383
384 /**
385 * Action for retrieving a request token
386 */
387 class RetrieveRequestTokenAction extends AbstractAction {
388
389 RetrieveRequestTokenAction() {
390 putValue(NAME, tr("Retrieve Request Token"));
391 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth-small"));
392 putValue(SHORT_DESCRIPTION, tr("Click to retrieve a Request Token"));
393 }
394
395 @Override
396 public void actionPerformed(ActionEvent evt) {
397 final RetrieveRequestTokenTask task = new RetrieveRequestTokenTask(
398 SemiAutomaticAuthorizationUI.this,
399 getAdvancedPropertiesPanel().getAdvancedParameters()
400 );
401 executor.execute(task);
402 Runnable r = new Runnable() {
403 @Override
404 public void run() {
405 if (task.isCanceled()) return;
406 if (task.getRequestToken() == null) return;
407 requestToken = task.getRequestToken();
408 GuiHelper.runInEDT(new Runnable() {
409 @Override
410 public void run() {
411 transitionToRetrieveAccessToken();
412 }
413 });
414 }
415 };
416 executor.execute(r);
417 }
418 }
419
420 /**
421 * Action for retrieving an Access Token
422 */
423 class RetrieveAccessTokenAction extends AbstractAction {
424
425 RetrieveAccessTokenAction() {
426 putValue(NAME, tr("Retrieve Access Token"));
427 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth-small"));
428 putValue(SHORT_DESCRIPTION, tr("Click to retrieve an Access Token"));
429 }
430
431 @Override
432 public void actionPerformed(ActionEvent evt) {
433 final RetrieveAccessTokenTask task = new RetrieveAccessTokenTask(
434 SemiAutomaticAuthorizationUI.this,
435 getAdvancedPropertiesPanel().getAdvancedParameters(),
436 requestToken
437 );
438 executor.execute(task);
439 Runnable r = new Runnable() {
440 @Override
441 public void run() {
442 if (task.isCanceled()) return;
443 if (task.getAccessToken() == null) return;
444 GuiHelper.runInEDT(new Runnable() {
445 @Override
446 public void run() {
447 setAccessToken(task.getAccessToken());
448 transitionToShowAccessToken();
449 }
450 });
451 }
452 };
453 executor.execute(r);
454 }
455 }
456
457 /**
458 * Action for testing an Access Token
459 */
460 class TestAccessTokenAction extends AbstractAction {
461
462 TestAccessTokenAction() {
463 putValue(NAME, tr("Test Access Token"));
464 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth-small"));
465 putValue(SHORT_DESCRIPTION, tr("Click to test the Access Token"));
466 }
467
468 @Override
469 public void actionPerformed(ActionEvent evt) {
470 TestAccessTokenTask task = new TestAccessTokenTask(
471 SemiAutomaticAuthorizationUI.this,
472 getApiUrl(),
473 getAdvancedPropertiesPanel().getAdvancedParameters(),
474 getAccessToken()
475 );
476 executor.execute(task);
477 }
478 }
479}
Note: See TracBrowser for help on using the repository browser.