source: josm/trunk/src/org/openstreetmap/josm/io/OsmConnection.java@ 12279

Last change on this file since 12279 was 11544, checked in by Don-vip, 7 years ago

sonar - squid:S1854 - Dead stores should be removed

  • Property svn:eol-style set to native
File size: 6.6 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[626]2package org.openstreetmap.josm.io;
3
[2748]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[9352]6import java.lang.reflect.InvocationTargetException;
[6248]7import java.net.Authenticator.RequestorType;
[9352]8import java.net.MalformedURLException;
9import java.net.URL;
[7082]10import java.nio.charset.StandardCharsets;
[10618]11import java.util.Base64;
[9352]12import java.util.Objects;
13import java.util.concurrent.FutureTask;
[626]14
[10237]15import javax.swing.SwingUtilities;
16
[2748]17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.data.oauth.OAuthParameters;
[9352]19import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
[2748]20import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
[4245]21import org.openstreetmap.josm.io.auth.CredentialsAgentException;
[6248]22import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
[4245]23import org.openstreetmap.josm.io.auth.CredentialsManager;
[9172]24import org.openstreetmap.josm.tools.HttpClient;
[10237]25import org.openstreetmap.josm.tools.Utils;
[626]26
[8840]27import oauth.signpost.OAuthConsumer;
28import oauth.signpost.exception.OAuthException;
29
[626]30/**
31 * Base class that handles common things like authentication for the reader and writer
32 * to the osm server.
33 *
34 * @author imi
35 */
36public class OsmConnection {
[8840]37 protected boolean cancel;
[9309]38 protected HttpClient activeConnection;
[2748]39 protected OAuthParameters oauthParameters;
[626]40
[1169]41 /**
[6643]42 * Cancels the connection.
43 */
[1169]44 public void cancel() {
45 cancel = true;
[2322]46 synchronized (this) {
47 if (activeConnection != null) {
48 activeConnection.disconnect();
49 }
50 }
[1169]51 }
[626]52
[2748]53 /**
54 * Adds an authentication header for basic authentication
[2801]55 *
[2748]56 * @param con the connection
[8291]57 * @throws OsmTransferException if something went wrong. Check for nested exceptions
[2748]58 */
[9172]59 protected void addBasicAuthorizationHeader(HttpClient con) throws OsmTransferException {
[4245]60 CredentialsAgentResponse response;
[1955]61 try {
[4245]62 synchronized (CredentialsManager.getInstance()) {
[4690]63 response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
64 con.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
[1955]65 }
[4245]66 } catch (CredentialsAgentException e) {
[2641]67 throw new OsmTransferException(e);
[1955]68 }
[11544]69 if (response != null) {
70 if (response.isCanceled()) {
71 cancel = true;
72 return;
73 } else {
74 String username = response.getUsername() == null ? "" : response.getUsername();
75 String password = response.getPassword() == null ? "" : String.valueOf(response.getPassword());
76 String token = username + ':' + password;
77 con.setHeader("Authorization", "Basic "+Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8)));
78 }
[2641]79 }
[1169]80 }
[1881]81
82 /**
[2748]83 * Signs the connection with an OAuth authentication header
[2801]84 *
[2748]85 * @param connection the connection
[2801]86 *
[8291]87 * @throws OsmTransferException if there is currently no OAuth Access Token configured
88 * @throws OsmTransferException if signing fails
[2748]89 */
[9172]90 protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
[2748]91 if (oauthParameters == null) {
92 oauthParameters = OAuthParameters.createFromPreferences(Main.pref);
93 }
94 OAuthConsumer consumer = oauthParameters.buildConsumer();
95 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
[9352]96 if (!holder.containsAccessToken()) {
97 obtainAccessToken(connection);
98 }
99 if (!holder.containsAccessToken()) { // check if wizard completed
[2862]100 throw new MissingOAuthAccessTokenException();
[9352]101 }
[2748]102 consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());
103 try {
104 consumer.sign(connection);
[8510]105 } catch (OAuthException e) {
[2748]106 throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);
107 }
108 }
109
[9352]110 /**
111 * Obtains an OAuth access token for the connection. Afterwards, the token is accessible via {@link OAuthAccessTokenHolder}.
112 * @param connection connection for which the access token should be obtained
113 * @throws MissingOAuthAccessTokenException if the process cannot be completec successfully
114 */
115 protected void obtainAccessToken(final HttpClient connection) throws MissingOAuthAccessTokenException {
116 try {
[9353]117 final URL apiUrl = new URL(OsmApi.getOsmApi().getServerUrl());
[9352]118 if (!Objects.equals(apiUrl.getHost(), connection.getURL().getHost())) {
119 throw new MissingOAuthAccessTokenException();
120 }
[10615]121 final Runnable authTask = new FutureTask<>(() -> {
122 // Concerning Utils.newDirectExecutor: Main.worker cannot be used since this connection is already
123 // executed via Main.worker. The OAuth connections would block otherwise.
124 final OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
125 Main.parent, apiUrl.toExternalForm(), Utils.newDirectExecutor());
126 wizard.showDialog();
127 OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true);
128 OAuthAccessTokenHolder.getInstance().save(Main.pref, CredentialsManager.getInstance());
129 return wizard;
[9352]130 });
131 // exception handling differs from implementation at GuiHelper.runInEDTAndWait()
132 if (SwingUtilities.isEventDispatchThread()) {
133 authTask.run();
134 } else {
135 SwingUtilities.invokeAndWait(authTask);
136 }
137 } catch (MalformedURLException | InterruptedException | InvocationTargetException e) {
[10237]138 throw new MissingOAuthAccessTokenException(e);
[9352]139 }
140 }
141
[9172]142 protected void addAuth(HttpClient connection) throws OsmTransferException {
[9352]143 final String authMethod = OsmApi.getAuthMethod();
[7012]144 if ("basic".equals(authMethod)) {
[2748]145 addBasicAuthorizationHeader(connection);
[7012]146 } else if ("oauth".equals(authMethod)) {
[2748]147 addOAuthAuthorizationHeader(connection);
148 } else {
[6248]149 String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
150 Main.warn(msg);
[2748]151 throw new OsmTransferException(msg);
152 }
153 }
154
155 /**
[1881]156 * Replies true if this connection is canceled
[2512]157 *
[1881]158 * @return true if this connection is canceled
159 */
160 public boolean isCanceled() {
161 return cancel;
162 }
[626]163}
Note: See TracBrowser for help on using the repository browser.