Ticket #22810: 22810.2.patch

File 22810.2.patch, 251.3 KB (added by taylor.smock, 2 years ago)

Drop support for Basic Auth and OAuth 1.0a

  • core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java

    Subject: [PATCH] See #22810: Drop deprecated authentication methods
    ---
    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java b/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java
    a b  
    147147        if (this.tokenUrl != null) builder.add(TOKEN_URL, this.tokenUrl);
    148148        return builder.build().toString();
    149149    }
     150
     151    @Override
     152    public int hashCode() {
     153        return Objects.hash(this.apiUrl, this.authorizeUrl, this.tokenUrl, this.clientId, this.clientSecret, this.redirectUri);
     154    }
     155
     156    @Override
     157    public boolean equals(Object obj) {
     158        if (obj != null && this.getClass() == obj.getClass()) {
     159            OAuth20Parameters other = (OAuth20Parameters) obj;
     160            return Objects.equals(this.clientSecret, other.clientSecret) &&
     161                    Objects.equals(this.clientId, other.clientId) &&
     162                    Objects.equals(this.redirectUri, other.redirectUri) &&
     163                    Objects.equals(this.tokenUrl, other.tokenUrl) &&
     164                    Objects.equals(this.authorizeUrl, other.authorizeUrl) &&
     165                    Objects.equals(this.apiUrl, other.apiUrl);
     166        }
     167        return false;
     168    }
    150169}
  • core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
    a b  
    3636    }
    3737
    3838    private boolean saveToPreferences;
    39     private String accessTokenKey;
    40     private String accessTokenSecret;
    4139
    4240    private final Map<String, Map<OAuthVersion, IOAuthToken>> tokenMap = new HashMap<>();
    4341
     
    5250
    5351    /**
    5452     * Sets whether the current access token should be saved to the preferences file.
    55      *
     53     * <p>
    5654     * If true, the access token is saved in clear text to the preferences file. The same
    5755     * access token can therefore be used in multiple JOSM sessions.
    58      *
     56     * <p>
    5957     * If false, the access token isn't saved to the preferences file. If JOSM is closed,
    6058     * the access token is lost and new token has to be generated by the OSM server the
    6159     * next time JOSM is used.
     
    6664        this.saveToPreferences = saveToPreferences;
    6765    }
    6866
    69     /**
    70      * Replies the access token key. null, if no access token key is currently set.
    71      *
    72      * @return the access token key
    73      */
    74     public String getAccessTokenKey() {
    75         return accessTokenKey;
    76     }
    77 
    78     /**
    79      * Sets the access token key. Pass in null to remove the current access token key.
    80      *
    81      * @param accessTokenKey the access token key
    82      */
    83     public void setAccessTokenKey(String accessTokenKey) {
    84         this.accessTokenKey = accessTokenKey;
    85     }
    86 
    87     /**
    88      * Replies the access token secret. null, if no access token secret is currently set.
    89      *
    90      * @return the access token secret
    91      */
    92     public String getAccessTokenSecret() {
    93         return accessTokenSecret;
    94     }
    95 
    96     /**
    97      * Sets the access token secret. Pass in null to remove the current access token secret.
    98      *
    99      * @param accessTokenSecret access token secret, or null
    100      */
    101     public void setAccessTokenSecret(String accessTokenSecret) {
    102         this.accessTokenSecret = accessTokenSecret;
    103     }
    104 
    105     /**
    106      * Replies the access token.
    107      * @return the access token, can be {@code null}
    108      */
    109     public OAuthToken getAccessToken() {
    110         if (!containsAccessToken())
    111             return null;
    112         return new OAuthToken(accessTokenKey, accessTokenSecret);
    113     }
    114 
    11567    /**
    11668     * Replies the access token.
    11769     * @param api The api the token is for
     
    13991        return null;
    14092    }
    14193
    142     /**
    143      * Sets the access token hold by this holder.
    144      *
    145      * @param accessTokenKey the access token key
    146      * @param accessTokenSecret the access token secret
    147      */
    148     public void setAccessToken(String accessTokenKey, String accessTokenSecret) {
    149         this.accessTokenKey = accessTokenKey;
    150         this.accessTokenSecret = accessTokenSecret;
    151     }
    152 
    153     /**
    154      * Sets the access token hold by this holder.
    155      *
    156      * @param token the access token. Can be null to clear the content in this holder.
    157      */
    158     public void setAccessToken(OAuthToken token) {
    159         if (token == null) {
    160             this.accessTokenKey = null;
    161             this.accessTokenSecret = null;
    162         } else {
    163             this.accessTokenKey = token.getKey();
    164             this.accessTokenSecret = token.getSecret();
    165         }
    166     }
    167 
    16894    /**
    16995     * Sets the access token hold by this holder.
    17096     *
     
    185111        }
    186112    }
    187113
    188     /**
    189      * Replies true if this holder contains an complete access token, consisting of an
    190      * Access Token Key and an Access Token Secret.
    191      *
    192      * @return true if this holder contains an complete access token
    193      */
    194     public boolean containsAccessToken() {
    195         return accessTokenKey != null && accessTokenSecret != null;
    196     }
    197 
    198114    /**
    199115     * Initializes the content of this holder from the Access Token managed by the
    200116     * credential manager.
     
    204120     */
    205121    public void init(CredentialsAgent cm) {
    206122        CheckParameterUtil.ensureParameterNotNull(cm, "cm");
    207         OAuthToken token = null;
    208         try {
    209             token = cm.lookupOAuthAccessToken();
    210         } catch (CredentialsAgentException e) {
    211             Logging.error(e);
    212             Logging.warn(tr("Failed to retrieve OAuth Access Token from credential manager"));
    213             Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    214         }
    215123        saveToPreferences = Config.getPref().getBoolean("oauth.access-token.save-to-preferences", true);
    216         if (token != null) {
    217             accessTokenKey = token.getKey();
    218             accessTokenSecret = token.getSecret();
    219         }
    220124    }
    221125
    222126    /**
     
    231135        Config.getPref().putBoolean("oauth.access-token.save-to-preferences", saveToPreferences);
    232136        try {
    233137            if (!saveToPreferences) {
    234                 cm.storeOAuthAccessToken(null);
    235138                for (String host : this.tokenMap.keySet()) {
    236139                    cm.storeOAuthAccessToken(host, null);
    237140                }
    238141            } else {
    239                 if (this.accessTokenKey != null && this.accessTokenSecret != null) {
    240                     cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret));
    241                 } else {
    242                     cm.storeOAuthAccessToken(null);
    243                 }
    244142                for (Map.Entry<String, Map<OAuthVersion, IOAuthToken>> entry : this.tokenMap.entrySet()) {
    245143                    if (entry.getValue().isEmpty()) {
    246144                        cm.storeOAuthAccessToken(entry.getKey(), null);
     
    264162     * Clears the content of this holder
    265163     */
    266164    public void clear() {
    267         accessTokenKey = null;
    268         accessTokenSecret = null;
     165        this.tokenMap.clear();
    269166    }
    270167}
  • core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
    a b  
    33
    44import java.io.BufferedReader;
    55import java.io.IOException;
    6 import java.net.URL;
    7 import java.util.Objects;
     6import java.net.URI;
     7import java.net.URISyntaxException;
     8import java.util.Arrays;
    89
    910import jakarta.json.Json;
    1011import jakarta.json.JsonObject;
     
    1718import org.openstreetmap.josm.io.auth.CredentialsManager;
    1819import org.openstreetmap.josm.spi.preferences.Config;
    1920import org.openstreetmap.josm.spi.preferences.IUrls;
    20 import org.openstreetmap.josm.tools.CheckParameterUtil;
    2121import org.openstreetmap.josm.tools.HttpClient;
    2222import org.openstreetmap.josm.tools.Logging;
    2323import org.openstreetmap.josm.tools.Utils;
    2424
    25 import oauth.signpost.OAuthConsumer;
    26 import oauth.signpost.OAuthProvider;
    27 
    2825/**
    2926 * This class manages an immutable set of OAuth parameters.
    30  * @since 2747
     27 * @since 2747 (static factory class since xxx)
    3128 */
    32 public class OAuthParameters implements IOAuthParameters {
     29public final class OAuthParameters {
     30    private static final String OSM_API_DEFAULT = "https://api.openstreetmap.org/api";
     31    private static final String OSM_API_DEV = "https://api06.dev.openstreetmap.org/api";
     32    private static final String OSM_API_MASTER = "https://master.apis.dev.openstreetmap.org/api";
    3333
    34     /**
    35      * The default JOSM OAuth consumer key (created by user josmeditor).
    36      */
    37     public static final String DEFAULT_JOSM_CONSUMER_KEY = "F7zPYlVCqE2BUH9Hr4SsWZSOnrKjpug1EgqkbsSb";
    38     /**
    39      * The default JOSM OAuth consumer secret (created by user josmeditor).
    40      */
    41     public static final String DEFAULT_JOSM_CONSUMER_SECRET = "rIkjpPcBNkMQxrqzcOvOC4RRuYupYr7k8mfP13H5";
     34    private OAuthParameters() {
     35        // Hide constructor
     36    }
    4237
    4338    /**
    4439     * Replies a set of default parameters for a consumer accessing the standard OSM server
     
    4641     *
    4742     * @return a set of default parameters
    4843     */
    49     public static OAuthParameters createDefault() {
    50         return createDefault(null);
    51     }
    52 
    53     /**
    54      * Replies a set of default parameters for a consumer accessing an OSM server
    55      * at the given API url. URL parameters are only set if the URL equals {@link IUrls#getDefaultOsmApiUrl}
    56      * or references the domain "dev.openstreetmap.org", otherwise they may be <code>null</code>.
    57      *
    58      * @param apiUrl The API URL for which the OAuth default parameters are created. If null or empty, the default OSM API url is used.
    59      * @return a set of default parameters for the given {@code apiUrl}
    60      * @since 5422
    61      */
    62     public static OAuthParameters createDefault(String apiUrl) {
    63         return (OAuthParameters) createDefault(apiUrl, OAuthVersion.OAuth10a);
     44    public static IOAuthParameters createDefault() {
     45        return createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20);
    6446    }
    6547
    6648    /**
     
    7961        }
    8062
    8163        switch (oAuthVersion) {
    82             case OAuth10a:
    83                 return getDefaultOAuth10Parameters(apiUrl);
    8464            case OAuth20:
    8565            case OAuth21: // For now, OAuth 2.1 (draft) is just OAuth 2.0 with mandatory extensions, which we implement.
    8666                return getDefaultOAuth20Parameters(apiUrl);
     
    9777    private static OAuth20Parameters getDefaultOAuth20Parameters(String apiUrl) {
    9878        final String clientId;
    9979        final String clientSecret;
    100         final String redirectUri;
     80        final String redirectUri = "http://127.0.0.1:8111/oauth_authorization";
    10181        final String baseUrl;
    102         if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl) && !"http://invalid".equals(apiUrl)) {
     82        apiUrl = apiUrl == null ? OsmApi.getOsmApi().getServerUrl() : apiUrl;
     83        if (!OsmApi.getOsmApi().getServerUrl().equals(apiUrl)
     84                && !Arrays.asList(OSM_API_DEFAULT, OSM_API_DEV, OSM_API_MASTER).contains(apiUrl)
     85                && !"http://invalid".equals(apiUrl)) {
    10386            clientId = "";
    10487            clientSecret = "";
    10588            baseUrl = apiUrl;
    10689            HttpClient client = null;
    107             redirectUri = "";
    10890            // Check if the server is RFC 8414 compliant
    10991            try {
    110                 client = HttpClient.create(new URL(apiUrl + (apiUrl.endsWith("/") ? "" : "/") + ".well-known/oauth-authorization-server"));
     92                client = HttpClient.create(new URI(apiUrl + (apiUrl.endsWith("/") ? "" : "/")
     93                        + ".well-known/oauth-authorization-server").toURL());
    11194                HttpClient.Response response = client.connect();
    11295                if (response.getResponseCode() == 200) {
    11396                    try (BufferedReader reader = response.getContentReader();
     
    119102                        }
    120103                    }
    121104                }
    122             } catch (IOException | OAuthException e) {
     105            } catch (URISyntaxException | IOException | OAuthException e) {
    123106                Logging.trace(e);
    124107            } finally {
    125108                if (client != null) client.disconnect();
    126109            }
    127110        } else {
    128             clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI";
    129             // We don't actually use the client secret in our authorization flow.
    130             clientSecret = null;
    131             baseUrl = "https://www.openstreetmap.org/oauth2";
    132             redirectUri = "http://127.0.0.1:8111/oauth_authorization";
     111            switch (apiUrl) {
     112                case OSM_API_DEV:
     113                case OSM_API_MASTER:
     114                    // This clientId/clientSecret are provided by taylor.smock. Feel free to change if needed, but
     115                    // do let one of the maintainers with server access know so that they can update the test OAuth
     116                    // token.
     117                    clientId = "-QZt6n1btDfqrfJNGUIMZjzcyqTgIV6sy79_W4kmQLM";
     118                    // Keep secret for dev apis, just in case we want to test something that needs it.
     119                    clientSecret = "SWnmRD4AdLO-2-ttHE5TR3eLF2McNf7dh0_Z2WNzJdI";
     120                    break;
     121                case OSM_API_DEFAULT:
     122                    clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI";
     123                    // We don't actually use the client secret in our authorization flow.
     124                    clientSecret = null;
     125                    break;
     126                default:
     127                    clientId = "";
     128                    clientSecret = null;
     129            }
     130            baseUrl = "https://" + OsmApi.getOsmApi().getHost() + "/oauth2";
    133131            apiUrl = OsmApi.getOsmApi().getBaseUrl();
    134132        }
    135133        return new OAuth20Parameters(clientId, clientSecret, baseUrl, apiUrl, redirectUri);
     
    153151        return new OAuth20Parameters(clientId, clientSecret, tokenEndpoint, authorizationEndpoint, apiUrl, redirectUri);
    154152    }
    155153
    156     /**
    157      * Get the default OAuth 1.0a parameters
    158      * @param apiUrl The api url
    159      * @return The default parameters
    160      */
    161     private static OAuthParameters getDefaultOAuth10Parameters(String apiUrl) {
    162         final String consumerKey;
    163         final String consumerSecret;
    164         final String serverUrl;
    165 
    166         if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) {
    167             consumerKey = ""; // a custom consumer key is required
    168             consumerSecret = ""; // a custom consumer secret is requireds
    169             serverUrl = apiUrl.replaceAll("/api$", "");
    170         } else {
    171             consumerKey = DEFAULT_JOSM_CONSUMER_KEY;
    172             consumerSecret = DEFAULT_JOSM_CONSUMER_SECRET;
    173             serverUrl = Config.getUrls().getOSMWebsite();
    174         }
    175 
    176         return new OAuthParameters(
    177                 consumerKey,
    178                 consumerSecret,
    179                 serverUrl + "/oauth/request_token",
    180                 serverUrl + "/oauth/access_token",
    181                 serverUrl + "/oauth/authorize",
    182                 serverUrl + "/login",
    183                 serverUrl + "/logout");
    184     }
    185 
    186     /**
    187      * Replies a set of parameters as defined in the preferences.
    188      *
    189      * @param apiUrl the API URL. Must not be null.
    190      * @return the parameters
    191      */
    192     public static OAuthParameters createFromApiUrl(String apiUrl) {
    193         return (OAuthParameters) createFromApiUrl(apiUrl, OAuthVersion.OAuth10a);
    194     }
    195 
    196154    /**
    197155     * Replies a set of parameters as defined in the preferences.
    198156     *
     
    204162    public static IOAuthParameters createFromApiUrl(String apiUrl, OAuthVersion oAuthVersion) {
    205163        IOAuthParameters parameters = createDefault(apiUrl, oAuthVersion);
    206164        switch (oAuthVersion) {
    207             case OAuth10a:
    208                 OAuthParameters oauth10aParameters = (OAuthParameters) parameters;
    209                 return new OAuthParameters(
    210                     Config.getPref().get("oauth.settings.consumer-key", oauth10aParameters.getConsumerKey()),
    211                     Config.getPref().get("oauth.settings.consumer-secret", oauth10aParameters.getConsumerSecret()),
    212                     Config.getPref().get("oauth.settings.request-token-url", oauth10aParameters.getRequestTokenUrl()),
    213                     Config.getPref().get("oauth.settings.access-token-url", oauth10aParameters.getAccessTokenUrl()),
    214                     Config.getPref().get("oauth.settings.authorise-url", oauth10aParameters.getAuthoriseUrl()),
    215                     Config.getPref().get("oauth.settings.osm-login-url", oauth10aParameters.getOsmLoginUrl()),
    216                     Config.getPref().get("oauth.settings.osm-logout-url", oauth10aParameters.getOsmLogoutUrl()));
    217165            case OAuth20:
    218166            case OAuth21: // Right now, OAuth 2.1 will work with our OAuth 2.0 implementation
    219167                OAuth20Parameters oAuth20Parameters = (OAuth20Parameters) parameters;
     
    228176                throw new IllegalArgumentException("Unknown OAuth version: " + oAuthVersion);
    229177        }
    230178    }
    231 
    232     /**
    233      * Remembers the current values in the preferences.
    234      */
    235     @Override
    236     public void rememberPreferences() {
    237         Config.getPref().put("oauth.settings.consumer-key", getConsumerKey());
    238         Config.getPref().put("oauth.settings.consumer-secret", getConsumerSecret());
    239         Config.getPref().put("oauth.settings.request-token-url", getRequestTokenUrl());
    240         Config.getPref().put("oauth.settings.access-token-url", getAccessTokenUrl());
    241         Config.getPref().put("oauth.settings.authorise-url", getAuthoriseUrl());
    242         Config.getPref().put("oauth.settings.osm-login-url", getOsmLoginUrl());
    243         Config.getPref().put("oauth.settings.osm-logout-url", getOsmLogoutUrl());
    244     }
    245 
    246     private final String consumerKey;
    247     private final String consumerSecret;
    248     private final String requestTokenUrl;
    249     private final String accessTokenUrl;
    250     private final String authoriseUrl;
    251     private final String osmLoginUrl;
    252     private final String osmLogoutUrl;
    253 
    254     /**
    255      * Constructs a new {@code OAuthParameters}.
    256      * @param consumerKey consumer key
    257      * @param consumerSecret consumer secret
    258      * @param requestTokenUrl request token URL
    259      * @param accessTokenUrl access token URL
    260      * @param authoriseUrl authorise URL
    261      * @param osmLoginUrl the OSM login URL (for automatic mode)
    262      * @param osmLogoutUrl the OSM logout URL (for automatic mode)
    263      * @see #createDefault
    264      * @see #createFromApiUrl
    265      * @since 9220
    266      */
    267     public OAuthParameters(String consumerKey, String consumerSecret,
    268                            String requestTokenUrl, String accessTokenUrl, String authoriseUrl, String osmLoginUrl, String osmLogoutUrl) {
    269         this.consumerKey = consumerKey;
    270         this.consumerSecret = consumerSecret;
    271         this.requestTokenUrl = requestTokenUrl;
    272         this.accessTokenUrl = accessTokenUrl;
    273         this.authoriseUrl = authoriseUrl;
    274         this.osmLoginUrl = osmLoginUrl;
    275         this.osmLogoutUrl = osmLogoutUrl;
    276     }
    277 
    278     /**
    279      * Creates a clone of the parameters in <code>other</code>.
    280      *
    281      * @param other the other parameters. Must not be null.
    282      * @throws IllegalArgumentException if other is null
    283      */
    284     public OAuthParameters(OAuthParameters other) {
    285         CheckParameterUtil.ensureParameterNotNull(other, "other");
    286         this.consumerKey = other.consumerKey;
    287         this.consumerSecret = other.consumerSecret;
    288         this.accessTokenUrl = other.accessTokenUrl;
    289         this.requestTokenUrl = other.requestTokenUrl;
    290         this.authoriseUrl = other.authoriseUrl;
    291         this.osmLoginUrl = other.osmLoginUrl;
    292         this.osmLogoutUrl = other.osmLogoutUrl;
    293     }
    294 
    295     /**
    296      * Gets the consumer key.
    297      * @return The consumer key
    298      */
    299     public String getConsumerKey() {
    300         return consumerKey;
    301     }
    302 
    303     /**
    304      * Gets the consumer secret.
    305      * @return The consumer secret
    306      */
    307     public String getConsumerSecret() {
    308         return consumerSecret;
    309     }
    310 
    311     /**
    312      * Gets the request token URL.
    313      * @return The request token URL
    314      */
    315     public String getRequestTokenUrl() {
    316         return requestTokenUrl;
    317     }
    318 
    319     /**
    320      * Gets the access token URL.
    321      * @return The access token URL
    322      */
    323     @Override
    324     public String getAccessTokenUrl() {
    325         return accessTokenUrl;
    326     }
    327 
    328     @Override
    329     public String getAuthorizationUrl() {
    330         return this.authoriseUrl;
    331     }
    332 
    333     @Override
    334     public OAuthVersion getOAuthVersion() {
    335         return OAuthVersion.OAuth10a;
    336     }
    337 
    338     @Override
    339     public String getClientId() {
    340         return this.consumerKey;
    341     }
    342 
    343     @Override
    344     public String getClientSecret() {
    345         return this.consumerSecret;
    346     }
    347 
    348     /**
    349      * Gets the authorise URL.
    350      * @return The authorise URL
    351      */
    352     public String getAuthoriseUrl() {
    353         return this.getAuthorizationUrl();
    354     }
    355 
    356     /**
    357      * Gets the URL used to login users on the website (for automatic mode).
    358      * @return The URL used to login users
    359      */
    360     public String getOsmLoginUrl() {
    361         return osmLoginUrl;
    362     }
    363 
    364     /**
    365      * Gets the URL used to logout users on the website (for automatic mode).
    366      * @return The URL used to logout users
    367      */
    368     public String getOsmLogoutUrl() {
    369         return osmLogoutUrl;
    370     }
    371 
    372     /**
    373      * Builds an {@link OAuthConsumer} based on these parameters.
    374      *
    375      * @return the consumer
    376      */
    377     public OAuthConsumer buildConsumer() {
    378         return new SignpostAdapters.OAuthConsumer(consumerKey, consumerSecret);
    379     }
    380 
    381     /**
    382      * Builds an {@link OAuthProvider} based on these parameters and a OAuth consumer <code>consumer</code>.
    383      *
    384      * @param consumer the consumer. Must not be null.
    385      * @return the provider
    386      * @throws IllegalArgumentException if consumer is null
    387      */
    388     public OAuthProvider buildProvider(OAuthConsumer consumer) {
    389         CheckParameterUtil.ensureParameterNotNull(consumer, "consumer");
    390         return new SignpostAdapters.OAuthProvider(
    391                 requestTokenUrl,
    392                 accessTokenUrl,
    393                 authoriseUrl
    394         );
    395     }
    396 
    397     @Override
    398     public boolean equals(Object o) {
    399         if (this == o) return true;
    400         if (o == null || getClass() != o.getClass()) return false;
    401         OAuthParameters that = (OAuthParameters) o;
    402         return Objects.equals(consumerKey, that.consumerKey) &&
    403                 Objects.equals(consumerSecret, that.consumerSecret) &&
    404                 Objects.equals(requestTokenUrl, that.requestTokenUrl) &&
    405                 Objects.equals(accessTokenUrl, that.accessTokenUrl) &&
    406                 Objects.equals(authoriseUrl, that.authoriseUrl) &&
    407                 Objects.equals(osmLoginUrl, that.osmLoginUrl) &&
    408                 Objects.equals(osmLogoutUrl, that.osmLogoutUrl);
    409     }
    410 
    411     @Override
    412     public int hashCode() {
    413         return Objects.hash(consumerKey, consumerSecret, requestTokenUrl, accessTokenUrl, authoriseUrl, osmLoginUrl, osmLogoutUrl);
    414     }
    415179}
  • deleted file core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java

    diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.data.oauth;
    3 
    4 import java.util.Objects;
    5 
    6 import org.openstreetmap.josm.tools.CheckParameterUtil;
    7 
    8 import oauth.signpost.OAuthConsumer;
    9 
    10 /**
    11  * An oauth token that has been obtained by JOSM and can be used to authenticate the user on the server.
    12  */
    13 public class OAuthToken {
    14 
    15     /**
    16      * Creates an OAuthToken from the token currently managed by the {@link OAuthConsumer}.
    17      *
    18      * @param consumer the consumer
    19      * @return the token
    20      */
    21     public static OAuthToken createToken(OAuthConsumer consumer) {
    22         return new OAuthToken(consumer.getToken(), consumer.getTokenSecret());
    23     }
    24 
    25     private final String key;
    26     private final String secret;
    27 
    28     /**
    29      * Creates a new token
    30      *
    31      * @param key the token key
    32      * @param secret the token secret
    33      */
    34     public OAuthToken(String key, String secret) {
    35         this.key = key;
    36         this.secret = secret;
    37     }
    38 
    39     /**
    40      * Creates a clone of another token
    41      *
    42      * @param other the other token. Must not be null.
    43      * @throws IllegalArgumentException if other is null
    44      */
    45     public OAuthToken(OAuthToken other) {
    46         CheckParameterUtil.ensureParameterNotNull(other, "other");
    47         this.key = other.key;
    48         this.secret = other.secret;
    49     }
    50 
    51     /**
    52      * Replies the token key
    53      *
    54      * @return the token key
    55      */
    56     public String getKey() {
    57         return key;
    58     }
    59 
    60     /**
    61      * Replies the token secret
    62      *
    63      * @return the token secret
    64      */
    65     public String getSecret() {
    66         return secret;
    67     }
    68 
    69     @Override
    70     public int hashCode() {
    71         return Objects.hash(key, secret);
    72     }
    73 
    74     @Override
    75     public boolean equals(Object obj) {
    76         if (this == obj) return true;
    77         if (obj == null || getClass() != obj.getClass()) return false;
    78         OAuthToken that = (OAuthToken) obj;
    79         return Objects.equals(key, that.key) &&
    80                 Objects.equals(secret, that.secret);
    81     }
    82 }
  • core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java
    a b  
    88 */
    99public enum OAuthVersion {
    1010    /** <a href="https://oauth.net/core/1.0a/">OAuth 1.0a</a> */
     11    @Deprecated
    1112    OAuth10a,
    1213    /** <a href="https://datatracker.ietf.org/doc/html/rfc6749">OAuth 2.0</a> */
    1314    OAuth20,
  • deleted file core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java

    diff --git a/core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java b/core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.data.oauth;
    3 
    4 import java.io.IOException;
    5 import java.io.InputStream;
    6 import java.net.URL;
    7 import java.util.Map;
    8 
    9 import org.openstreetmap.josm.tools.HttpClient;
    10 
    11 import oauth.signpost.AbstractOAuthConsumer;
    12 import oauth.signpost.AbstractOAuthProvider;
    13 
    14 /**
    15  * Adapters to make {@code oauth.signpost} work with {@link HttpClient}.
    16  */
    17 public final class SignpostAdapters {
    18 
    19     private SignpostAdapters() {
    20         // Hide constructor for utility classes
    21     }
    22 
    23     /**
    24      * OAuth provider.
    25      */
    26     public static class OAuthProvider extends AbstractOAuthProvider {
    27 
    28         private static final long serialVersionUID = 1L;
    29 
    30         /**
    31          * Constructs a new {@code OAuthProvider}.
    32          * @param requestTokenEndpointUrl request token endpoint URL
    33          * @param accessTokenEndpointUrl access token endpoint URL
    34          * @param authorizationWebsiteUrl authorization website URL
    35          */
    36         public OAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl, String authorizationWebsiteUrl) {
    37             super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);
    38         }
    39 
    40         @Override
    41         protected HttpRequest createRequest(String endpointUrl) throws Exception {
    42             return new HttpRequest(HttpClient.create(new URL(endpointUrl)));
    43         }
    44 
    45         @Override
    46         protected HttpResponse sendRequest(oauth.signpost.http.HttpRequest request) throws Exception {
    47             return new HttpResponse(((HttpRequest) request).request.connect());
    48         }
    49 
    50         @Override
    51         protected void closeConnection(oauth.signpost.http.HttpRequest request, oauth.signpost.http.HttpResponse response) throws Exception {
    52             if (response != null) {
    53                 ((HttpResponse) response).response.disconnect();
    54             } else if (request != null) {
    55                 ((HttpRequest) request).request.disconnect();
    56             }
    57         }
    58     }
    59 
    60     /**
    61      * OAuth consumer.
    62      */
    63     public static class OAuthConsumer extends AbstractOAuthConsumer {
    64 
    65         private static final long serialVersionUID = 1L;
    66 
    67         /**
    68          * Constructs a new {@code OAuthConsumer}.
    69          * @param consumerKey consumer key
    70          * @param consumerSecret consumer secret
    71          */
    72         public OAuthConsumer(String consumerKey, String consumerSecret) {
    73             super(consumerKey, consumerSecret);
    74         }
    75 
    76         @Override
    77         protected HttpRequest wrap(Object request) {
    78             return new HttpRequest((HttpClient) request);
    79         }
    80     }
    81 
    82     static final class HttpRequest implements oauth.signpost.http.HttpRequest {
    83         final HttpClient request;
    84 
    85         HttpRequest(HttpClient request) {
    86             this.request = request;
    87         }
    88 
    89         @Override
    90         public void setHeader(String name, String value) {
    91             request.setHeader(name, value);
    92         }
    93 
    94         @Override
    95         public String getMethod() {
    96             return request.getRequestMethod();
    97         }
    98 
    99         @Override
    100         public String getRequestUrl() {
    101             return request.getURL().toExternalForm();
    102         }
    103 
    104         @Override
    105         public String getContentType() {
    106             return request.getRequestHeader("Content-Type");
    107         }
    108 
    109         @Override
    110         public String getHeader(String name) {
    111             return request.getRequestHeader(name);
    112         }
    113 
    114         @Override
    115         public InputStream getMessagePayload() {
    116             return null;
    117         }
    118 
    119         @Override
    120         public void setRequestUrl(String url) {
    121             throw new IllegalStateException();
    122         }
    123 
    124         @Override
    125         public Map<String, String> getAllHeaders() {
    126             throw new IllegalStateException();
    127         }
    128 
    129         @Override
    130         public Object unwrap() {
    131             throw new IllegalStateException();
    132         }
    133     }
    134 
    135     static final class HttpResponse implements oauth.signpost.http.HttpResponse {
    136         final HttpClient.Response response;
    137 
    138         HttpResponse(HttpClient.Response response) {
    139             this.response = response;
    140         }
    141 
    142         @Override
    143         public int getStatusCode() {
    144             return response.getResponseCode();
    145         }
    146 
    147         @Override
    148         public String getReasonPhrase() {
    149             return response.getResponseMessage();
    150         }
    151 
    152         @Override
    153         public InputStream getContent() throws IOException {
    154             return response.getContent();
    155         }
    156 
    157         @Override
    158         public Object unwrap() {
    159             throw new IllegalStateException();
    160         }
    161     }
    162 }
  • core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java
    a b  
    44import java.util.Objects;
    55
    66import org.openstreetmap.josm.data.oauth.IOAuthParameters;
     7import org.openstreetmap.josm.data.oauth.IOAuthToken;
    78import org.openstreetmap.josm.data.oauth.OAuthParameters;
    8 import org.openstreetmap.josm.data.oauth.OAuthToken;
    99import org.openstreetmap.josm.data.oauth.OAuthVersion;
    1010import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
    1111import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    2222    public static final String ACCESS_TOKEN_PROP = AbstractAuthorizationUI.class.getName() + ".accessToken";
    2323
    2424    private String apiUrl;
    25     private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(OAuthVersion.OAuth10a);
    26     private transient OAuthToken accessToken;
    27 
    28     /**
    29      * Constructs a new {@code AbstractAuthorizationUI} without API URL.
    30      * @since 10189
    31      */
    32     protected AbstractAuthorizationUI() {
    33     }
     25    private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties;
     26    private transient IOAuthToken accessToken;
    3427
    3528    /**
    3629     * Constructs a new {@code AbstractAuthorizationUI} for the given API URL.
    37      * @param apiUrl The OSM API URL
    38      * @since 5422
     30     * @param apiUrl The OSM API URL (may be null)
     31     * @param oAuthVersion The oauth version to use
     32     * @since xxx
    3933     */
    40     protected AbstractAuthorizationUI(String apiUrl) {
    41         setApiUrl(apiUrl);
     34    protected AbstractAuthorizationUI(String apiUrl, OAuthVersion oAuthVersion) {
     35        this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(oAuthVersion);
     36        if (apiUrl != null) {
     37            setApiUrl(apiUrl);
     38        }
    4239    }
    4340
    44     protected void fireAccessTokenChanged(OAuthToken oldValue, OAuthToken newValue) {
     41    protected void fireAccessTokenChanged(IOAuthToken oldValue, IOAuthToken newValue) {
    4542        firePropertyChange(ACCESS_TOKEN_PROP, oldValue, newValue);
    4643    }
    4744
     
    9087     *
    9188     * @return the retrieved Access Token
    9289     */
    93     public OAuthToken getAccessToken() {
     90    public IOAuthToken getAccessToken() {
    9491        return accessToken;
    9592    }
    9693
     
    10097     *
    10198     * @param accessToken the new access token. null, to clear the current access token
    10299     */
    103     protected void setAccessToken(OAuthToken accessToken) {
    104         OAuthToken oldValue = this.accessToken;
     100    protected void setAccessToken(IOAuthToken accessToken) {
     101        IOAuthToken oldValue = this.accessToken;
    105102        this.accessToken = accessToken;
    106103        if (oldValue == null ^ this.accessToken == null) {
    107104            fireAccessTokenChanged(oldValue, this.accessToken);
     
    112109        }
    113110    }
    114111
     112    /**
     113     * Get the OAuth version for this AuthorizationUI
     114     * @return The OAuth version
     115     * @since xxx
     116     */
     117    public OAuthVersion getOAuthVersion() {
     118        return this.pnlAdvancedProperties.getAdvancedParameters().getOAuthVersion();
     119    }
     120
    115121    /**
    116122     * Replies true if this UI currently has an Access Token
    117123     *
  • core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java b/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java
    a b  
    1111import javax.swing.JLabel;
    1212import javax.swing.JPanel;
    1313
     14import org.openstreetmap.josm.data.oauth.IOAuthToken;
     15import org.openstreetmap.josm.data.oauth.OAuth20Token;
    1416import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    15 import org.openstreetmap.josm.data.oauth.OAuthToken;
    1617import org.openstreetmap.josm.gui.widgets.JosmTextField;
     18import org.openstreetmap.josm.tools.JosmRuntimeException;
    1719
    1820/**
    19  * Displays the key and the secret of an OAuth Access Token.
    20  * @since 2746
     21 * Displays the key of an OAuth Access Token.
     22 * @since 2746 (modified for OAuth 2 in xxx)
    2123 */
    2224public class AccessTokenInfoPanel extends JPanel {
    2325
    2426    private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
    25     private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
    2627    private final JCheckBox cbSaveAccessTokenInPreferences = new JCheckBox(tr("Save Access Token in preferences"));
    2728
    2829    /**
     
    5556        gc.insets = new Insets(0, 0, 3, 3);
    5657        add(new JLabel(tr("Access Token Secret:")), gc);
    5758
    58         gc.gridx = 1;
    5959        gc.weightx = 1.0;
    60         add(tfAccessTokenSecret, gc);
    61         tfAccessTokenSecret.setEditable(false);
    62 
    6360        // the checkbox
    6461        gc.gridx = 0;
    6562        gc.gridy = 2;
     
    8683     *
    8784     * @param token the access  token. If null, the content in the info panel is cleared
    8885     */
    89     public void setAccessToken(OAuthToken token) {
     86    public void setAccessToken(IOAuthToken token) {
    9087        if (token == null) {
    9188            tfAccessTokenKey.setText("");
    92             tfAccessTokenSecret.setText("");
    9389            return;
    9490        }
    95         tfAccessTokenKey.setText(token.getKey());
    96         tfAccessTokenSecret.setText(token.getSecret());
     91        if (token instanceof OAuth20Token) {
     92            tfAccessTokenKey.setText(((OAuth20Token) token).getBearerToken());
     93        } else {
     94            throw new JosmRuntimeException("Unknown token type: " + token.getClass());
     95        }
    9796    }
    9897
    9998    public void setSaveToPreferences(boolean saveToPreferences) {
  • core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java b/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java
    a b  
    5252    private final JosmTextField tfRequestTokenURL = new JosmTextField();
    5353    private final JosmTextField tfAccessTokenURL = new JosmTextField();
    5454    private final JosmTextField tfAuthoriseURL = new JosmTextField();
    55     private final JosmTextField tfOsmLoginURL = new JosmTextField();
    56     private final JosmTextField tfOsmLogoutURL = new JosmTextField();
    5755    private final OAuthVersion oauthVersion;
    5856    private transient UseDefaultItemListener ilUseDefault;
    5957    private String apiUrl;
     
    8381        gc.gridy = 1;
    8482        gc.weightx = 0.0;
    8583        gc.gridwidth = 1;
    86         if (this.oauthVersion == OAuthVersion.OAuth10a) {
    87             add(new JLabel(tr("Consumer Key:")), gc);
    88         } else {
    89             add(new JLabel(tr("Client ID:")), gc);
    90         }
     84        add(new JLabel(tr("Client ID:")), gc);
    9185
    9286        gc.gridx = 1;
    9387        gc.weightx = 1.0;
     
    9892        gc.gridy++;
    9993        gc.gridx = 0;
    10094        gc.weightx = 0.0;
    101         if (this.oauthVersion == OAuthVersion.OAuth10a) {
    102             add(new JLabel(tr("Consumer Secret:")), gc);
    103         } else {
    104             add(new JLabel(tr("Client Secret:")), gc);
    105         }
     95        add(new JLabel(tr("Client Secret:")), gc);
    10696
    10797        gc.gridx = 1;
    10898        gc.weightx = 1.0;
     
    113103        gc.gridy++;
    114104        gc.gridx = 0;
    115105        gc.weightx = 0.0;
    116         if (this.oauthVersion == OAuthVersion.OAuth10a) {
    117             add(new JLabel(tr("Request Token URL:")), gc);
    118         } else {
    119             add(new JLabel(tr("Redirect URL:")), gc);
    120         }
     106        add(new JLabel(tr("Redirect URL:")), gc);
    121107
    122108        gc.gridx = 1;
    123109        gc.weightx = 1.0;
     
    146132        add(tfAuthoriseURL, gc);
    147133        SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL);
    148134
    149         if (this.oauthVersion == OAuthVersion.OAuth10a) {
    150             // -- OSM login URL
    151             gc.gridy++;
    152             gc.gridx = 0;
    153             gc.weightx = 0.0;
    154             add(new JLabel(tr("OSM login URL:")), gc);
    155 
    156             gc.gridx = 1;
    157             gc.weightx = 1.0;
    158             add(tfOsmLoginURL, gc);
    159             SelectAllOnFocusGainedDecorator.decorate(tfOsmLoginURL);
    160 
    161             // -- OSM logout URL
    162             gc.gridy++;
    163             gc.gridx = 0;
    164             gc.weightx = 0.0;
    165             add(new JLabel(tr("OSM logout URL:")), gc);
    166 
    167             gc.gridx = 1;
    168             gc.weightx = 1.0;
    169             add(tfOsmLogoutURL, gc);
    170             SelectAllOnFocusGainedDecorator.decorate(tfOsmLogoutURL);
    171         }
    172 
    173135        ilUseDefault = new UseDefaultItemListener();
    174136        cbUseDefaults.addItemListener(ilUseDefault);
    175137    }
    176138
    177139    protected boolean hasCustomSettings() {
    178         OAuthParameters params = OAuthParameters.createDefault(apiUrl);
     140        IOAuthParameters params = OAuthParameters.createDefault(apiUrl, OAuthVersion.OAuth20);
    179141        return !params.equals(getAdvancedParameters());
    180142    }
    181143
     
    213175        cbUseDefaults.setSelected(true);
    214176        IOAuthParameters iParams = OAuthParameters.createDefault(apiUrl, this.oauthVersion);
    215177        switch (this.oauthVersion) {
    216             case OAuth10a:
    217                 OAuthParameters params = (OAuthParameters) iParams;
    218                 tfConsumerKey.setText(params.getConsumerKey());
    219                 tfConsumerSecret.setText(params.getConsumerSecret());
    220                 tfRequestTokenURL.setText(params.getRequestTokenUrl());
    221                 tfAccessTokenURL.setText(params.getAccessTokenUrl());
    222                 tfAuthoriseURL.setText(params.getAuthoriseUrl());
    223                 tfOsmLoginURL.setText(params.getOsmLoginUrl());
    224                 tfOsmLogoutURL.setText(params.getOsmLogoutUrl());
    225                 break;
    226178            case OAuth20:
    227179            case OAuth21:
    228180                OAuth20Parameters params20 = (OAuth20Parameters) iParams;
     
    231183                tfAccessTokenURL.setText(params20.getAccessTokenUrl());
    232184                tfAuthoriseURL.setText(params20.getAuthorizationUrl());
    233185                tfRequestTokenURL.setText(params20.getRedirectUri());
     186                break;
     187            default:
     188                throw new UnsupportedOperationException("Unsupported OAuth version: " + this.oauthVersion);
    234189        }
    235190
    236191        setChildComponentsEnabled(false);
     
    252207    public IOAuthParameters getAdvancedParameters() {
    253208        if (cbUseDefaults.isSelected())
    254209            return OAuthParameters.createDefault(apiUrl, this.oauthVersion);
    255         if (this.oauthVersion == OAuthVersion.OAuth10a) {
    256             return new OAuthParameters(
    257                     tfConsumerKey.getText(),
    258                     tfConsumerSecret.getText(),
    259                     tfRequestTokenURL.getText(),
    260                     tfAccessTokenURL.getText(),
    261                     tfAuthoriseURL.getText(),
    262                     tfOsmLoginURL.getText(),
    263                     tfOsmLogoutURL.getText());
    264         }
    265210        return new OAuth20Parameters(
    266211                tfConsumerKey.getText(),
    267212                tfConsumerSecret.getText(),
     
    285230        } else {
    286231            cbUseDefaults.setSelected(false);
    287232            setChildComponentsEnabled(true);
    288             if (parameters instanceof OAuthParameters) {
    289                 OAuthParameters parameters10 = (OAuthParameters) parameters;
    290                 tfConsumerKey.setText(parameters10.getConsumerKey() == null ? "" : parameters10.getConsumerKey());
    291                 tfConsumerSecret.setText(parameters10.getConsumerSecret() == null ? "" : parameters10.getConsumerSecret());
    292                 tfRequestTokenURL.setText(parameters10.getRequestTokenUrl() == null ? "" : parameters10.getRequestTokenUrl());
    293                 tfAccessTokenURL.setText(parameters10.getAccessTokenUrl() == null ? "" : parameters10.getAccessTokenUrl());
    294                 tfAuthoriseURL.setText(parameters10.getAuthoriseUrl() == null ? "" : parameters10.getAuthoriseUrl());
    295                 tfOsmLoginURL.setText(parameters10.getOsmLoginUrl() == null ? "" : parameters10.getOsmLoginUrl());
    296                 tfOsmLogoutURL.setText(parameters10.getOsmLogoutUrl() == null ? "" : parameters10.getOsmLogoutUrl());
    297             } else if (parameters instanceof OAuth20Parameters) {
     233            if (parameters instanceof OAuth20Parameters) {
    298234                OAuth20Parameters parameters20 = (OAuth20Parameters) parameters;
    299235                tfConsumerKey.setText(parameters20.getClientId());
    300236                tfConsumerSecret.setText(parameters20.getClientSecret());
     
    319255        if (useDefault) {
    320256            resetToDefaultSettings();
    321257        } else {
    322             setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl));
     258            setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl, OAuthVersion.OAuth20));
    323259        }
    324260        ilUseDefault.setEnabled(true);
    325261    }
     
    330266    public void rememberPreferences() {
    331267        Config.getPref().putBoolean("oauth.settings.use-default", cbUseDefaults.isSelected());
    332268        if (cbUseDefaults.isSelected()) {
    333             new OAuthParameters(null, null, null, null, null, null, null).rememberPreferences();
     269            OAuthParameters.createDefault().rememberPreferences();
    334270        } else {
    335271            getAdvancedParameters().rememberPreferences();
    336272        }
  • core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java
    a b  
    1212import java.awt.Insets;
    1313import java.awt.event.ActionEvent;
    1414import java.io.IOException;
    15 import java.net.Authenticator.RequestorType;
    16 import java.net.PasswordAuthentication;
    1715import java.util.concurrent.Executor;
    1816
    1917import javax.swing.AbstractAction;
     
    2321import javax.swing.JOptionPane;
    2422import javax.swing.JPanel;
    2523import javax.swing.JTabbedPane;
    26 import javax.swing.event.DocumentEvent;
    27 import javax.swing.event.DocumentListener;
    28 import javax.swing.text.JTextComponent;
    2924import javax.swing.text.html.HTMLEditorKit;
    3025
     26import org.openstreetmap.josm.data.oauth.IOAuthToken;
    3127import org.openstreetmap.josm.data.oauth.OAuthParameters;
    32 import org.openstreetmap.josm.data.oauth.OAuthToken;
     28import org.openstreetmap.josm.data.oauth.OAuthVersion;
    3329import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    3430import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    3531import org.openstreetmap.josm.gui.help.HelpUtil;
    36 import org.openstreetmap.josm.gui.preferences.server.UserNameValidator;
    3732import org.openstreetmap.josm.gui.util.GuiHelper;
    38 import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator;
    3933import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    4034import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    41 import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
    42 import org.openstreetmap.josm.gui.widgets.JosmTextField;
    43 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
    4435import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
    45 import org.openstreetmap.josm.io.OsmApi;
    4636import org.openstreetmap.josm.io.OsmTransferException;
    47 import org.openstreetmap.josm.io.auth.CredentialsAgent;
    48 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
    49 import org.openstreetmap.josm.io.auth.CredentialsManager;
    5037import org.openstreetmap.josm.tools.ImageProvider;
    5138import org.openstreetmap.josm.tools.Logging;
    52 import org.openstreetmap.josm.tools.Utils;
    5339import org.xml.sax.SAXException;
    5440
    5541/**
    56  * This is an UI which supports a JOSM user to get an OAuth Access Token in a fully
     42 * This is a UI which supports a JOSM user to get an OAuth Access Token in a fully
    5743 * automatic process.
    5844 *
    5945 * @since 2746
    6046 */
    6147public class FullyAutomaticAuthorizationUI extends AbstractAuthorizationUI {
    62 
    63     private final JosmTextField tfUserName = new JosmTextField();
    64     private final JosmPasswordField tfPassword = new JosmPasswordField();
    65     private transient UserNameValidator valUserName;
    66     private transient PasswordValidator valPassword;
    6748    private final AccessTokenInfoPanel pnlAccessTokenInfo = new AccessTokenInfoPanel();
    6849    private OsmPrivilegesPanel pnlOsmPrivileges;
    6950    private JPanel pnlPropertiesPanel;
     
    10485        pnlMessage.setText("<html><body><p class=\"warning-body\">"
    10586                + tr("Please enter your OSM user name and password. The password will <strong>not</strong> be saved "
    10687                        + "in clear text in the JOSM preferences and it will be submitted to the OSM server <strong>only once</strong>. "
    107                         + "Subsequent data upload requests don''t use your password any more.").replaceAll("\\. ", ".<br>")
     88                        + "Subsequent data upload requests don''t use your password any more.").replace(". ", ".<br>")
    10889                        + "</p>"
    10990                        + "</body></html>");
    11091        pnl.add(pnlMessage, gc);
     
    120101
    121102        gc.gridx = 1;
    122103        gc.weightx = 1.0;
    123         pnl.add(tfUserName, gc);
    124         SelectAllOnFocusGainedDecorator.decorate(tfUserName);
    125         valUserName = new UserNameValidator(tfUserName);
    126         valUserName.validate();
    127104
    128105        // the password input field
    129106        gc.anchor = GridBagConstraints.NORTHWEST;
     
    135112
    136113        gc.gridx = 1;
    137114        gc.weightx = 1.0;
    138         pnl.add(tfPassword, gc);
    139         SelectAllOnFocusGainedDecorator.decorate(tfPassword);
    140         valPassword = new PasswordValidator(tfPassword);
    141         valPassword.validate();
    142115
    143116        // filler - grab remaining space
    144117        gc.gridy = 4;
     
    166139        return pnl;
    167140    }
    168141
    169     /**
    170      * Initializes the panel with values from the preferences
    171      * @param paramApiUrl the API URL
    172      */
    173     @Override
    174     public void initialize(String paramApiUrl) {
    175         super.initialize(paramApiUrl);
    176         CredentialsAgent cm = CredentialsManager.getInstance();
    177         try {
    178             PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());
    179             if (pa == null) {
    180                 tfUserName.setText("");
    181                 tfPassword.setText("");
    182             } else {
    183                 tfUserName.setText(pa.getUserName() == null ? "" : pa.getUserName());
    184                 tfPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
    185             }
    186         } catch (CredentialsAgentException e) {
    187             Logging.error(e);
    188             tfUserName.setText("");
    189             tfPassword.setText("");
    190         }
    191     }
    192 
    193142    /**
    194143     * Builds the panel with the action button  for starting the authorisation
    195144     *
     
    199148        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
    200149
    201150        RunAuthorisationAction runAuthorisationAction = new RunAuthorisationAction();
    202         tfPassword.getDocument().addDocumentListener(runAuthorisationAction);
    203         tfUserName.getDocument().addDocumentListener(runAuthorisationAction);
    204151        pnl.add(new JButton(runAuthorisationAction));
    205152        return pnl;
    206153    }
     
    288235        repaint();
    289236    }
    290237
    291     protected String getOsmUserName() {
    292         return tfUserName.getText();
    293     }
    294 
    295     protected String getOsmPassword() {
    296         return String.valueOf(tfPassword.getPassword());
    297     }
    298 
    299238    /**
    300239     * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL.
    301240     * @param apiUrl The OSM API URL
    302241     * @param executor the executor used for running the HTTP requests for the authorization
    303242     * @since 5422
     243     * @deprecated since xxx
    304244     */
     245    @Deprecated
    305246    public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor) {
    306         super(apiUrl);
     247        this(apiUrl, executor, OAuthVersion.OAuth10a);
     248    }
     249
     250    /**
     251     * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL.
     252     * @param apiUrl The OSM API URL
     253     * @param executor the executor used for running the HTTP requests for the authorization
     254     * @param oAuthVersion The OAuth version to use for this UI
     255     * @since xxx
     256     */
     257    public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) {
     258        super(apiUrl, oAuthVersion);
    307259        this.executor = executor;
    308260        build();
    309261    }
     
    314266    }
    315267
    316268    @Override
    317     protected void setAccessToken(OAuthToken accessToken) {
     269    protected void setAccessToken(IOAuthToken accessToken) {
    318270        super.setAccessToken(accessToken);
    319271        pnlAccessTokenInfo.setAccessToken(accessToken);
    320272    }
     
    322274    /**
    323275     * Starts the authorisation process
    324276     */
    325     class RunAuthorisationAction extends AbstractAction implements DocumentListener {
     277    class RunAuthorisationAction extends AbstractAction {
    326278        RunAuthorisationAction() {
    327279            putValue(NAME, tr("Authorize now"));
    328280            new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
    329281            putValue(SHORT_DESCRIPTION, tr("Click to redirect you to the authorization form on the JOSM web site"));
    330             updateEnabledState();
    331282        }
    332283
    333284        @Override
    334285        public void actionPerformed(ActionEvent evt) {
    335286            executor.execute(new FullyAutomaticAuthorisationTask(FullyAutomaticAuthorizationUI.this));
    336287        }
    337 
    338         protected final void updateEnabledState() {
    339             setEnabled(valPassword.isValid() && valUserName.isValid());
    340         }
    341 
    342         @Override
    343         public void changedUpdate(DocumentEvent e) {
    344             updateEnabledState();
    345         }
    346 
    347         @Override
    348         public void insertUpdate(DocumentEvent e) {
    349             updateEnabledState();
    350         }
    351 
    352         @Override
    353         public void removeUpdate(DocumentEvent e) {
    354             updateEnabledState();
    355         }
    356288    }
    357289
    358290    /**
     
    385317            executor.execute(new TestAccessTokenTask(
    386318                    FullyAutomaticAuthorizationUI.this,
    387319                    getApiUrl(),
    388                     (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
    389320                    getAccessToken()
    390321            ));
    391322        }
    392323    }
    393324
    394     static class PasswordValidator extends DefaultTextComponentValidator {
    395         PasswordValidator(JTextComponent tc) {
    396             super(tc, tr("Please enter your OSM password"), tr("The password cannot be empty. Please enter your OSM password"));
    397         }
    398     }
    399 
    400325    class FullyAutomaticAuthorisationTask extends PleaseWaitRunnable {
    401326        private boolean canceled;
    402327
     
    438363                            + "a valid login URL from the OAuth Authorize Endpoint URL ''{0}''.<br><br>"
    439364                            + "Please check your advanced setting and try again."
    440365                            + "</html>",
    441                             ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getAuthoriseUrl()),
    442                     tr("OAuth authorization failed"),
    443                     JOptionPane.ERROR_MESSAGE,
    444                     HelpUtil.ht("/Dialog/OAuthAuthorisationWizard#FullyAutomaticProcessFailed")
    445             );
    446         }
    447 
    448         protected void alertLoginFailed() {
    449             final String loginUrl = ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getOsmLoginUrl();
    450             HelpAwareOptionPane.showOptionDialog(
    451                     FullyAutomaticAuthorizationUI.this,
    452                     tr("<html>"
    453                             + "The automatic process for retrieving an OAuth Access Token<br>"
    454                             + "from the OSM server failed. JOSM failed to log into {0}<br>"
    455                             + "for user {1}.<br><br>"
    456                             + "Please check username and password and try again."
    457                             +"</html>",
    458                             loginUrl,
    459                             Utils.escapeReservedCharactersHTML(getOsmUserName())),
     366                            getAdvancedPropertiesPanel().getAdvancedParameters().getAuthorizationUrl()),
    460367                    tr("OAuth authorization failed"),
    461368                    JOptionPane.ERROR_MESSAGE,
    462369                    HelpUtil.ht("/Dialog/OAuthAuthorisationWizard#FullyAutomaticProcessFailed")
     
    464371        }
    465372
    466373        protected void handleException(final OsmOAuthAuthorizationException e) {
    467             Runnable r = () -> {
    468                 if (e instanceof OsmLoginFailedException) {
    469                     alertLoginFailed();
    470                 } else {
    471                     alertAuthorisationFailed();
    472                 }
    473             };
    474374            Logging.error(e);
    475             GuiHelper.runInEDT(r);
     375            GuiHelper.runInEDT(this::alertAuthorisationFailed);
    476376        }
    477377
    478378        @Override
    479379        protected void realRun() throws SAXException, IOException, OsmTransferException {
    480             try {
    481                 getProgressMonitor().setTicksCount(3);
    482                 OsmOAuthAuthorizationClient authClient = new OsmOAuthAuthorizationClient(
    483                         (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()
    484                 );
    485                 OAuthToken requestToken = authClient.getRequestToken(
    486                         getProgressMonitor().createSubTaskMonitor(1, false)
    487                 );
    488                 getProgressMonitor().worked(1);
    489                 if (canceled) return;
    490                 authClient.authorise(
    491                         requestToken,
    492                         getOsmUserName(),
    493                         getOsmPassword(),
    494                         pnlOsmPrivileges.getPrivileges(),
    495                         getProgressMonitor().createSubTaskMonitor(1, false)
    496                 );
    497                 getProgressMonitor().worked(1);
    498                 if (canceled) return;
    499                 final OAuthToken accessToken = authClient.getAccessToken(
    500                         getProgressMonitor().createSubTaskMonitor(1, false)
    501                 );
    502                 getProgressMonitor().worked(1);
    503                 if (canceled) return;
    504                 GuiHelper.runInEDT(() -> {
    505                     prepareUIForResultDisplay();
    506                     setAccessToken(accessToken);
    507                 });
    508             } catch (final OsmOAuthAuthorizationException e) {
    509                 handleException(e);
    510             }
     380            getProgressMonitor().setTicksCount(2);
     381            OAuthAuthorizationWizard.authorize(true, token -> {
     382                if (!canceled) {
     383                    getProgressMonitor().worked(1);
     384                    GuiHelper.runInEDT(() -> {
     385                        prepareUIForResultDisplay();
     386                        setAccessToken(token.orElse(null));
     387                    });
     388                }
     389            }, getOAuthVersion());
     390            getProgressMonitor().worked(1);
    511391        }
    512392    }
    513393}
  • core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java
    a b  
    2424import javax.swing.event.DocumentListener;
    2525import javax.swing.text.JTextComponent;
    2626
     27import org.openstreetmap.josm.data.oauth.OAuth20Exception;
     28import org.openstreetmap.josm.data.oauth.OAuth20Token;
    2729import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    2830import org.openstreetmap.josm.data.oauth.OAuthParameters;
    29 import org.openstreetmap.josm.data.oauth.OAuthToken;
     31import org.openstreetmap.josm.data.oauth.OAuthVersion;
    3032import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator;
    3133import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    3234import org.openstreetmap.josm.gui.widgets.JosmTextField;
    3335import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
    3436import org.openstreetmap.josm.tools.ImageProvider;
     37import org.openstreetmap.josm.tools.JosmRuntimeException;
    3538
    3639/**
    3740 * This is an UI which supports a JOSM user to get an OAuth Access Token in a fully manual process.
     
    4346    private final JosmTextField tfAccessTokenKey = new JosmTextField();
    4447    private transient AccessTokenKeyValidator valAccessTokenKey;
    4548    private final JosmTextField tfAccessTokenSecret = new JosmTextField();
    46     private transient AccessTokenSecretValidator valAccessTokenSecret;
    4749    private final JCheckBox cbSaveToPreferences = new JCheckBox(tr("Save Access Token in preferences"));
    4850    private final HtmlPanel pnlMessage = new HtmlPanel();
    4951    private final transient Executor executor;
     
    5355     * @param apiUrl The OSM API URL
    5456     * @param executor the executor used for running the HTTP requests for the authorization
    5557     * @since 5422
     58     * @deprecated since xxx, use {@link ManualAuthorizationUI#ManualAuthorizationUI(String, Executor, OAuthVersion)}
     59     * instead.
    5660     */
     61    @Deprecated
    5762    public ManualAuthorizationUI(String apiUrl, Executor executor) {
    58         super(/* dont pass apiURL because setApiUrl is overridden and references a local field */);
     63        this(apiUrl, executor, OAuthVersion.OAuth10a);
     64    }
     65
     66    /**
     67     * Constructs a new {@code ManualAuthorizationUI} for the given API URL.
     68     * @param apiUrl The OSM API URL
     69     * @param executor the executor used for running the HTTP requests for the authorization
     70     * @param oAuthVersion The OAuthVersion to use for this UI
     71     * @since xxx
     72     */
     73    public ManualAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) {
     74        super(null /* don't pass apiURL because setApiUrl is overridden and references a local field */,
     75                oAuthVersion);
    5976        setApiUrl(apiUrl);
    6077        this.executor = executor;
    6178        build();
     
    94111        valAccessTokenKey.validate();
    95112        tfAccessTokenKey.getDocument().addDocumentListener(accessTokenBuilder);
    96113
    97         // the access token key input field
    98         gc.gridy = 2;
    99         gc.gridx = 0;
    100         gc.weightx = 0.0;
    101         pnl.add(new JLabel(tr("Access Token Secret:")), gc);
    102 
    103         gc.gridx = 1;
    104         gc.weightx = 1.0;
    105         pnl.add(tfAccessTokenSecret, gc);
    106         SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenSecret);
    107         valAccessTokenSecret = new AccessTokenSecretValidator(tfAccessTokenSecret);
    108         valAccessTokenSecret.validate();
    109         tfAccessTokenSecret.getDocument().addDocumentListener(accessTokenBuilder);
    110 
    111114        // the checkbox for saving to preferences
    112115        gc.gridy = 3;
    113116        gc.gridx = 0;
     
    184187        }
    185188    }
    186189
    187     private static class AccessTokenSecretValidator extends DefaultTextComponentValidator {
    188         AccessTokenSecretValidator(JTextComponent tc) {
    189             super(tc, tr("Please enter an Access Token Secret"),
    190                       tr("The Access Token Secret must not be empty. Please enter an Access Token Secret"));
    191         }
    192     }
    193 
    194190    class AccessTokenBuilder implements DocumentListener {
    195191
    196192        public void build() {
    197             if (!valAccessTokenKey.isValid() || !valAccessTokenSecret.isValid()) {
     193            if (!valAccessTokenKey.isValid()) {
    198194                setAccessToken(null);
    199195            } else {
    200                 setAccessToken(new OAuthToken(tfAccessTokenKey.getText().trim(), tfAccessTokenSecret.getText().trim()));
     196                try {
     197                    setAccessToken(new OAuth20Token(getOAuthParameters(), "{\"token_type\":\"bearer\", \"access_token\""
     198                            + tfAccessTokenKey.getText().trim() + "\"}"));
     199                } catch (OAuth20Exception e) {
     200                    throw new JosmRuntimeException(e);
     201                }
    201202            }
    202203        }
    203204
     
    233234            TestAccessTokenTask task = new TestAccessTokenTask(
    234235                    ManualAuthorizationUI.this,
    235236                    getApiUrl(),
    236                     (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
    237237                    getAccessToken()
    238238            );
    239239            executor.execute(task);
  • core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java b/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
    a b  
    1717import java.beans.PropertyChangeEvent;
    1818import java.beans.PropertyChangeListener;
    1919import java.lang.reflect.InvocationTargetException;
    20 import java.net.URL;
     20import java.net.URI;
    2121import java.util.Objects;
     22import java.util.Optional;
    2223import java.util.concurrent.Executor;
    2324import java.util.concurrent.FutureTask;
     25import java.util.function.Consumer;
    2426
    2527import javax.swing.AbstractAction;
    2628import javax.swing.BorderFactory;
    2729import javax.swing.JButton;
    2830import javax.swing.JDialog;
     31import javax.swing.JOptionPane;
    2932import javax.swing.JPanel;
    3033import javax.swing.JScrollPane;
    3134import javax.swing.SwingUtilities;
    3235import javax.swing.UIManager;
    3336import javax.swing.text.html.HTMLEditorKit;
    3437
     38import org.openstreetmap.josm.data.oauth.IOAuthParameters;
     39import org.openstreetmap.josm.data.oauth.IOAuthToken;
     40import org.openstreetmap.josm.data.oauth.OAuth20Authorization;
    3541import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    3642import org.openstreetmap.josm.data.oauth.OAuthParameters;
    37 import org.openstreetmap.josm.data.oauth.OAuthToken;
     43import org.openstreetmap.josm.data.oauth.OAuthVersion;
     44import org.openstreetmap.josm.data.oauth.osm.OsmScopes;
    3845import org.openstreetmap.josm.gui.MainApplication;
    3946import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
    4047import org.openstreetmap.josm.gui.help.HelpUtil;
     
    4249import org.openstreetmap.josm.gui.util.WindowGeometry;
    4350import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    4451import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
     52import org.openstreetmap.josm.io.OsmApi;
     53import org.openstreetmap.josm.io.auth.CredentialsManager;
     54import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
    4555import org.openstreetmap.josm.spi.preferences.Config;
    4656import org.openstreetmap.josm.tools.GBC;
    4757import org.openstreetmap.josm.tools.ImageProvider;
     
    5868    private boolean canceled;
    5969    private final AuthorizationProcedure procedure;
    6070    private final String apiUrl;
     71    private final OAuthVersion oAuthVersion;
    6172
    6273    private FullyAutomaticAuthorizationUI pnlFullyAutomaticAuthorisationUI;
    63     private SemiAutomaticAuthorizationUI pnlSemiAutomaticAuthorisationUI;
    6474    private ManualAuthorizationUI pnlManualAuthorisationUI;
    6575    private JScrollPane spAuthorisationProcedureUI;
    6676    private final transient Executor executor;
    6777
    6878    /**
    69      * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken(OAuthToken) sets the token}
     79     * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken(String, IOAuthToken)} sets the token
    7080     * and {@link OAuthAccessTokenHolder#setSaveToPreferences(boolean) saves to preferences}.
     81     * @param callback Callback to run when authorization is finished
    7182     * @throws UserCancelException if user cancels the operation
    7283     */
    73     public void showDialog() throws UserCancelException {
    74         setVisible(true);
    75         if (isCanceled()) {
    76             throw new UserCancelException();
     84    public void showDialog(Consumer<Optional<IOAuthToken>> callback) throws UserCancelException {
     85        if ((this.oAuthVersion == OAuthVersion.OAuth20 || this.oAuthVersion == OAuthVersion.OAuth21)
     86        && this.procedure == AuthorizationProcedure.FULLY_AUTOMATIC) {
     87            authorize(true, callback, this.oAuthVersion);
     88        } else {
     89            setVisible(true);
     90            if (isCanceled()) {
     91                throw new UserCancelException();
     92            }
    7793        }
    7894        OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
    79         holder.setAccessToken(getAccessToken());
     95        holder.setAccessToken(apiUrl, getAccessToken());
    8096        holder.setSaveToPreferences(isSaveAccessTokenToPreferences());
    8197    }
    8298
     99    /**
     100     * Perform the oauth dance
     101     * @param startRemoteControl {@code true} to start remote control if it is not already running
     102     * @param callback The callback to use to notify that the OAuth dance succeeded
     103     * @param oAuthVersion The OAuth version that the authorization dance is force
     104     */
     105    static void authorize(boolean startRemoteControl, Consumer<Optional<IOAuthToken>> callback, OAuthVersion oAuthVersion) {
     106        final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get());
     107        // TODO: Ask user if they want to start remote control?
     108        if (!remoteControlIsRunning && startRemoteControl) {
     109            RemoteControl.start();
     110        }
     111        new OAuth20Authorization().authorize(OAuthParameters.createDefault(OsmApi.getOsmApi().getServerUrl(), oAuthVersion), token -> {
     112                    if (!remoteControlIsRunning) {
     113                        RemoteControl.stop();
     114                    }
     115                    OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), token.orElse(null));
     116                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
     117                    if (!token.isPresent()) {
     118                        GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(),
     119                                tr("Authentication failed, please check browser for details."),
     120                                tr("OAuth Authentication Failed"),
     121                                JOptionPane.ERROR_MESSAGE));
     122                    }
     123                    if (callback != null) {
     124                        callback.accept(token);
     125                    }
     126                }, OsmScopes.read_gpx, OsmScopes.write_gpx,
     127                OsmScopes.read_prefs, OsmScopes.write_prefs,
     128                OsmScopes.write_api, OsmScopes.write_notes);
     129    }
     130
    83131    /**
    84132     * Builds the row with the action buttons
    85133     *
     
    90138
    91139        AcceptAccessTokenAction actAcceptAccessToken = new AcceptAccessTokenAction();
    92140        pnlFullyAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
    93         pnlSemiAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
    94141        pnlManualAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
    95142
    96143        pnl.add(new JButton(actAcceptAccessToken));
     
    153200            spAuthorisationProcedureUI.getViewport().setView(pnlFullyAutomaticAuthorisationUI);
    154201            pnlFullyAutomaticAuthorisationUI.revalidate();
    155202            break;
    156         case SEMI_AUTOMATIC:
    157             spAuthorisationProcedureUI.getViewport().setView(pnlSemiAutomaticAuthorisationUI);
    158             pnlSemiAutomaticAuthorisationUI.revalidate();
    159             break;
    160203        case MANUALLY:
    161204            spAuthorisationProcedureUI.getViewport().setView(pnlManualAuthorisationUI);
    162205            pnlManualAuthorisationUI.revalidate();
    163206            break;
     207        default:
     208            throw new UnsupportedOperationException("Unsupported auth type: " + procedure);
    164209        }
    165210        validate();
    166211        repaint();
     
    176221        setTitle(tr("Get an Access Token for ''{0}''", apiUrl));
    177222        this.setMinimumSize(new Dimension(500, 300));
    178223
    179         pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor);
    180         pnlSemiAutomaticAuthorisationUI = new SemiAutomaticAuthorizationUI(apiUrl, executor);
    181         pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor);
     224        pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor, oAuthVersion);
     225        pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor, oAuthVersion);
    182226
    183227        spAuthorisationProcedureUI = GuiHelper.embedInVerticalScrollPane(new JPanel());
    184228        spAuthorisationProcedureUI.getVerticalScrollBar().addComponentListener(
     
    212256     * @param procedure the authorization procedure to use
    213257     * @param apiUrl the API URL. Must not be null.
    214258     * @param executor the executor used for running the HTTP requests for the authorization
     259     * @param oAuthVersion The OAuth version this wizard is for
    215260     * @throws IllegalArgumentException if apiUrl is null
    216261     */
    217     public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl, Executor executor) {
     262    public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl,
     263                                    Executor executor, OAuthVersion oAuthVersion) {
    218264        super(GuiHelper.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
    219265        this.procedure = Objects.requireNonNull(procedure, "procedure");
    220266        this.apiUrl = Objects.requireNonNull(apiUrl, "apiUrl");
    221267        this.executor = executor;
     268        this.oAuthVersion = oAuthVersion;
    222269        build();
    223270    }
    224271
     
    235282        switch(procedure) {
    236283        case FULLY_AUTOMATIC: return pnlFullyAutomaticAuthorisationUI;
    237284        case MANUALLY: return pnlManualAuthorisationUI;
    238         case SEMI_AUTOMATIC: return pnlSemiAutomaticAuthorisationUI;
    239285        default: return null;
    240286        }
    241287    }
     
    245291     *
    246292     * @return the access token. May be null if the wizard was canceled.
    247293     */
    248     public OAuthToken getAccessToken() {
     294    public IOAuthToken getAccessToken() {
    249295        return getCurrentAuthorisationUI().getAccessToken();
    250296    }
    251297
     
    254300     *
    255301     * @return the current OAuth parameters.
    256302     */
    257     public OAuthParameters getOAuthParameters() {
    258         return (OAuthParameters) getCurrentAuthorisationUI().getOAuthParameters();
     303    public IOAuthParameters getOAuthParameters() {
     304        return getCurrentAuthorisationUI().getOAuthParameters();
    259305    }
    260306
    261307    /**
     
    275321     */
    276322    public void initFromPreferences() {
    277323        pnlFullyAutomaticAuthorisationUI.initialize(apiUrl);
    278         pnlSemiAutomaticAuthorisationUI.initialize(apiUrl);
    279324        pnlManualAuthorisationUI.initialize(apiUrl);
    280325    }
    281326
     
    308353     * @throws InvocationTargetException if an exception is thrown while running OAuth authorization task
    309354     * @since 12803
    310355     */
    311     public static void obtainAccessToken(final URL serverUrl) throws InvocationTargetException, InterruptedException {
     356    public static void obtainAccessToken(final URI serverUrl) throws InvocationTargetException, InterruptedException {
    312357        final Runnable authTask = new FutureTask<>(() -> {
    313358            // Concerning Utils.newDirectExecutor: Main worker cannot be used since this connection is already
    314359            // executed via main worker. The OAuth connections would block otherwise.
    315360            final OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
    316361                    MainApplication.getMainFrame(),
    317362                    AuthorizationProcedure.FULLY_AUTOMATIC,
    318                     serverUrl.toExternalForm(), Utils.newDirectExecutor());
    319             wizard.showDialog();
     363                    serverUrl.toString(), Utils.newDirectExecutor(),
     364                    OAuthVersion.OAuth20);
     365            wizard.showDialog(null);
    320366            return wizard;
    321367        });
    322368        // exception handling differs from implementation at GuiHelper.runInEDTAndWait()
     
    358404            putValue(NAME, tr("Accept Access Token"));
    359405            new ImageProvider("ok").getResource().attachImageIcon(this);
    360406            putValue(SHORT_DESCRIPTION, tr("Close the dialog and accept the Access Token"));
    361             updateEnabledState(null);
     407            updateEnabledState((IOAuthToken) null);
    362408        }
    363409
    364410        @Override
     
    367413            setVisible(false);
    368414        }
    369415
    370         public final void updateEnabledState(OAuthToken token) {
     416        /**
     417         * Update the enabled state
     418         * @param token The token to use
     419         * @since xxx
     420         */
     421        public final void updateEnabledState(IOAuthToken token) {
    371422            setEnabled(token != null);
    372423        }
    373424
     
    375426        public void propertyChange(PropertyChangeEvent evt) {
    376427            if (!evt.getPropertyName().equals(AbstractAuthorizationUI.ACCESS_TOKEN_PROP))
    377428                return;
    378             updateEnabledState((OAuthToken) evt.getNewValue());
     429            updateEnabledState((IOAuthToken) evt.getNewValue());
    379430        }
    380431    }
    381432
  • deleted file core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java

    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java b/core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 /**
    5  * OSM login failure exception.
    6  * @since 2746
    7  */
    8 public class OsmLoginFailedException extends OsmOAuthAuthorizationException {
    9 
    10     /**
    11      * Constructs a new {@code OsmLoginFailedException} with the specified cause.
    12      * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
    13      */
    14     public OsmLoginFailedException(Throwable cause) {
    15         super(cause);
    16     }
    17 }
  • deleted file core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java

    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java b/core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.io.BufferedReader;
    7 import java.io.IOException;
    8 import java.net.CookieHandler;
    9 import java.net.HttpURLConnection;
    10 import java.net.URISyntaxException;
    11 import java.net.URL;
    12 import java.nio.charset.StandardCharsets;
    13 import java.util.Collections;
    14 import java.util.HashMap;
    15 import java.util.Iterator;
    16 import java.util.List;
    17 import java.util.Map;
    18 import java.util.Map.Entry;
    19 import java.util.regex.Matcher;
    20 import java.util.regex.Pattern;
    21 
    22 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    23 import org.openstreetmap.josm.data.oauth.OAuthToken;
    24 import org.openstreetmap.josm.data.oauth.OsmPrivileges;
    25 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    26 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    27 import org.openstreetmap.josm.io.OsmTransferCanceledException;
    28 import org.openstreetmap.josm.tools.CheckParameterUtil;
    29 import org.openstreetmap.josm.tools.HttpClient;
    30 import org.openstreetmap.josm.tools.Logging;
    31 import org.openstreetmap.josm.tools.Utils;
    32 
    33 import oauth.signpost.OAuth;
    34 import oauth.signpost.OAuthConsumer;
    35 import oauth.signpost.OAuthProvider;
    36 import oauth.signpost.exception.OAuthException;
    37 
    38 /**
    39  * An OAuth 1.0 authorization client.
    40  * @since 2746
    41  */
    42 public class OsmOAuthAuthorizationClient {
    43     private final OAuthParameters oauthProviderParameters;
    44     private final OAuthConsumer consumer;
    45     private final OAuthProvider provider;
    46     private boolean canceled;
    47     private HttpClient connection;
    48 
    49     protected static class SessionId {
    50         protected String id;
    51         protected String token;
    52         protected String userName;
    53     }
    54 
    55     /**
    56      * Creates a new authorisation client with the parameters <code>parameters</code>.
    57      *
    58      * @param parameters the OAuth parameters. Must not be null.
    59      * @throws IllegalArgumentException if parameters is null
    60      */
    61     public OsmOAuthAuthorizationClient(OAuthParameters parameters) {
    62         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    63         oauthProviderParameters = new OAuthParameters(parameters);
    64         consumer = oauthProviderParameters.buildConsumer();
    65         provider = oauthProviderParameters.buildProvider(consumer);
    66     }
    67 
    68     /**
    69      * Creates a new authorisation client with the parameters <code>parameters</code>
    70      * and an already known Request Token.
    71      *
    72      * @param parameters the OAuth parameters. Must not be null.
    73      * @param requestToken the request token. Must not be null.
    74      * @throws IllegalArgumentException if parameters is null
    75      * @throws IllegalArgumentException if requestToken is null
    76      */
    77     public OsmOAuthAuthorizationClient(OAuthParameters parameters, OAuthToken requestToken) {
    78         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    79         oauthProviderParameters = new OAuthParameters(parameters);
    80         consumer = oauthProviderParameters.buildConsumer();
    81         provider = oauthProviderParameters.buildProvider(consumer);
    82         consumer.setTokenWithSecret(requestToken.getKey(), requestToken.getSecret());
    83     }
    84 
    85     /**
    86      * Cancels the current OAuth operation.
    87      */
    88     public void cancel() {
    89         canceled = true;
    90         synchronized (this) {
    91             if (connection != null) {
    92                 connection.disconnect();
    93             }
    94         }
    95     }
    96 
    97     /**
    98      * Submits a request for a Request Token to the Request Token Endpoint Url of the OAuth Service
    99      * Provider and replies the request token.
    100      *
    101      * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
    102      * @return the OAuth Request Token
    103      * @throws OsmOAuthAuthorizationException if something goes wrong when retrieving the request token
    104      * @throws OsmTransferCanceledException if the user canceled the request
    105      */
    106     public OAuthToken getRequestToken(ProgressMonitor monitor) throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
    107         if (monitor == null) {
    108             monitor = NullProgressMonitor.INSTANCE;
    109         }
    110         try {
    111             monitor.beginTask("");
    112             monitor.indeterminateSubTask(tr("Retrieving OAuth Request Token from ''{0}''", oauthProviderParameters.getRequestTokenUrl()));
    113             provider.retrieveRequestToken(consumer, "");
    114             return OAuthToken.createToken(consumer);
    115         } catch (OAuthException e) {
    116             if (canceled)
    117                 throw new OsmTransferCanceledException(e);
    118             throw new OsmOAuthAuthorizationException(e);
    119         } finally {
    120             monitor.finishTask();
    121         }
    122     }
    123 
    124     /**
    125      * Submits a request for an Access Token to the Access Token Endpoint Url of the OAuth Service
    126      * Provider and replies the request token.
    127      *
    128      * You must have requested a Request Token using {@link #getRequestToken(ProgressMonitor)} first.
    129      *
    130      * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
    131      * @return the OAuth Access Token
    132      * @throws OsmOAuthAuthorizationException if something goes wrong when retrieving the request token
    133      * @throws OsmTransferCanceledException if the user canceled the request
    134      * @see #getRequestToken(ProgressMonitor)
    135      */
    136     public OAuthToken getAccessToken(ProgressMonitor monitor) throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
    137         if (monitor == null) {
    138             monitor = NullProgressMonitor.INSTANCE;
    139         }
    140         try {
    141             monitor.beginTask("");
    142             monitor.indeterminateSubTask(tr("Retrieving OAuth Access Token from ''{0}''", oauthProviderParameters.getAccessTokenUrl()));
    143             provider.retrieveAccessToken(consumer, null);
    144             return OAuthToken.createToken(consumer);
    145         } catch (OAuthException e) {
    146             if (canceled)
    147                 throw new OsmTransferCanceledException(e);
    148             throw new OsmOAuthAuthorizationException(e);
    149         } finally {
    150             monitor.finishTask();
    151         }
    152     }
    153 
    154     /**
    155      * Builds the authorise URL for a given Request Token. Users can be redirected to this URL.
    156      * There they can login to OSM and authorise the request.
    157      *
    158      * @param requestToken  the request token
    159      * @return  the authorise URL for this request
    160      */
    161     public String getAuthoriseUrl(OAuthToken requestToken) {
    162         StringBuilder sb = new StringBuilder(32);
    163 
    164         // OSM is an OAuth 1.0 provider and JOSM isn't a web app. We just add the oauth request token to
    165         // the authorisation request, no callback parameter.
    166         //
    167         sb.append(oauthProviderParameters.getAuthoriseUrl()).append('?'+OAuth.OAUTH_TOKEN+'=').append(requestToken.getKey());
    168         return sb.toString();
    169     }
    170 
    171     protected String extractToken() {
    172         try (BufferedReader r = connection.getResponse().getContentReader()) {
    173             String c;
    174             Pattern p = Pattern.compile(".*authenticity_token.*value=\"([^\"]+)\".*");
    175             while ((c = r.readLine()) != null) {
    176                 Matcher m = p.matcher(c);
    177                 if (m.find()) {
    178                     return m.group(1);
    179                 }
    180             }
    181         } catch (IOException e) {
    182             Logging.error(e);
    183             return null;
    184         }
    185         Logging.warn("No authenticity_token found in response!");
    186         return null;
    187     }
    188 
    189     protected SessionId extractOsmSession() throws IOException, URISyntaxException {
    190         // response headers might not contain the cookie, see #12584
    191         final List<String> setCookies = CookieHandler.getDefault()
    192                 .get(connection.getURL().toURI(), Collections.<String, List<String>>emptyMap())
    193                 .get("Cookie");
    194         if (setCookies == null) {
    195             Logging.warn("No 'Set-Cookie' in response header!");
    196             return null;
    197         }
    198 
    199         for (String setCookie: setCookies) {
    200             String[] kvPairs = setCookie.split(";", -1);
    201             for (String kvPair : kvPairs) {
    202                 kvPair = kvPair.trim();
    203                 String[] kv = kvPair.split("=", -1);
    204                 if (kv.length != 2) {
    205                     continue;
    206                 }
    207                 if ("_osm_session".equals(kv[0])) {
    208                     // osm session cookie found
    209                     String token = extractToken();
    210                     if (token == null)
    211                         return null;
    212                     SessionId si = new SessionId();
    213                     si.id = kv[1];
    214                     si.token = token;
    215                     return si;
    216                 }
    217             }
    218         }
    219         Logging.warn("No suitable 'Set-Cookie' in response header found! {0}", setCookies);
    220         return null;
    221     }
    222 
    223     protected static String buildPostRequest(Map<String, String> parameters) {
    224         StringBuilder sb = new StringBuilder(32);
    225 
    226         for (Iterator<Entry<String, String>> it = parameters.entrySet().iterator(); it.hasNext();) {
    227             Entry<String, String> entry = it.next();
    228             String value = entry.getValue();
    229             value = (value == null) ? "" : value;
    230             sb.append(entry.getKey()).append('=').append(Utils.encodeUrl(value));
    231             if (it.hasNext()) {
    232                 sb.append('&');
    233             }
    234         }
    235         return sb.toString();
    236     }
    237 
    238     /**
    239      * Submits a request to the OSM website for a login form. The OSM website replies a session ID in
    240      * a cookie.
    241      *
    242      * @return the session ID structure
    243      * @throws OsmOAuthAuthorizationException if something went wrong
    244      */
    245     protected SessionId fetchOsmWebsiteSessionId() throws OsmOAuthAuthorizationException {
    246         try {
    247             final URL url = new URL(oauthProviderParameters.getOsmLoginUrl() + "?cookie_test=true");
    248             synchronized (this) {
    249                 connection = HttpClient.create(url).useCache(false);
    250                 connection.connect();
    251             }
    252             SessionId sessionId = extractOsmSession();
    253             if (sessionId == null)
    254                 throw new OsmOAuthAuthorizationException(
    255                         tr("OSM website did not return a session cookie in response to ''{0}'',", url.toString()));
    256             return sessionId;
    257         } catch (IOException | URISyntaxException e) {
    258             throw new OsmOAuthAuthorizationException(e);
    259         } finally {
    260             synchronized (this) {
    261                 connection = null;
    262             }
    263         }
    264     }
    265 
    266     /**
    267      * Submits a request to the OSM website for a OAuth form. The OSM website replies a session token in
    268      * a hidden parameter.
    269      * @param sessionId session id
    270      * @param requestToken request token
    271      *
    272      * @throws OsmOAuthAuthorizationException if something went wrong
    273      */
    274     protected void fetchOAuthToken(SessionId sessionId, OAuthToken requestToken) throws OsmOAuthAuthorizationException {
    275         try {
    276             URL url = new URL(getAuthoriseUrl(requestToken));
    277             synchronized (this) {
    278                 connection = HttpClient.create(url)
    279                         .useCache(false)
    280                         .setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName);
    281                 connection.connect();
    282             }
    283             sessionId.token = extractToken();
    284             if (sessionId.token == null)
    285                 throw new OsmOAuthAuthorizationException(tr("OSM website did not return a session cookie in response to ''{0}'',",
    286                         url.toString()));
    287         } catch (IOException e) {
    288             throw new OsmOAuthAuthorizationException(e);
    289         } finally {
    290             synchronized (this) {
    291                 connection = null;
    292             }
    293         }
    294     }
    295 
    296     protected void authenticateOsmSession(SessionId sessionId, String userName, String password) throws OsmLoginFailedException {
    297         try {
    298             final URL url = new URL(oauthProviderParameters.getOsmLoginUrl());
    299             final HttpClient client = HttpClient.create(url, "POST").useCache(false);
    300 
    301             Map<String, String> parameters = new HashMap<>();
    302             parameters.put("username", userName);
    303             parameters.put("password", password);
    304             parameters.put("referer", "/");
    305             parameters.put("commit", "Login");
    306             parameters.put("authenticity_token", sessionId.token);
    307             client.setRequestBody(buildPostRequest(parameters).getBytes(StandardCharsets.UTF_8));
    308 
    309             client.setHeader("Content-Type", "application/x-www-form-urlencoded");
    310             client.setHeader("Cookie", "_osm_session=" + sessionId.id);
    311             // make sure we can catch 302 Moved Temporarily below
    312             client.setMaxRedirects(-1);
    313 
    314             synchronized (this) {
    315                 connection = client;
    316                 connection.connect();
    317             }
    318 
    319             // after a successful login the OSM website sends a redirect to a follow up page. Everything
    320             // else, including a 200 OK, is a failed login. A 200 OK is replied if the login form with
    321             // an error page is sent to back to the user.
    322             //
    323             int retCode = connection.getResponse().getResponseCode();
    324             if (retCode != HttpURLConnection.HTTP_MOVED_TEMP)
    325                 throw new OsmOAuthAuthorizationException(tr("Failed to authenticate user ''{0}'' with password ''***'' as OAuth user",
    326                         userName));
    327         } catch (OsmOAuthAuthorizationException | IOException e) {
    328             throw new OsmLoginFailedException(e);
    329         } finally {
    330             synchronized (this) {
    331                 connection = null;
    332             }
    333         }
    334     }
    335 
    336     protected void logoutOsmSession(SessionId sessionId) throws OsmOAuthAuthorizationException {
    337         try {
    338             URL url = new URL(oauthProviderParameters.getOsmLogoutUrl());
    339             synchronized (this) {
    340                 connection = HttpClient.create(url).setMaxRedirects(-1);
    341                 connection.connect();
    342             }
    343         } catch (IOException e) {
    344             throw new OsmOAuthAuthorizationException(e);
    345         } finally {
    346             synchronized (this) {
    347                 connection = null;
    348             }
    349         }
    350     }
    351 
    352     protected void sendAuthorisationRequest(SessionId sessionId, OAuthToken requestToken, OsmPrivileges privileges)
    353             throws OsmOAuthAuthorizationException {
    354         Map<String, String> parameters = new HashMap<>();
    355         fetchOAuthToken(sessionId, requestToken);
    356         parameters.put("oauth_token", requestToken.getKey());
    357         parameters.put("oauth_callback", "");
    358         parameters.put("authenticity_token", sessionId.token);
    359         parameters.put("allow_write_api", booleanParam(privileges.isAllowWriteApi()));
    360         parameters.put("allow_write_gpx", booleanParam(privileges.isAllowWriteGpx()));
    361         parameters.put("allow_read_gpx", booleanParam(privileges.isAllowReadGpx()));
    362         parameters.put("allow_write_prefs", booleanParam(privileges.isAllowWritePrefs()));
    363         parameters.put("allow_read_prefs", booleanParam(privileges.isAllowReadPrefs()));
    364         parameters.put("allow_write_notes", booleanParam(privileges.isAllowModifyNotes()));
    365         parameters.put("allow_write_diary", booleanParam(privileges.isAllowWriteDiary()));
    366 
    367         String request = buildPostRequest(parameters);
    368         try {
    369             URL url = new URL(oauthProviderParameters.getAuthoriseUrl());
    370             final HttpClient client = HttpClient.create(url, "POST").useCache(false);
    371             client.setHeader("Content-Type", "application/x-www-form-urlencoded");
    372             client.setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName);
    373             client.setMaxRedirects(-1);
    374             client.setRequestBody(request.getBytes(StandardCharsets.UTF_8));
    375 
    376             synchronized (this) {
    377                 connection = client;
    378                 connection.connect();
    379             }
    380 
    381             int retCode = connection.getResponse().getResponseCode();
    382             if (retCode != HttpURLConnection.HTTP_OK)
    383                 throw new OsmOAuthAuthorizationException(tr("Failed to authorize OAuth request  ''{0}''", requestToken.getKey()));
    384         } catch (IOException e) {
    385             throw new OsmOAuthAuthorizationException(e);
    386         } finally {
    387             synchronized (this) {
    388                 connection = null;
    389             }
    390         }
    391     }
    392 
    393     private static String booleanParam(boolean param) {
    394         return param ? "1" : "0";
    395     }
    396 
    397     /**
    398      * Automatically authorises a request token for a set of privileges.
    399      *
    400      * @param requestToken the request token. Must not be null.
    401      * @param userName the OSM user name. Must not be null.
    402      * @param password the OSM password. Must not be null.
    403      * @param privileges the set of privileges. Must not be null.
    404      * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
    405      * @throws IllegalArgumentException if requestToken is null
    406      * @throws IllegalArgumentException if osmUserName is null
    407      * @throws IllegalArgumentException if osmPassword is null
    408      * @throws IllegalArgumentException if privileges is null
    409      * @throws OsmOAuthAuthorizationException if the authorisation fails
    410      * @throws OsmTransferCanceledException if the task is canceled by the user
    411      */
    412     public void authorise(OAuthToken requestToken, String userName, String password, OsmPrivileges privileges, ProgressMonitor monitor)
    413             throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
    414         CheckParameterUtil.ensureParameterNotNull(requestToken, "requestToken");
    415         CheckParameterUtil.ensureParameterNotNull(userName, "userName");
    416         CheckParameterUtil.ensureParameterNotNull(password, "password");
    417         CheckParameterUtil.ensureParameterNotNull(privileges, "privileges");
    418 
    419         if (monitor == null) {
    420             monitor = NullProgressMonitor.INSTANCE;
    421         }
    422         try {
    423             monitor.beginTask(tr("Authorizing OAuth Request token ''{0}'' at the OSM website ...", requestToken.getKey()));
    424             monitor.setTicksCount(4);
    425             monitor.indeterminateSubTask(tr("Initializing a session at the OSM website..."));
    426             SessionId sessionId = fetchOsmWebsiteSessionId();
    427             sessionId.userName = userName;
    428             if (canceled)
    429                 throw new OsmTransferCanceledException("Authorization canceled");
    430             monitor.worked(1);
    431 
    432             monitor.indeterminateSubTask(tr("Authenticating the session for user ''{0}''...", userName));
    433             authenticateOsmSession(sessionId, userName, password);
    434             if (canceled)
    435                 throw new OsmTransferCanceledException("Authorization canceled");
    436             monitor.worked(1);
    437 
    438             monitor.indeterminateSubTask(tr("Authorizing request token ''{0}''...", requestToken.getKey()));
    439             sendAuthorisationRequest(sessionId, requestToken, privileges);
    440             if (canceled)
    441                 throw new OsmTransferCanceledException("Authorization canceled");
    442             monitor.worked(1);
    443 
    444             monitor.indeterminateSubTask(tr("Logging out session ''{0}''...", sessionId));
    445             logoutOsmSession(sessionId);
    446             if (canceled)
    447                 throw new OsmTransferCanceledException("Authorization canceled");
    448             monitor.worked(1);
    449         } catch (OsmOAuthAuthorizationException e) {
    450             if (canceled)
    451                 throw new OsmTransferCanceledException(e);
    452             throw e;
    453         } finally {
    454             monitor.finishTask();
    455         }
    456     }
    457 }
  • deleted file core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java

    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.awt.Component;
    7 import java.io.IOException;
    8 
    9 import javax.swing.JOptionPane;
    10 
    11 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    12 import org.openstreetmap.josm.data.oauth.OAuthToken;
    13 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    14 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    15 import org.openstreetmap.josm.gui.help.HelpUtil;
    16 import org.openstreetmap.josm.gui.util.GuiHelper;
    17 import org.openstreetmap.josm.io.OsmTransferCanceledException;
    18 import org.openstreetmap.josm.io.OsmTransferException;
    19 import org.openstreetmap.josm.tools.CheckParameterUtil;
    20 import org.openstreetmap.josm.tools.Logging;
    21 import org.xml.sax.SAXException;
    22 
    23 /**
    24  * Asynchronous task for retrieving an Access Token.
    25  *
    26  */
    27 public class RetrieveAccessTokenTask extends PleaseWaitRunnable {
    28 
    29     private boolean canceled;
    30     private OAuthToken accessToken;
    31     private final OAuthParameters parameters;
    32     private OsmOAuthAuthorizationClient client;
    33     private final OAuthToken requestToken;
    34     private final Component parent;
    35 
    36     /**
    37      * Creates the task
    38      *
    39      * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog
    40      * is displayed
    41      * @param parameters the OAuth parameters. Must not be null.
    42      * @param requestToken the request token for which an Access Token is retrieved. Must not be null.
    43      * @throws IllegalArgumentException if parameters is null.
    44      * @throws IllegalArgumentException if requestToken is null.
    45      */
    46     public RetrieveAccessTokenTask(Component parent, OAuthParameters parameters, OAuthToken requestToken) {
    47         super(parent, tr("Retrieving OAuth Access Token..."), false /* don't ignore exceptions */);
    48         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    49         CheckParameterUtil.ensureParameterNotNull(requestToken, "requestToken");
    50         this.parameters = parameters;
    51         this.requestToken = requestToken;
    52         this.parent = parent;
    53     }
    54 
    55     @Override
    56     protected void cancel() {
    57         canceled = true;
    58         synchronized (this) {
    59             if (client != null) {
    60                 client.cancel();
    61             }
    62         }
    63     }
    64 
    65     @Override
    66     protected void finish() { /* not used in this task */}
    67 
    68     protected void alertRetrievingAccessTokenFailed() {
    69         HelpAwareOptionPane.showOptionDialog(
    70                 parent,
    71                 tr(
    72                         "<html>Retrieving an OAuth Access Token from ''{0}'' failed.</html>",
    73                         parameters.getAccessTokenUrl()
    74                 ),
    75                 tr("Request Failed"),
    76                 JOptionPane.ERROR_MESSAGE,
    77                 HelpUtil.ht("/OAuth#NotAuthorizedException")
    78         );
    79     }
    80 
    81     @Override
    82     protected void realRun() throws SAXException, IOException, OsmTransferException {
    83         try {
    84             synchronized (this) {
    85                 client = new OsmOAuthAuthorizationClient(parameters, requestToken);
    86             }
    87             accessToken = client.getAccessToken(getProgressMonitor().createSubTaskMonitor(0, false));
    88         } catch (OsmTransferCanceledException e) {
    89             Logging.trace(e);
    90         } catch (final OsmOAuthAuthorizationException e) {
    91             Logging.error(e);
    92             GuiHelper.runInEDT(this::alertRetrievingAccessTokenFailed);
    93             accessToken = null;
    94         } finally {
    95             synchronized (this) {
    96                 client = null;
    97             }
    98         }
    99     }
    100 
    101     /**
    102      * Replies true if the task was canceled.
    103      *
    104      * @return {@code true} if user aborted operation
    105      */
    106     public boolean isCanceled() {
    107         return canceled;
    108     }
    109 
    110     /**
    111      * Replies the retrieved Access Token. null, if something went wrong.
    112      *
    113      * @return the retrieved Access Token
    114      */
    115     public OAuthToken getAccessToken() {
    116         return accessToken;
    117     }
    118 }
  • deleted file core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java

    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.awt.Component;
    7 import java.io.IOException;
    8 
    9 import javax.swing.JOptionPane;
    10 
    11 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    12 import org.openstreetmap.josm.data.oauth.OAuthToken;
    13 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    14 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    15 import org.openstreetmap.josm.gui.help.HelpUtil;
    16 import org.openstreetmap.josm.gui.util.GuiHelper;
    17 import org.openstreetmap.josm.io.OsmTransferCanceledException;
    18 import org.openstreetmap.josm.io.OsmTransferException;
    19 import org.openstreetmap.josm.tools.CheckParameterUtil;
    20 import org.openstreetmap.josm.tools.Logging;
    21 import org.xml.sax.SAXException;
    22 
    23 /**
    24  * Asynchronous task for retrieving a request token
    25  */
    26 public class RetrieveRequestTokenTask extends PleaseWaitRunnable {
    27 
    28     private boolean canceled;
    29     private OAuthToken requestToken;
    30     private final OAuthParameters parameters;
    31     private OsmOAuthAuthorizationClient client;
    32     private final Component parent;
    33 
    34     /**
    35      * Creates the task
    36      *
    37      * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog
    38      * is displayed
    39      * @param parameters the OAuth parameters. Must not be null.
    40      * @throws IllegalArgumentException if parameters is null.
    41      */
    42     public RetrieveRequestTokenTask(Component parent, OAuthParameters parameters) {
    43         super(parent, tr("Retrieving OAuth Request Token..."), false /* don't ignore exceptions */);
    44         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    45         this.parameters = parameters;
    46         this.parent = parent;
    47     }
    48 
    49     @Override
    50     protected void cancel() {
    51         canceled = true;
    52         synchronized (this) {
    53             if (client != null) {
    54                 client.cancel();
    55             }
    56         }
    57     }
    58 
    59     @Override
    60     protected void finish() { /* not used in this task */}
    61 
    62     protected void alertRetrievingRequestTokenFailed() {
    63         HelpAwareOptionPane.showOptionDialog(
    64                 parent,
    65                 tr(
    66                         "<html>Retrieving an OAuth Request Token from ''{0}'' failed.</html>",
    67                         parameters.getRequestTokenUrl()
    68                 ),
    69                 tr("Request Failed"),
    70                 JOptionPane.ERROR_MESSAGE,
    71                 HelpUtil.ht("/OAuth#NotAuthorizedException")
    72         );
    73     }
    74 
    75     @Override
    76     protected void realRun() throws SAXException, IOException, OsmTransferException {
    77         try {
    78             synchronized (this) {
    79                 client = new OsmOAuthAuthorizationClient(parameters);
    80             }
    81             requestToken = client.getRequestToken(getProgressMonitor().createSubTaskMonitor(0, false));
    82         } catch (OsmTransferCanceledException e) {
    83             Logging.trace(e);
    84         } catch (final OsmOAuthAuthorizationException e) {
    85             Logging.error(e);
    86             GuiHelper.runInEDT(this::alertRetrievingRequestTokenFailed);
    87             requestToken = null;
    88         } finally {
    89             synchronized (this) {
    90                 client = null;
    91             }
    92         }
    93     }
    94 
    95     /**
    96      * Replies true if the task was canceled
    97      *
    98      * @return true if the task was canceled
    99      */
    100     public boolean isCanceled() {
    101         return canceled;
    102     }
    103 
    104     /**
    105      * Replies the request token. null, if something went wrong.
    106      *
    107      * @return the request token
    108      */
    109     public OAuthToken getRequestToken() {
    110         return requestToken;
    111     }
    112 }
  • deleted file core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java

    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.awt.BorderLayout;
    7 import java.awt.Color;
    8 import java.awt.FlowLayout;
    9 import java.awt.Font;
    10 import java.awt.GridBagConstraints;
    11 import java.awt.GridBagLayout;
    12 import java.awt.Insets;
    13 import java.awt.event.ActionEvent;
    14 import java.awt.event.ItemEvent;
    15 import java.util.concurrent.Executor;
    16 
    17 import javax.swing.AbstractAction;
    18 import javax.swing.BorderFactory;
    19 import javax.swing.JButton;
    20 import javax.swing.JCheckBox;
    21 import javax.swing.JLabel;
    22 import javax.swing.JPanel;
    23 
    24 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    25 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    26 import org.openstreetmap.josm.data.oauth.OAuthToken;
    27 import org.openstreetmap.josm.gui.util.GuiHelper;
    28 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    29 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    30 import org.openstreetmap.josm.gui.widgets.JosmTextField;
    31 import org.openstreetmap.josm.tools.ImageProvider;
    32 import org.openstreetmap.josm.tools.OpenBrowser;
    33 
    34 /**
    35  * This is the UI for running a semi-automatic 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  */
    42 public 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                 (OAuthParameters) 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                     evt -> getAdvancedPropertiesPanel().setVisible(evt.getStateChange() == ItemEvent.SELECTED)
    146             );
    147 
    148             gc.gridx = 1;
    149             gc.weightx = 1.0;
    150             JMultilineLabel lbl = new JMultilineLabel(tr("Display Advanced OAuth Parameters"));
    151             lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
    152             pnl.add(lbl, gc);
    153 
    154             gc.gridy = 1;
    155             gc.gridx = 1;
    156             gc.insets = new Insets(3, 0, 3, 0);
    157             gc.fill = GridBagConstraints.BOTH;
    158             gc.weightx = 1.0;
    159             gc.weighty = 1.0;
    160             pnl.add(getAdvancedPropertiesPanel(), gc);
    161             getAdvancedPropertiesPanel().setBorder(
    162                     BorderFactory.createCompoundBorder(
    163                             BorderFactory.createLineBorder(Color.GRAY, 1),
    164                             BorderFactory.createEmptyBorder(3, 3, 3, 3)
    165                     )
    166             );
    167             getAdvancedPropertiesPanel().setVisible(false);
    168             return pnl;
    169         }
    170 
    171         protected JPanel buildCommandPanel() {
    172             JPanel pnl = new JPanel(new GridBagLayout());
    173             GridBagConstraints gc = new GridBagConstraints();
    174 
    175             gc.anchor = GridBagConstraints.NORTHWEST;
    176             gc.fill = GridBagConstraints.BOTH;
    177             gc.weightx = 1.0;
    178             gc.weighty = 1.0;
    179             gc.insets = new Insets(0, 0, 0, 3);
    180 
    181 
    182             HtmlPanel h = new HtmlPanel();
    183             h.setText(tr("<html>"
    184                     + "Please click on <strong>{0}</strong> to retrieve an OAuth Request Token from "
    185                     + "''{1}''.</html>",
    186                     tr("Retrieve Request Token"),
    187                     ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getRequestTokenUrl()
    188             ));
    189             pnl.add(h, gc);
    190 
    191             JPanel pnl1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
    192             pnl1.add(new JButton(new RetrieveRequestTokenAction()));
    193             gc.fill = GridBagConstraints.HORIZONTAL;
    194             gc.weightx = 1.0;
    195             gc.gridy = 1;
    196             pnl.add(pnl1, gc);
    197             return pnl;
    198 
    199         }
    200 
    201         protected final void build() {
    202             setLayout(new BorderLayout(0, 5));
    203             add(new StepLabel(tr("<html>Step 1/3: Retrieve an OAuth Request Token</html>")), BorderLayout.NORTH);
    204             add(buildAdvancedParametersPanel(), BorderLayout.CENTER);
    205             add(buildCommandPanel(), BorderLayout.SOUTH);
    206         }
    207     }
    208 
    209     /**
    210      * This is the panel displayed in the second step of the semi-automatic authorization process.
    211      */
    212     private class RetrieveAccessTokenPanel extends JPanel {
    213 
    214         private final JosmTextField tfAuthoriseUrl = new JosmTextField(null, null, 0, false);
    215 
    216         /**
    217          * Constructs a new {@code RetrieveAccessTokenPanel}.
    218          */
    219         RetrieveAccessTokenPanel() {
    220             build();
    221         }
    222 
    223         protected JPanel buildTitlePanel() {
    224             JPanel pnl = new JPanel(new BorderLayout());
    225             pnl.add(new StepLabel(tr("<html>Step 2/3: Authorize and retrieve an Access Token</html>")), BorderLayout.CENTER);
    226             return pnl;
    227         }
    228 
    229         protected JPanel buildContentPanel() {
    230             JPanel pnl = new JPanel(new GridBagLayout());
    231             GridBagConstraints gc = new GridBagConstraints();
    232 
    233             gc.anchor = GridBagConstraints.NORTHWEST;
    234             gc.fill = GridBagConstraints.HORIZONTAL;
    235             gc.weightx = 1.0;
    236             gc.gridwidth = 2;
    237             HtmlPanel html = new HtmlPanel();
    238             html.setText(tr("<html>"
    239                     + "JOSM successfully retrieved a Request Token. "
    240                     + "JOSM is now launching an authorization page in an external browser. "
    241                     + "Please login with your OSM username and password and follow the instructions "
    242                     + "to authorize the Request Token. Then switch back to this dialog and click on "
    243                     + "<strong>{0}</strong><br><br>"
    244                     + "If launching the external browser fails you can copy the following authorize URL "
    245                     + "and paste it into the address field of your browser.</html>",
    246                     tr("Request Access Token")
    247             ));
    248             pnl.add(html, gc);
    249 
    250             gc.gridx = 0;
    251             gc.gridy = 1;
    252             gc.weightx = 0.0;
    253             gc.gridwidth = 1;
    254             pnl.add(new JLabel(tr("Authorize URL:")), gc);
    255 
    256             gc.gridx = 1;
    257             gc.weightx = 1.0;
    258             pnl.add(tfAuthoriseUrl, gc);
    259             tfAuthoriseUrl.setEditable(false);
    260 
    261             return pnl;
    262         }
    263 
    264         protected JPanel buildActionPanel() {
    265             JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
    266             pnl.add(new JButton(new BackAction()));
    267             pnl.add(new JButton(new RetrieveAccessTokenAction()));
    268             return pnl;
    269         }
    270 
    271         protected final void build() {
    272             setLayout(new BorderLayout());
    273             add(buildTitlePanel(), BorderLayout.NORTH);
    274             add(buildContentPanel(), BorderLayout.CENTER);
    275             add(buildActionPanel(), BorderLayout.SOUTH);
    276         }
    277 
    278         public void setAuthoriseUrl(String url) {
    279             tfAuthoriseUrl.setText(url);
    280         }
    281 
    282         /**
    283          * Action to go back to step 1 in the process
    284          */
    285         class BackAction extends AbstractAction {
    286             BackAction() {
    287                 putValue(NAME, tr("Back"));
    288                 putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
    289                 new ImageProvider("dialogs", "previous").getResource().attachImageIcon(this);
    290             }
    291 
    292             @Override
    293             public void actionPerformed(ActionEvent arg0) {
    294                 transitionToRetrieveRequestToken();
    295             }
    296         }
    297     }
    298 
    299     /**
    300      * Displays the retrieved Access Token in step 3.
    301      */
    302     class ShowAccessTokenPanel extends JPanel {
    303 
    304         /**
    305          * Constructs a new {@code ShowAccessTokenPanel}.
    306          */
    307         ShowAccessTokenPanel() {
    308             build();
    309         }
    310 
    311         protected JPanel buildTitlePanel() {
    312             JPanel pnl = new JPanel(new BorderLayout());
    313             pnl.add(new StepLabel(tr("<html>Step 3/3: Successfully retrieved an Access Token</html>")), BorderLayout.CENTER);
    314             return pnl;
    315         }
    316 
    317         protected JPanel buildContentPanel() {
    318             JPanel pnl = new JPanel(new GridBagLayout());
    319             GridBagConstraints gc = new GridBagConstraints();
    320 
    321             gc.anchor = GridBagConstraints.NORTHWEST;
    322             gc.fill = GridBagConstraints.HORIZONTAL;
    323             gc.weightx = 1.0;
    324             HtmlPanel html = new HtmlPanel();
    325             html.setText(tr("<html>"
    326                     + "JOSM has successfully retrieved an Access Token. "
    327                     + "You can now accept this token. JOSM will use it in the future for authentication "
    328                     + "and authorization to the OSM server.<br><br>"
    329                     + "The access token is: </html>"
    330             ));
    331             pnl.add(html, gc);
    332 
    333             gc.gridx = 0;
    334             gc.gridy = 1;
    335             gc.weightx = 1.0;
    336             gc.gridwidth = 1;
    337             pnl.add(pnlAccessTokenInfo, gc);
    338             pnlAccessTokenInfo.setSaveToPreferences(
    339                     OAuthAccessTokenHolder.getInstance().isSaveToPreferences()
    340             );
    341             return pnl;
    342         }
    343 
    344         protected JPanel buildActionPanel() {
    345             JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
    346             pnl.add(new JButton(new RestartAction()));
    347             pnl.add(new JButton(new TestAccessTokenAction()));
    348             return pnl;
    349         }
    350 
    351         protected final void build() {
    352             setLayout(new BorderLayout());
    353             add(buildTitlePanel(), BorderLayout.NORTH);
    354             add(buildContentPanel(), BorderLayout.CENTER);
    355             add(buildActionPanel(), BorderLayout.SOUTH);
    356         }
    357 
    358         /**
    359          * Action to go back to step 1 in the process
    360          */
    361         class RestartAction extends AbstractAction {
    362             RestartAction() {
    363                 putValue(NAME, tr("Restart"));
    364                 putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
    365                 new ImageProvider("dialogs", "previous").getResource().attachImageIcon(this);
    366             }
    367 
    368             @Override
    369             public void actionPerformed(ActionEvent arg0) {
    370                 transitionToRetrieveRequestToken();
    371             }
    372         }
    373 
    374         public void setAccessToken(OAuthToken accessToken) {
    375             pnlAccessTokenInfo.setAccessToken(accessToken);
    376         }
    377     }
    378 
    379     /**
    380      * Action for retrieving a request token
    381      */
    382     class RetrieveRequestTokenAction extends AbstractAction {
    383 
    384         RetrieveRequestTokenAction() {
    385             putValue(NAME, tr("Retrieve Request Token"));
    386             new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
    387             putValue(SHORT_DESCRIPTION, tr("Click to retrieve a Request Token"));
    388         }
    389 
    390         @Override
    391         public void actionPerformed(ActionEvent evt) {
    392             final RetrieveRequestTokenTask task = new RetrieveRequestTokenTask(
    393                     SemiAutomaticAuthorizationUI.this,
    394                     (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()
    395             );
    396             executor.execute(task);
    397             Runnable r = () -> {
    398                 if (task.isCanceled()) return;
    399                 if (task.getRequestToken() == null) return;
    400                 requestToken = task.getRequestToken();
    401                 GuiHelper.runInEDT(SemiAutomaticAuthorizationUI.this::transitionToRetrieveAccessToken);
    402             };
    403             executor.execute(r);
    404         }
    405     }
    406 
    407     /**
    408      * Action for retrieving an Access Token
    409      */
    410     class RetrieveAccessTokenAction extends AbstractAction {
    411 
    412         RetrieveAccessTokenAction() {
    413             putValue(NAME, tr("Retrieve Access Token"));
    414             new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
    415             putValue(SHORT_DESCRIPTION, tr("Click to retrieve an Access Token"));
    416         }
    417 
    418         @Override
    419         public void actionPerformed(ActionEvent evt) {
    420             final RetrieveAccessTokenTask task = new RetrieveAccessTokenTask(
    421                     SemiAutomaticAuthorizationUI.this,
    422                     (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
    423                     requestToken
    424             );
    425             executor.execute(task);
    426             Runnable r = () -> {
    427                 if (task.isCanceled()) return;
    428                 if (task.getAccessToken() == null) return;
    429                 GuiHelper.runInEDT(() -> {
    430                     setAccessToken(task.getAccessToken());
    431                     transitionToShowAccessToken();
    432                 });
    433             };
    434             executor.execute(r);
    435         }
    436     }
    437 
    438     /**
    439      * Action for testing an Access Token
    440      */
    441     class TestAccessTokenAction extends AbstractAction {
    442 
    443         TestAccessTokenAction() {
    444             putValue(NAME, tr("Test Access Token"));
    445             new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
    446             putValue(SHORT_DESCRIPTION, tr("Click to test the Access Token"));
    447         }
    448 
    449         @Override
    450         public void actionPerformed(ActionEvent evt) {
    451             TestAccessTokenTask task = new TestAccessTokenTask(
    452                     SemiAutomaticAuthorizationUI.this,
    453                     getApiUrl(),
    454                     (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
    455                     getAccessToken()
    456             );
    457             executor.execute(task);
    458         }
    459     }
    460 }
  • core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
    a b  
    1414import org.openstreetmap.josm.data.oauth.IOAuthParameters;
    1515import org.openstreetmap.josm.data.oauth.IOAuthToken;
    1616import org.openstreetmap.josm.data.oauth.OAuth20Token;
    17 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    18 import org.openstreetmap.josm.data.oauth.OAuthToken;
     17import org.openstreetmap.josm.data.oauth.OAuthException;
    1918import org.openstreetmap.josm.data.osm.UserInfo;
    2019import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    2120import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     
    3332import org.w3c.dom.Document;
    3433import org.xml.sax.SAXException;
    3534
    36 import oauth.signpost.OAuthConsumer;
    37 import oauth.signpost.exception.OAuthException;
    38 
    3935/**
    4036 * Checks whether an OSM API server can be accessed with a specific Access Token.
    41  *
     37 * <p>
    4238 * It retrieves the user details for the user which is authorized to access the server with
    4339 * this token.
    4440 *
    4541 */
    4642public class TestAccessTokenTask extends PleaseWaitRunnable {
    47     private final OAuthToken tokenOAuth1;
    4843    private final IOAuthToken tokenOAuth2;
    49     private final IOAuthParameters oauthParameters;
    5044    private boolean canceled;
    5145    private final Component parent;
    5246    private final String apiUrl;
     
    5751     *
    5852     * @param parent the parent component relative to which the  {@link PleaseWaitRunnable}-Dialog is displayed
    5953     * @param apiUrl the API URL. Must not be null.
    60      * @param parameters the OAuth parameters. Must not be null.
    61      * @param accessToken the Access Token. Must not be null.
    62      */
    63     public TestAccessTokenTask(Component parent, String apiUrl, OAuthParameters parameters, OAuthToken accessToken) {
    64         super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */);
    65         CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");
    66         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    67         CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken");
    68         this.tokenOAuth1 = accessToken;
    69         this.tokenOAuth2 = null;
    70         this.oauthParameters = parameters;
    71         this.parent = parent;
    72         this.apiUrl = apiUrl;
    73     }
    74 
    75     /**
    76      * Create the task
    77      *
    78      * @param parent the parent component relative to which the  {@link PleaseWaitRunnable}-Dialog is displayed
    79      * @param apiUrl the API URL. Must not be null.
    80      * @param parameters the OAuth parameters. Must not be null.
    8154     * @param accessToken the Access Token. Must not be null.
    8255     * @since xxx
    8356     */
    84     public TestAccessTokenTask(Component parent, String apiUrl, IOAuthParameters parameters, IOAuthToken accessToken) {
     57    public TestAccessTokenTask(Component parent, String apiUrl, IOAuthToken accessToken) {
    8558        super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */);
    8659        CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");
    87         CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
    8860        CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken");
    89         this.tokenOAuth1 = null;
    9061        this.tokenOAuth2 = accessToken;
    91         this.oauthParameters = parameters;
    9262        this.parent = parent;
    9363        this.apiUrl = apiUrl;
    9464    }
     
    10979    }
    11080
    11181    protected void sign(HttpClient con) throws OAuthException {
    112         if (oauthParameters instanceof OAuthParameters) {
    113             OAuthConsumer consumer = ((OAuthParameters) oauthParameters).buildConsumer();
    114             consumer.setTokenWithSecret(tokenOAuth1.getKey(), tokenOAuth1.getSecret());
    115             consumer.sign(con);
    116         } else {
    117             try {
    118                 this.tokenOAuth2.sign(con);
    119             } catch (org.openstreetmap.josm.data.oauth.OAuthException e) {
    120                 // Adapt our OAuthException to the SignPost OAuth exception
    121                 throw new OAuthException(e) {};
    122             }
    123         }
     82        this.tokenOAuth2.sign(con);
    12483    }
    12584
    12685    protected String normalizeApiUrl(String url) {
     
    314273    }
    315274
    316275    private String getAuthKey() {
    317         if (this.tokenOAuth1 != null) {
    318             return this.tokenOAuth1.getKey();
    319         }
    320276        if (this.tokenOAuth2 instanceof OAuth20Token) {
    321277            return ((OAuth20Token) this.tokenOAuth2).getBearerToken();
    322278        }
    323         throw new IllegalArgumentException("Only OAuth1 and OAuth2 tokens are understood: " + this.tokenOAuth2);
     279        throw new IllegalArgumentException("Only OAuth2 tokens are understood: " + this.tokenOAuth2);
    324280    }
    325281}
  • core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java b/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java
    a b  
    1818import javax.swing.JRadioButton;
    1919
    2020import org.openstreetmap.josm.data.UserIdentityManager;
    21 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    2221import org.openstreetmap.josm.data.oauth.OAuthVersion;
    2322import org.openstreetmap.josm.gui.help.HelpUtil;
    2423import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
    2524import org.openstreetmap.josm.io.OsmApi;
    26 import org.openstreetmap.josm.io.auth.CredentialsManager;
    2725import org.openstreetmap.josm.spi.preferences.Config;
    2826import org.openstreetmap.josm.tools.GBC;
    2927import org.openstreetmap.josm.tools.Logging;
     
    3331 * @since 2745
    3432 */
    3533public class AuthenticationPreferencesPanel extends VerticallyScrollablePanel implements PropertyChangeListener {
    36 
    37     /** indicates whether we use basic authentication */
    38     private final JRadioButton rbBasicAuthentication = new JRadioButton();
    39     /** indicates whether we use OAuth 1.0a as authentication scheme */
    40     private final JRadioButton rbOAuth = new JRadioButton();
    4134    /** indicates whether we use OAuth 2.0 as authentication scheme */
    4235    private final JRadioButton rbOAuth20 = new JRadioButton();
    4336    /** the panel which contains the authentication parameters for the respective authentication scheme */
    4437    private final JPanel pnlAuthenticationParameters = new JPanel(new BorderLayout());
    45     /** the panel for the basic authentication parameters */
    46     private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences;
    47     /** the panel for the OAuth 1.0a authentication parameters */
    48     private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;
    4938    /** the panel for the OAuth 2.0 authentication parameters */
    5039    private OAuthAuthenticationPreferencesPanel pnlOAuth20Preferences;
    5140
     
    6756        AuthenticationMethodChangeListener authChangeListener = new AuthenticationMethodChangeListener();
    6857
    6958        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
    70         // -- radio button for basic authentication
    71         buttonPanel.add(rbBasicAuthentication);
    72         rbBasicAuthentication.setText(tr("Use Basic Authentication"));
    73         rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password"));
    74         rbBasicAuthentication.addItemListener(authChangeListener);
    75 
    76         //-- radio button for OAuth 1.0a
    77         buttonPanel.add(rbOAuth);
    78         rbOAuth.setText(tr("Use OAuth {0}", "1.0a"));
    79         rbOAuth.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "1.0a"));
    80         rbOAuth.addItemListener(authChangeListener);
    81 
    8259        //-- radio button for OAuth 2.0
    8360        buttonPanel.add(rbOAuth20);
    8461        rbOAuth20.setText(tr("Use OAuth {0}", "2.0"));
     
    8865        add(buttonPanel, GBC.eol());
    8966        //-- radio button for OAuth
    9067        ButtonGroup bg = new ButtonGroup();
    91         bg.add(rbBasicAuthentication);
    92         bg.add(rbOAuth);
    9368        bg.add(rbOAuth20);
    9469
    9570        //-- add the panel which will hold the authentication parameters
     
    10479        gc.weighty = 1.0;
    10580        add(pnlAuthenticationParameters, gc);
    10681
    107         //-- the two panels for authentication parameters
    108         pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel();
    109         pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth10a);
     82        //-- the panels for authentication parameters
    11083        pnlOAuth20Preferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth20);
    11184
    112         rbBasicAuthentication.setSelected(true);
    113         pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
     85        rbOAuth20.setSelected(true);
     86        pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER);
    11487    }
    11588
    11689    /**
     
    11891     */
    11992    public final void initFromPreferences() {
    12093        final String authMethod = OsmApi.getAuthMethod();
    121         switch (authMethod) {
    122             case "basic":
    123                 rbBasicAuthentication.setSelected(true);
    124                 break;
    125             case "oauth":
    126                 rbOAuth.setSelected(true);
    127                 break;
    128             case "oauth20":
    129                 rbOAuth20.setSelected(true);
    130                 break;
    131             default:
    132                 Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.",
    133                         "osm-server.auth-method", authMethod));
    134                 rbBasicAuthentication.setSelected(true);
     94        if ("oauth20".equals(authMethod)) {
     95            rbOAuth20.setSelected(true);
     96        } else {
     97            Logging.warn(
     98                    tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''OAuth 2.0 Authentication''.",
     99                            "osm-server.auth-method", authMethod));
     100            rbOAuth20.setSelected(true);
    135101        }
    136         pnlBasicAuthPreferences.initFromPreferences();
    137         pnlOAuthPreferences.initFromPreferences();
    138102        pnlOAuth20Preferences.initFromPreferences();
    139103    }
    140104
     
    144108    public final void saveToPreferences() {
    145109        // save the authentication method
    146110        String authMethod;
    147         if (rbBasicAuthentication.isSelected()) {
    148             authMethod = "basic";
    149         } else if (rbOAuth.isSelected()) {
    150             authMethod = "oauth";
    151         } else if (rbOAuth20.isSelected()) {
     111        if (rbOAuth20.isSelected()) {
    152112            authMethod = "oauth20";
    153113        } else {
    154114            throw new IllegalStateException("One of OAuth 2.0, OAuth 1.0a, or Basic authentication must be checked");
    155115        }
    156116        final boolean initUser = Config.getPref().put("osm-server.auth-method", authMethod);
    157         if ("basic".equals(authMethod)) {
    158             // save username and password and clear the OAuth token
    159             pnlBasicAuthPreferences.saveToPreferences();
    160             OAuthAccessTokenHolder.getInstance().clear();
    161             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    162         } else if ("oauth".equals(authMethod)) {
    163             // clear the password in the preferences
    164             pnlBasicAuthPreferences.clearPassword();
    165             pnlBasicAuthPreferences.saveToPreferences();
    166             pnlOAuthPreferences.saveToPreferences();
    167         } else { // oauth20
    168             // clear the password in the preferences
    169             pnlBasicAuthPreferences.clearPassword();
    170             pnlBasicAuthPreferences.saveToPreferences();
    171             pnlOAuth20Preferences.saveToPreferences();
    172         }
     117        // oauth20
     118        pnlOAuth20Preferences.saveToPreferences();
    173119        if (initUser) {
    174             if ("basic".equals(authMethod)) {
    175                 UserIdentityManager.getInstance().initFromPreferences();
     120            if (OsmApi.isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())) {
     121                UserIdentityManager.getInstance().initFromOAuth();
    176122            } else {
    177                 UserIdentityManager.getInstance().initFromOAuth();
     123                UserIdentityManager.getInstance().setAnonymous();
    178124            }
    179125        }
    180126    }
     
    186132        @Override
    187133        public void itemStateChanged(ItemEvent e) {
    188134            pnlAuthenticationParameters.removeAll();
    189             if (rbBasicAuthentication.isSelected()) {
    190                 pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
    191                 pnlBasicAuthPreferences.revalidate();
    192             } else if (rbOAuth.isSelected()) {
    193                 pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER);
    194                 pnlOAuthPreferences.saveToPreferences();
    195                 pnlOAuthPreferences.initFromPreferences();
    196                 pnlOAuthPreferences.revalidate();
    197             } else if (rbOAuth20.isSelected()) {
     135            if (rbOAuth20.isSelected()) {
    198136                pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER);
    199137                pnlOAuth20Preferences.saveToPreferences();
    200138                pnlOAuth20Preferences.initFromPreferences();
     
    206144
    207145    @Override
    208146    public void propertyChange(PropertyChangeEvent evt) {
    209         if (pnlOAuthPreferences != null) {
    210             pnlOAuthPreferences.propertyChange(evt);
     147        if (pnlOAuth20Preferences != null) {
     148            pnlOAuth20Preferences.propertyChange(evt);
    211149        }
    212150    }
    213151}
  • deleted file core/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java

    diff --git a/core/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java b/core/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.preferences.server;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.awt.BorderLayout;
    7 import java.awt.GridBagConstraints;
    8 import java.awt.GridBagLayout;
    9 import java.awt.Insets;
    10 import java.net.Authenticator.RequestorType;
    11 import java.net.PasswordAuthentication;
    12 
    13 import javax.swing.BorderFactory;
    14 import javax.swing.JLabel;
    15 import javax.swing.JPanel;
    16 
    17 import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
    18 import org.openstreetmap.josm.gui.widgets.JosmTextField;
    19 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
    20 import org.openstreetmap.josm.io.OsmApi;
    21 import org.openstreetmap.josm.io.auth.CredentialsAgent;
    22 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
    23 import org.openstreetmap.josm.io.auth.CredentialsManager;
    24 import org.openstreetmap.josm.tools.Logging;
    25 
    26 /**
    27  * The preferences panel for parameters necessary for the Basic Authentication Scheme.
    28  * @since 2745
    29  */
    30 public class BasicAuthenticationPreferencesPanel extends JPanel {
    31 
    32     /** the OSM user name */
    33     private final JosmTextField tfOsmUserName = new JosmTextField();
    34     /** the OSM password */
    35     private final JosmPasswordField tfOsmPassword = new JosmPasswordField();
    36     /** a panel with further information, e.g. some warnings */
    37     private JPanel decorationPanel;
    38 
    39     /**
    40      * Constructs a new {@code BasicAuthenticationPreferencesPanel}.
    41      */
    42     public BasicAuthenticationPreferencesPanel() {
    43         build();
    44     }
    45 
    46     /**
    47      * builds the UI
    48      */
    49     protected final void build() {
    50         setLayout(new GridBagLayout());
    51         setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    52         GridBagConstraints gc = new GridBagConstraints();
    53 
    54         // -- OSM user name
    55         gc.fill = GridBagConstraints.HORIZONTAL;
    56         gc.anchor = GridBagConstraints.NORTHWEST;
    57         gc.weightx = 0.0;
    58         gc.insets = new Insets(0, 0, 3, 3);
    59         add(new JLabel(tr("OSM username:")), gc);
    60 
    61         gc.gridx = 1;
    62         gc.weightx = 1.0;
    63         add(tfOsmUserName, gc);
    64         SelectAllOnFocusGainedDecorator.decorate(tfOsmUserName);
    65         UserNameValidator valUserName = new UserNameValidator(tfOsmUserName);
    66         valUserName.validate();
    67 
    68         // -- OSM password
    69         gc.gridx = 0;
    70         gc.gridy = 1;
    71         gc.weightx = 0.0;
    72         add(new JLabel(tr("OSM password:")), gc);
    73 
    74         gc.gridx = 1;
    75         gc.weightx = 1.0;
    76         add(tfOsmPassword, gc);
    77         SelectAllOnFocusGainedDecorator.decorate(tfOsmPassword);
    78         tfOsmPassword.setToolTipText(tr("Please enter your OSM password"));
    79 
    80         // -- an info panel with a warning message
    81         gc.gridx = 0;
    82         gc.gridy = 2;
    83         gc.gridwidth = 2;
    84         gc.weightx = 1.0;
    85         gc.weighty = 1.0;
    86         gc.insets = new Insets(5, 0, 0, 0);
    87         gc.fill = GridBagConstraints.BOTH;
    88         decorationPanel = new JPanel(new BorderLayout());
    89         add(decorationPanel, gc);
    90     }
    91 
    92     /**
    93      * Inits contents from preferences.
    94      */
    95     public void initFromPreferences() {
    96         CredentialsAgent cm = CredentialsManager.getInstance();
    97         try {
    98             decorationPanel.removeAll();
    99             decorationPanel.add(cm.getPreferencesDecorationPanel(), BorderLayout.CENTER);
    100             PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());
    101             if (pa == null) {
    102                 tfOsmUserName.setText("");
    103                 tfOsmPassword.setText("");
    104             } else {
    105                 tfOsmUserName.setText(pa.getUserName() == null ? "" : pa.getUserName());
    106                 tfOsmPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
    107             }
    108         } catch (CredentialsAgentException e) {
    109             Logging.error(e);
    110             Logging.warn(tr("Failed to retrieve OSM credentials from credential manager."));
    111             Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    112             tfOsmUserName.setText("");
    113             tfOsmPassword.setText("");
    114         }
    115     }
    116 
    117     /**
    118      * Saves contents to preferences.
    119      */
    120     public void saveToPreferences() {
    121         CredentialsAgent cm = CredentialsManager.getInstance();
    122         try {
    123             PasswordAuthentication pa = new PasswordAuthentication(
    124                     tfOsmUserName.getText().trim(),
    125                     tfOsmPassword.getPassword()
    126             );
    127             cm.store(RequestorType.SERVER, OsmApi.getOsmApi().getHost(), pa);
    128         } catch (CredentialsAgentException e) {
    129             Logging.error(e);
    130             Logging.warn(tr("Failed to save OSM credentials to credential manager."));
    131             Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    132         }
    133     }
    134 
    135     /**
    136      * Clears the password field.
    137      */
    138     public void clearPassword() {
    139         tfOsmPassword.setText("");
    140     }
    141 }
  • core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java b/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java
    a b  
    55
    66import java.awt.BorderLayout;
    77import java.awt.Color;
     8import java.awt.Component;
    89import java.awt.FlowLayout;
    910import java.awt.Font;
    1011import java.awt.GridBagConstraints;
     
    1415import java.awt.event.ItemEvent;
    1516import java.beans.PropertyChangeEvent;
    1617import java.beans.PropertyChangeListener;
     18import java.util.Arrays;
     19import java.util.Objects;
    1720
    1821import javax.swing.AbstractAction;
    1922import javax.swing.BorderFactory;
    2023import javax.swing.JButton;
    2124import javax.swing.JCheckBox;
    2225import javax.swing.JLabel;
    23 import javax.swing.JOptionPane;
    2426import javax.swing.JPanel;
    2527
    2628import org.openstreetmap.josm.actions.ExpertToggleAction;
    2729import org.openstreetmap.josm.data.oauth.IOAuthToken;
    28 import org.openstreetmap.josm.data.oauth.OAuth20Authorization;
    2930import org.openstreetmap.josm.data.oauth.OAuth20Token;
    3031import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    3132import org.openstreetmap.josm.data.oauth.OAuthParameters;
    32 import org.openstreetmap.josm.data.oauth.OAuthToken;
    3333import org.openstreetmap.josm.data.oauth.OAuthVersion;
    34 import org.openstreetmap.josm.data.oauth.osm.OsmScopes;
    3534import org.openstreetmap.josm.gui.MainApplication;
    3635import org.openstreetmap.josm.gui.oauth.AdvancedOAuthPropertiesPanel;
    3736import org.openstreetmap.josm.gui.oauth.AuthorizationProcedure;
     
    4241import org.openstreetmap.josm.gui.widgets.JosmTextField;
    4342import org.openstreetmap.josm.io.OsmApi;
    4443import org.openstreetmap.josm.io.auth.CredentialsManager;
    45 import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
    4644import org.openstreetmap.josm.tools.GBC;
    4745import org.openstreetmap.josm.tools.ImageProvider;
    4846import org.openstreetmap.josm.tools.Logging;
    4947import org.openstreetmap.josm.tools.UserCancelException;
     48import org.openstreetmap.josm.tools.Utils;
    5049
    5150/**
    5251 * The preferences panel for the OAuth 1.0a preferences. This just a summary panel
     
    6766    private final OAuthVersion oAuthVersion;
    6867    private String apiUrl;
    6968
    70     /**
    71      * Create the panel. Uses {@link OAuthVersion#OAuth10a}.
    72      */
    73     public OAuthAuthenticationPreferencesPanel() {
    74         this(OAuthVersion.OAuth10a);
    75     }
    76 
    7769    /**
    7870     * Create the panel.
    7971     * @param oAuthVersion The OAuth version to use
     
    138130
    139131    protected void refreshView() {
    140132        pnlAuthorisationMessage.removeAll();
    141         if ((this.oAuthVersion == OAuthVersion.OAuth10a &&
    142                 OAuthAccessTokenHolder.getInstance().containsAccessToken())
    143         || OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) {
     133        if (OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) {
    144134            pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER);
    145135            pnlAlreadyAuthorised.refreshView();
    146136            pnlAlreadyAuthorised.revalidate();
     
    159149    public void setApiUrl(String apiUrl) {
    160150        this.apiUrl = apiUrl;
    161151        pnlAdvancedProperties.setApiUrl(apiUrl);
     152        for (JPanel panel : Arrays.asList(this.pnlNotYetAuthorised, (JPanel) this.pnlAlreadyAuthorised.getComponent(6))) {
     153            for (Component component : panel.getComponents()) {
     154                if (component instanceof JButton && ((JButton) component).getAction() instanceof AuthoriseNowAction) {
     155                    ((AuthoriseNowAction) ((JButton) component).getAction()).updateEnabledState();
     156                }
     157            }
     158        }
    162159    }
    163160
    164161    /**
     
    203200            lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
    204201
    205202            // Action for authorising now
    206             if (oAuthVersion == OAuthVersion.OAuth10a) {
    207                 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol());
    208             }
    209             add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.SEMI_AUTOMATIC)), GBC.eol());
    210             if (oAuthVersion == OAuthVersion.OAuth10a) {
    211                 JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY));
    212                 add(authManually, GBC.eol());
    213                 ExpertToggleAction.addVisibilitySwitcher(authManually);
    214             }
     203            add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol());
     204            JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY));
     205            add(authManually, GBC.eol());
     206            ExpertToggleAction.addVisibilitySwitcher(authManually);
    215207
    216208            // filler - grab remaining space
    217209            add(new JPanel(), GBC.std().fill(GBC.BOTH));
     
    224216     */
    225217    private class AlreadyAuthorisedPanel extends JPanel {
    226218        private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
    227         private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
    228219
    229220        /**
    230221         * Constructs a new {@code AlreadyAuthorisedPanel}.
     
    265256            gc.weightx = 0.0;
    266257            add(new JLabel(tr("Access Token Secret:")), gc);
    267258
    268             gc.gridx = 1;
    269             gc.weightx = 1.0;
    270             add(tfAccessTokenSecret, gc);
    271             tfAccessTokenSecret.setEditable(false);
    272 
    273259            // -- access token secret
    274260            gc.gridy = 3;
    275261            gc.gridx = 0;
     
    280266
    281267            // -- action buttons
    282268            JPanel btns = new JPanel(new FlowLayout(FlowLayout.LEFT));
    283             if (oAuthVersion == OAuthVersion.OAuth10a) {
    284                 // these want the OAuth 1.0 token information
    285                 btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC)));
    286             }
    287             btns.add(new JButton(new TestAuthorisationAction(oAuthVersion)));
     269            btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC)));
     270            btns.add(new JButton(new TestAuthorisationAction()));
    288271            btns.add(new JButton(new RemoveAuthorisationAction()));
    289272            gc.gridy = 4;
    290273            gc.gridx = 0;
     
    309292
    310293        protected final void refreshView() {
    311294            switch (oAuthVersion) {
    312                 case OAuth10a:
    313                     String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey();
    314                     tfAccessTokenKey.setText(v == null ? "" : v);
    315                     v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret();
    316                     tfAccessTokenSecret.setText(v == null ? "" : v);
    317                     tfAccessTokenSecret.setVisible(true);
    318                     break;
    319295                case OAuth20:
    320296                case OAuth21:
    321297                    String token = "";
     
    324300                        token = bearerToken == null ? "" : bearerToken.getBearerToken();
    325301                    }
    326302                    tfAccessTokenKey.setText(token == null ? "" : token);
    327                     tfAccessTokenSecret.setVisible(false);
     303                    break;
     304                default:
    328305            }
    329306            cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences());
    330307        }
     
    340317            this.procedure = procedure;
    341318            putValue(NAME, tr("{0} ({1})", tr("Authorize now"), procedure.getText()));
    342319            putValue(SHORT_DESCRIPTION, procedure.getDescription());
    343             if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC
    344             || OAuthAuthenticationPreferencesPanel.this.oAuthVersion != OAuthVersion.OAuth10a) {
     320            if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC) {
    345321                new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
    346322            }
     323            updateEnabledState();
     324        }
     325
     326        void updateEnabledState() {
     327            if (procedure == AuthorizationProcedure.MANUALLY) {
     328                this.setEnabled(true);
     329            } else {
     330                final String currentApiUrl = apiUrl;
     331                MainApplication.worker.execute(() -> {
     332                    final String clientId = OAuthParameters.createDefault(apiUrl, oAuthVersion).getClientId();
     333                    if (Objects.equals(apiUrl, currentApiUrl)) {
     334                        GuiHelper.runInEDT(() -> this.setEnabled(!Utils.isEmpty(clientId)));
     335                    }
     336                });
     337            }
    347338        }
    348339
    349340        @Override
    350341        public void actionPerformed(ActionEvent arg0) {
    351             if (OAuthAuthenticationPreferencesPanel.this.oAuthVersion == OAuthVersion.OAuth10a) {
    352                 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
    353                         OAuthAuthenticationPreferencesPanel.this,
    354                         procedure,
    355                         apiUrl,
    356                         MainApplication.worker);
    357                 try {
    358                     wizard.showDialog();
    359                 } catch (UserCancelException ignore) {
    360                     Logging.trace(ignore);
    361                     return;
    362                 }
    363                 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
    364                 refreshView();
    365             } else {
    366                 final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get());
    367                 // TODO: Ask user if they want to start remote control?
    368                 if (!remoteControlIsRunning) {
    369                     RemoteControl.start();
    370                 }
    371                 new OAuth20Authorization().authorize(OAuthParameters.createDefault(OsmApi.getOsmApi().getServerUrl(), oAuthVersion), token -> {
    372                     if (!remoteControlIsRunning) {
    373                         RemoteControl.stop();
    374                     }
    375                     OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), token.orElse(null));
    376                     OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    377                     GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView);
    378                     if (!token.isPresent()) {
    379                         GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(),
    380                                 tr("Authentication failed, please check browser for details."),
    381                                 tr("OAuth Authentication Failed"),
    382                                 JOptionPane.ERROR_MESSAGE));
    383                     }
    384                 }, OsmScopes.read_gpx, OsmScopes.write_gpx,
    385                         OsmScopes.read_prefs, OsmScopes.write_prefs,
    386                         OsmScopes.write_api, OsmScopes.write_notes);
    387             }
     342            OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
     343                    OAuthAuthenticationPreferencesPanel.this,
     344                    procedure,
     345                    apiUrl,
     346                    MainApplication.worker,
     347                    oAuthVersion);
     348            try {
     349                wizard.showDialog(token -> GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView));
     350            } catch (UserCancelException userCancelException) {
     351                Logging.trace(userCancelException);
     352                return;
     353            }
     354            pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
     355            refreshView();
    388356        }
    389357    }
    390358
     
    400368
    401369        @Override
    402370        public void actionPerformed(ActionEvent e) {
    403             if (oAuthVersion == OAuthVersion.OAuth10a) {
    404                 OAuthAccessTokenHolder.getInstance().setAccessToken(null);
    405             } else {
    406                 OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, (IOAuthToken) null);
    407             }
     371            OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, null);
    408372            OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    409373            refreshView();
    410374        }
     
    429393     * Runs a test whether we can access the OSM server with the current Access Token
    430394     */
    431395    private class TestAuthorisationAction extends AbstractAction {
    432         private final OAuthVersion oAuthVersion;
    433 
    434396        /**
    435397         * Constructs a new {@code TestAuthorisationAction}.
    436398         */
    437         TestAuthorisationAction(OAuthVersion oAuthVersion) {
    438             this.oAuthVersion = oAuthVersion;
     399        TestAuthorisationAction() {
    439400            putValue(NAME, tr("Test Access Token"));
    440401            putValue(SHORT_DESCRIPTION, tr("Click test access to the OSM server with the current access token"));
    441402            new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
     
    443404
    444405        @Override
    445406        public void actionPerformed(ActionEvent evt) {
    446             if (this.oAuthVersion == OAuthVersion.OAuth10a) {
    447                 OAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken();
    448                 OAuthParameters parameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
    449                 TestAccessTokenTask task = new TestAccessTokenTask(
    450                         OAuthAuthenticationPreferencesPanel.this,
    451                         apiUrl,
    452                         parameters,
    453                         token
    454                 );
    455                 MainApplication.worker.submit(task);
    456             } else {
    457                 IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
    458                 TestAccessTokenTask task = new TestAccessTokenTask(
    459                         OAuthAuthenticationPreferencesPanel.this,
    460                         apiUrl,
    461                         token.getParameters(),
    462                         token
    463                 );
    464                 MainApplication.worker.submit(task);
    465             }
     407            IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
     408            TestAccessTokenTask task = new TestAccessTokenTask(
     409                    OAuthAuthenticationPreferencesPanel.this,
     410                    apiUrl,
     411                    token
     412            );
     413            MainApplication.worker.submit(task);
    466414        }
    467415    }
    468416
  • core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java b/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
    a b  
    88import javax.annotation.Nullable;
    99
    1010import org.openstreetmap.josm.data.oauth.IOAuthToken;
    11 import org.openstreetmap.josm.data.oauth.OAuthToken;
    1211
    1312/**
    1413 * A CredentialsAgent manages two credentials:
     
    6463     *
    6564     * @return the current OAuth Access Token to access the OSM server.
    6665     * @throws CredentialsAgentException if something goes wrong
     66     * @deprecated since xxx -- OAuth 1.0 is being removed from the OSM API
    6767     */
    68     OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException;
     68    @Deprecated
     69    default IOAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
     70        throw new CredentialsAgentException("Call to deprecated method");
     71    }
    6972
    7073    /**
    7174     * Lookup the current OAuth Access Token to access the specified server. Replies null, if no
     
    8487     *
    8588     * @param accessToken the access Token. null, to remove the Access Token.
    8689     * @throws CredentialsAgentException if something goes wrong
     90     * @deprecated since xxx -- OAuth 1.0 is being removed from the OSM API
    8791     */
    88     void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException;
     92    @Deprecated
     93    default void storeOAuthAccessToken(IOAuthToken accessToken) throws CredentialsAgentException {
     94        throw new CredentialsAgentException("Call to deprecated method");
     95    }
    8996
    9097    /**
    9198     * Stores the OAuth Access Token <code>accessToken</code>.
    9299     *
    93100     * @param host The host the access token is for
    94101     * @param accessToken the access Token. null, to remove the Access Token. This will remove all IOAuthTokens <i>not</i> managed by
    95      *                    {@link #storeOAuthAccessToken(OAuthToken)}.
     102     *                    {@link #storeOAuthAccessToken(IOAuthToken)}.
    96103     * @throws CredentialsAgentException if something goes wrong
    97104     * @since 18650
    98105     */
  • core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java b/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
    a b  
    88
    99import org.openstreetmap.josm.data.UserIdentityManager;
    1010import org.openstreetmap.josm.data.oauth.IOAuthToken;
    11 import org.openstreetmap.josm.data.oauth.OAuthToken;
    1211import org.openstreetmap.josm.io.OsmApi;
    1312import org.openstreetmap.josm.tools.CheckParameterUtil;
    1413import org.openstreetmap.josm.tools.Logging;
     
    1615
    1716/**
    1817 * CredentialManager is a factory for the single credential agent used.
    19  *
     18 * <p>
    2019 * Currently, it defaults to replying an instance of {@link JosmPreferencesCredentialAgent}.
    2120 * @since 2641
    2221 */
     
    156155        return credentials;
    157156    }
    158157
    159     @Override
    160     public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
    161         return delegate.lookupOAuthAccessToken();
    162     }
    163 
    164158    @Override
    165159    public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
    166160        return delegate.lookupOAuthAccessToken(host);
    167161    }
    168162
    169     @Override
    170     public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
    171         delegate.storeOAuthAccessToken(accessToken);
    172     }
    173 
    174163    @Override
    175164    public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException {
    176165        delegate.storeOAuthAccessToken(host, accessToken);
  • core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java b/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
    a b  
    1717import org.openstreetmap.josm.data.oauth.OAuth20Exception;
    1818import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    1919import org.openstreetmap.josm.data.oauth.OAuth20Token;
    20 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2120import org.openstreetmap.josm.data.oauth.OAuthVersion;
    2221import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    2322import org.openstreetmap.josm.io.DefaultProxySelector;
     
    102101        }
    103102    }
    104103
    105     /**
    106      * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
    107      * Access Token is currently managed by this CredentialManager.
    108      *
    109      * @return the current OAuth Access Token to access the OSM server.
    110      * @throws CredentialsAgentException if something goes wrong
    111      */
    112     @Override
    113     public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
    114         String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);
    115         String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);
    116         if (accessTokenKey == null && accessTokenSecret == null)
    117             return null;
    118         return new OAuthToken(accessTokenKey, accessTokenSecret);
    119     }
    120 
    121104    @Override
    122105    public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
    123106        Set<String> keySet = new HashSet<>(Config.getPref().getKeySet());
     
    142125        return null;
    143126    }
    144127
    145     /**
    146      * Stores the OAuth Access Token <code>accessToken</code>.
    147      *
    148      * @param accessToken the access Token. null, to remove the Access Token.
    149      * @throws CredentialsAgentException if something goes wrong
    150      */
    151     @Override
    152     public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
    153         if (accessToken == null) {
    154             Config.getPref().put("oauth.access-token.key", null);
    155             Config.getPref().put("oauth.access-token.secret", null);
    156         } else {
    157             Config.getPref().put("oauth.access-token.key", accessToken.getKey());
    158             Config.getPref().put("oauth.access-token.secret", accessToken.getSecret());
    159         }
    160     }
    161 
    162128    @Override
    163129    public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException {
    164130        Objects.requireNonNull(host, "host");
  • core/src/org/openstreetmap/josm/io/MessageNotifier.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/MessageNotifier.java b/core/src/org/openstreetmap/josm/io/MessageNotifier.java
    a b  
    144144            CredentialsManager credManager = CredentialsManager.getInstance();
    145145            try {
    146146                if (JosmPreferencesCredentialAgent.class.equals(credManager.getCredentialsAgentClass())) {
    147                     if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) {
    148                         return credManager.lookupOAuthAccessToken() != null;
    149                     } else if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) {
     147                    if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) {
    150148                        return credManager.lookupOAuthAccessToken(OsmApi.getOsmApi().getHost()) != null;
    151149                    } else if (OsmApi.isUsingOAuth()) {
    152150                        // Ensure we do not forget to update this section
  • core/src/org/openstreetmap/josm/io/NetworkManager.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/NetworkManager.java b/core/src/org/openstreetmap/josm/io/NetworkManager.java
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.io;
    33
     4import java.net.URI;
    45import java.net.URL;
    56import java.util.Collections;
    67import java.util.EnumSet;
     
    5758        }
    5859        return null;
    5960    }
     61
     62    /**
     63     * Adds a new network error that occur to give a hint about broken Internet connection.
     64     * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
     65     *
     66     * @param url The accessed URL that caused the error
     67     * @param t The network error
     68     * @return The previous error associated to the given resource, if any. Can be {@code null}
     69     * @since xxx
     70     */
     71    public static Throwable addNetworkError(URI url, Throwable t) {
     72        if (url != null && t != null) {
     73            Throwable old = addNetworkError(url.toString(), t);
     74            if (old != null) {
     75                Logging.warn("Already here "+old);
     76            }
     77            return old;
     78        }
     79        return null;
     80    }
    6081
    6182    /**
    6283     * Returns the network errors that occurred until now.
  • core/src/org/openstreetmap/josm/io/OsmApi.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/OsmApi.java b/core/src/org/openstreetmap/josm/io/OsmApi.java
    a b  
    1111import java.net.Authenticator.RequestorType;
    1212import java.net.ConnectException;
    1313import java.net.HttpURLConnection;
    14 import java.net.MalformedURLException;
    1514import java.net.NoRouteToHostException;
    1615import java.net.PortUnreachableException;
    1716import java.net.SocketException;
    1817import java.net.SocketTimeoutException;
     18import java.net.URI;
     19import java.net.URISyntaxException;
    1920import java.net.URL;
    2021import java.nio.charset.StandardCharsets;
    2122import java.util.Collection;
     
    8485    private static final Map<String, OsmApi> instances = new HashMap<>();
    8586
    8687    private static final ListenerList<OsmApiInitializationListener> listeners = ListenerList.create();
    87     /** This is used to make certain we have set osm-server.auth-method to the "right" default */
    88     private static boolean oauthCompatibilitySwitch;
    8988
    9089    private URL url;
    9190
     
    194193    public String getHost() {
    195194        String host = null;
    196195        try {
    197             host = new URL(serverUrl).getHost();
    198         } catch (MalformedURLException e) {
     196            host = new URI(serverUrl).getHost();
     197        } catch (URISyntaxException e) {
    199198            Logging.warn(e);
    200199        }
    201200        return host;
     
    455454    /**
    456455     * Creates a new changeset based on the keys in <code>changeset</code>. If this
    457456     * method succeeds, changeset.getId() replies the id the server assigned to the new changeset
    458      *
     457     * <p>
    459458     * The changeset must not be null, but its key/value-pairs may be empty.
    460459     *
    461460     * @param changeset the changeset toe be created. Must not be null.
     
    652651     * @since 6349
    653652     */
    654653    public static boolean isUsingOAuth() {
    655         return isUsingOAuth(OAuthVersion.OAuth10a)
    656                 || isUsingOAuth(OAuthVersion.OAuth20)
     654        return isUsingOAuth(OAuthVersion.OAuth20)
    657655                || isUsingOAuth(OAuthVersion.OAuth21);
    658656    }
    659657
     
    664662     * @since 18650
    665663     */
    666664    public static boolean isUsingOAuth(OAuthVersion version) {
    667         if (version == OAuthVersion.OAuth10a) {
    668             return "oauth".equalsIgnoreCase(getAuthMethod());
    669         } else if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) {
    670             return "oauth20".equalsIgnoreCase(getAuthMethod());
     665        if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) {
     666            return getAuthMethodVersion() == OAuthVersion.OAuth20 || getAuthMethodVersion() == OAuthVersion.OAuth21;
    671667        }
    672668        return false;
    673669    }
     
    679675     */
    680676    public static boolean isUsingOAuthAndOAuthSetUp(OsmApi api) {
    681677        if (OsmApi.isUsingOAuth()) {
    682             if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) {
    683                 return OAuthAccessTokenHolder.getInstance().containsAccessToken();
    684             }
    685678            if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20)) {
    686679                return OAuthAccessTokenHolder.getInstance().getAccessToken(api.getBaseUrl(), OAuthVersion.OAuth20) != null;
    687680            }
     
    697690     * @return the authentication method
    698691     */
    699692    public static String getAuthMethod() {
    700         setCurrentAuthMethod();
    701693        return Config.getPref().get("osm-server.auth-method", "oauth20");
    702694    }
    703695
    704696    /**
    705      * This is a compatibility method for users who currently use OAuth 1.0 -- we are changing the default from oauth to oauth20,
    706      * but since oauth was the default, pre-existing users will suddenly be switched to oauth20.
    707      * This should be removed whenever {@link OAuthVersion#OAuth10a} support is removed.
     697     * Returns the authentication method set in the preferences
     698     * @return the authentication method
     699     * @since xxx
    708700     */
    709     private static void setCurrentAuthMethod() {
    710         if (!oauthCompatibilitySwitch) {
    711             oauthCompatibilitySwitch = true;
    712             final String prefKey = "osm-server.auth-method";
    713             if ("oauth20".equals(Config.getPref().get(prefKey, "oauth20"))
    714                 && !isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())
    715                 && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
    716                 Config.getPref().put(prefKey, "oauth");
    717             }
     701    public static OAuthVersion getAuthMethodVersion() {
     702        switch (getAuthMethod()) {
     703            case "oauth20": return OAuthVersion.OAuth20;
     704            case "oauth21": return OAuthVersion.OAuth21;
     705            default:
     706                Config.getPref().put("osm-server.auth-method", null);
     707                return getAuthMethodVersion();
    718708        }
    719709    }
    720710
  • core/src/org/openstreetmap/josm/io/OsmConnection.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/io/OsmConnection.java b/core/src/org/openstreetmap/josm/io/OsmConnection.java
    a b  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    66import java.lang.reflect.InvocationTargetException;
    7 import java.net.Authenticator.RequestorType;
    8 import java.net.MalformedURLException;
     7import java.net.URI;
     8import java.net.URISyntaxException;
    99import java.net.URL;
    1010import java.nio.charset.StandardCharsets;
    1111import java.util.Base64;
     
    2727import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    2828import org.openstreetmap.josm.gui.MainApplication;
    2929import org.openstreetmap.josm.gui.util.GuiHelper;
    30 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
    31 import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
    3230import org.openstreetmap.josm.io.auth.CredentialsManager;
    3331import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
    3432import org.openstreetmap.josm.tools.HttpClient;
    3533import org.openstreetmap.josm.tools.JosmRuntimeException;
    3634import org.openstreetmap.josm.tools.Logging;
    3735
    38 import oauth.signpost.OAuthConsumer;
    39 import oauth.signpost.exception.OAuthException;
    4036
    4137/**
    4238 * Base class that handles common things like authentication for the reader and writer
     
    5046
    5147    protected boolean cancel;
    5248    protected HttpClient activeConnection;
    53     protected OAuthParameters oauthParameters;
    5449    protected IOAuthParameters oAuth20Parameters;
    5550
    5651    /**
     
    6459         * @throws InterruptedException if we're interrupted while waiting for the event dispatching thread to finish OAuth authorization task
    6560         * @throws InvocationTargetException if an exception is thrown while running OAuth authorization task
    6661         */
    67         void obtainAccessToken(URL serverUrl) throws InvocationTargetException, InterruptedException;
     62        default void obtainAccessToken(URL serverUrl) throws InvocationTargetException, InterruptedException {
     63            try {
     64                this.obtainAccessToken(serverUrl.toURI());
     65            } catch (URISyntaxException e) {
     66                throw new JosmRuntimeException(e);
     67            }
     68        }
     69
     70        /**
     71         * Obtains an OAuth access token for the connection. Afterwards, the token is accessible via {@link OAuthAccessTokenHolder}.
     72         * @param serverUrl the URL to OSM server
     73         * @throws InterruptedException if we're interrupted while waiting for the event dispatching thread to finish OAuth authorization task
     74         * @throws InvocationTargetException if an exception is thrown while running OAuth authorization task
     75         */
     76        void obtainAccessToken(URI serverUrl) throws InvocationTargetException, InterruptedException;
    6877    }
    6978
    7079    static volatile OAuthAccessTokenFetcher fetcher = u -> {
     
    116125        return null;
    117126    }
    118127
    119     /**
    120      * Adds an authentication header for basic authentication
    121      *
    122      * @param con the connection
    123      * @throws OsmTransferException if something went wrong. Check for nested exceptions
    124      */
    125     protected void addBasicAuthorizationHeader(HttpClient con) throws OsmTransferException {
    126         CredentialsAgentResponse response;
    127         try {
    128             synchronized (CredentialsManager.getInstance()) {
    129                 response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
    130                 con.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
    131             }
    132         } catch (CredentialsAgentException e) {
    133             throw new OsmTransferException(e);
    134         }
    135         if (response != null) {
    136             if (response.isCanceled()) {
    137                 cancel = true;
    138             } else {
    139                 String username = response.getUsername() == null ? "" : response.getUsername();
    140                 String password = response.getPassword() == null ? "" : String.valueOf(response.getPassword());
    141                 String token = username + ':' + password;
    142                 con.setHeader("Authorization", BASIC_AUTH + Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8)));
    143             }
    144         }
    145     }
    146 
    147     /**
    148      * Signs the connection with an OAuth authentication header
    149      *
    150      * @param connection the connection
    151      *
    152      * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured
    153      * @throws OsmTransferException if signing fails
    154      */
    155     protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
    156         if (oauthParameters == null) {
    157             oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
    158         }
    159         OAuthConsumer consumer = oauthParameters.buildConsumer();
    160         OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
    161         if (!holder.containsAccessToken()) {
    162             obtainAccessToken(connection);
    163         }
    164         if (!holder.containsAccessToken()) { // check if wizard completed
    165             throw new MissingOAuthAccessTokenException();
    166         }
    167         consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());
    168         try {
    169             consumer.sign(connection);
    170         } catch (OAuthException e) {
    171             throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);
    172         }
    173     }
    174 
    175     /**
    176      * Obtains an OAuth access token for the connection.
    177      * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
    178      * @param connection connection for which the access token should be obtained
    179      * @throws MissingOAuthAccessTokenException if the process cannot be completed successfully
    180      */
    181     protected void obtainAccessToken(final HttpClient connection) throws MissingOAuthAccessTokenException {
    182         try {
    183             final URL apiUrl = new URL(OsmApi.getOsmApi().getServerUrl());
    184             if (!Objects.equals(apiUrl.getHost(), connection.getURL().getHost())) {
    185                 throw new MissingOAuthAccessTokenException();
    186             }
    187             fetcher.obtainAccessToken(apiUrl);
    188             OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true);
    189             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    190         } catch (MalformedURLException | InvocationTargetException e) {
    191             throw new MissingOAuthAccessTokenException(e);
    192         } catch (InterruptedException e) {
    193             Thread.currentThread().interrupt();
    194             throw new MissingOAuthAccessTokenException(e);
    195         }
    196     }
    197 
    198128    /**
    199129     * Obtains an OAuth access token for the connection.
    200130     * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
     
    220150                        RemoteControl.stop();
    221151                    }
    222152                    // Clean up old token/password
    223                     OAuthAccessTokenHolder.getInstance().setAccessToken(null);
    224153                    OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), authToken.orElse(null));
    225154                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    226155                    done.countDown();
     
    276205
    277206    protected void addAuth(HttpClient connection) throws OsmTransferException {
    278207        final String authMethod = OsmApi.getAuthMethod();
    279         switch (authMethod) {
    280             case "basic":
    281                 addBasicAuthorizationHeader(connection);
    282                 return;
    283             case "oauth":
    284                 addOAuthAuthorizationHeader(connection);
    285                 return;
    286             case "oauth20":
    287                 addOAuth20AuthorizationHeader(connection);
    288                 return;
    289             default:
    290                 String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
    291                 Logging.warn(msg);
    292                 throw new OsmTransferException(msg);
    293         }
     208        if ("oauth20".equals(authMethod)) {
     209            addOAuth20AuthorizationHeader(connection);
     210            return;
     211        }
     212        String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
     213        Logging.warn(msg);
     214        throw new OsmTransferException(msg);
    294215    }
    295216
    296217    /**
  • core/src/org/openstreetmap/josm/tools/ExceptionUtil.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java b/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java
    a b  
    297297                + "Authentication at the OSM server with the OAuth token ''{0}'' failed.<br>"
    298298                + "Please launch the preferences dialog and retrieve another OAuth token."
    299299                + "</html>",
    300                 OAuthAccessTokenHolder.getInstance().getAccessTokenKey()
     300                OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion())
    301301        );
    302302    }
    303303
     
    343343                + "''{1}''.<br>"
    344344                + "Please launch the preferences dialog and retrieve another OAuth token."
    345345                + "</html>",
    346                 OAuthAccessTokenHolder.getInstance().getAccessTokenKey(),
     346                OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion()),
    347347                e.getAccessedUrl() == null ? tr("unknown") : e.getAccessedUrl()
    348348        );
    349349    }
  • core/src/org/openstreetmap/josm/tools/HttpClient.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/src/org/openstreetmap/josm/tools/HttpClient.java b/core/src/org/openstreetmap/josm/tools/HttpClient.java
    a b  
    66import java.io.BufferedReader;
    77import java.io.IOException;
    88import java.io.InputStream;
     9import java.io.UncheckedIOException;
    910import java.net.CookieHandler;
    1011import java.net.CookieManager;
    1112import java.net.HttpURLConnection;
    1213import java.net.MalformedURLException;
     14import java.net.URI;
     15import java.net.URISyntaxException;
    1316import java.net.URL;
    1417import java.nio.charset.StandardCharsets;
    1518import java.util.List;
     
    5457         * @return a new instance
    5558         */
    5659        HttpClient create(URL url, String requestMethod);
     60
     61        /**
     62         * Creates a new instance for the given URL and a {@code GET} request
     63         *
     64         * @param url the URL
     65         * @param requestMethod the HTTP request method to perform when calling
     66         * @return a new instance
     67         * @since xxx
     68         */
     69        default HttpClient create(URI url, String requestMethod) {
     70            try {
     71                return create(url.toURL(), requestMethod);
     72            } catch (MalformedURLException e) {
     73                throw new UncheckedIOException(e);
     74            }
     75        }
    5776    }
    5877
    5978    private URL url;
     
    535554    public static HttpClient create(URL url) {
    536555        return create(url, "GET");
    537556    }
     557
     558    /**
     559     * Creates a new instance for the given URL and a {@code GET} request
     560     *
     561     * @param url the URL
     562     * @return a new instance
     563     */
     564    public static HttpClient create(URI url) {
     565        return create(url, "GET");
     566    }
    538567
    539568    /**
    540569     * Creates a new instance for the given URL and a {@code GET} request
     
    551580                // #18812: specify `Accept=*/*` to prevent Java from adding `Accept=text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2`
    552581                .setAccept("*/*");
    553582    }
     583
     584    /**
     585     * Creates a new instance for the given URL and a {@code GET} request
     586     *
     587     * @param url the URL
     588     * @param requestMethod the HTTP request method to perform when calling
     589     * @return a new instance
     590     * @since xxx
     591     */
     592    public static HttpClient create(URI url, String requestMethod) {
     593        if (factory == null) {
     594            throw new IllegalStateException("HTTP factory has not been set");
     595        }
     596        return factory.create(url, requestMethod)
     597                // #18812: specify `Accept=*/*` to prevent Java from adding `Accept=text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2`
     598                .setAccept("*/*");
     599    }
    554600
    555601    /**
    556602     * Returns the URL set for this connection.
  • core/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java b/core/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java
    a b  
    1616import java.io.OutputStreamWriter;
    1717import java.io.PrintWriter;
    1818import java.nio.charset.StandardCharsets;
     19import java.nio.file.Files;
    1920import java.text.MessageFormat;
    2021import java.util.HashSet;
    2122import java.util.Locale;
     
    4243import org.openstreetmap.josm.data.projection.Projections;
    4344import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    4445import org.openstreetmap.josm.spi.preferences.Config;
     46import org.openstreetmap.josm.testutils.annotations.TestUser;
    4547import org.openstreetmap.josm.tools.Logging;
    4648
    4749import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    5153 * @since 1806
    5254 */
    5355@SuppressFBWarnings(value = "CRLF_INJECTION_LOGS")
     56@org.openstreetmap.josm.testutils.annotations.OsmApi(org.openstreetmap.josm.testutils.annotations.OsmApi.APIType.DEV)
     57@TestUser
    5458class OsmServerBackreferenceReaderTest {
    5559    private static final Logger logger = Logger.getLogger(OsmServerBackreferenceReader.class.getName());
    5660
     
    159163     */
    160164    @BeforeAll
    161165    public static void setUpBeforeClass() throws OsmTransferException, CyclicUploadDependencyException, IOException {
    162         if (!TestUtils.areCredentialsProvided()) {
    163             logger.severe("OSM DEV API credentials not provided. Please define them with -Dosm.username and -Dosm.password");
    164             return;
    165         }
     166        assumeTrue(TestUtils.areCredentialsProvided(),
     167                "OSM DEV API credentials not provided. Please define them with -Dosm.oauth2");
     168
    166169        logger.info("initializing ...");
    167170
    168         JOSMFixture.createFunctionalTestFixture().init();
    169 
    170         Config.getPref().put("osm-server.auth-method", "basic");
    171 
    172171        // don't use atomic upload, the test API server can't cope with large diff uploads
    173172        //
    174173        Config.getPref().putBoolean("osm-server.atomic-upload", false);
     
    196195
    197196        try (
    198197            PrintWriter pw = new PrintWriter(
    199                     new OutputStreamWriter(new FileOutputStream(dataSetCacheOutputFile), StandardCharsets.UTF_8)
     198                    new OutputStreamWriter(Files.newOutputStream(dataSetCacheOutputFile.toPath()), StandardCharsets.UTF_8)
    200199        )) {
    201200            logger.info(MessageFormat.format("caching test data set in ''{0}'' ...", dataSetCacheOutputFile.toString()));
    202201            try (OsmWriter w = new OsmWriter(pw, false, testDataSet.getVersion())) {
     
    218217     */
    219218    @BeforeEach
    220219    public void setUp() throws IOException, IllegalDataException, FileNotFoundException {
    221         if (!TestUtils.areCredentialsProvided()) {
    222             return;
    223         }
    224220        File f = new File(System.getProperty("java.io.tmpdir"), MultiFetchServerObjectReaderTest.class.getName() + ".dataset");
    225221        logger.info(MessageFormat.format("reading cached dataset ''{0}''", f.toString()));
    226222        ds = new DataSet();
     
    291287     */
    292288    @Test
    293289    void testBackreferenceForNodeFull() throws OsmTransferException {
    294         assumeTrue(TestUtils.areCredentialsProvided());
    295290        Node n = lookupNode(ds, 0);
    296291        assertNotNull(n);
    297292
     
    338333     */
    339334    @Test
    340335    void testBackreferenceForWay() throws OsmTransferException {
    341         assumeTrue(TestUtils.areCredentialsProvided());
    342336        Way w = lookupWay(ds, 1);
    343337        assertNotNull(w);
    344338        // way with name "way-1" is referred to by two relations
     
    381375     */
    382376    @Test
    383377    void testBackreferenceForWayFull() throws OsmTransferException {
    384         assumeTrue(TestUtils.areCredentialsProvided());
    385378        Way w = lookupWay(ds, 1);
    386379        assertNotNull(w);
    387380        // way with name "way-1" is referred to by two relations
     
    418411     */
    419412    @Test
    420413    void testBackreferenceForRelation() throws OsmTransferException {
    421         assumeTrue(TestUtils.areCredentialsProvided());
    422414        Relation r = lookupRelation(ds, 1);
    423415        assertNotNull(r);
    424416        // way with name "relation-1" is referred to by four relations:
     
    536528     */
    537529    @Test
    538530    void testBackreferenceForRelationFull() throws OsmTransferException {
    539         assumeTrue(TestUtils.areCredentialsProvided());
    540531        Relation r = lookupRelation(ds, 1);
    541532        assertNotNull(r);
    542533        // way with name "relation-1" is referred to by four relations:
  • core/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java b/core/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java
    a b  
    1212import org.openstreetmap.josm.data.osm.OsmDataGenerator;
    1313import org.openstreetmap.josm.data.osm.OsmDataGenerator.KeyValueDataGenerator;
    1414import org.openstreetmap.josm.gui.mappaint.MultiCascade;
     15import org.openstreetmap.josm.testutils.annotations.Main;
     16import org.openstreetmap.josm.testutils.annotations.Projection;
    1517
    1618/**
    1719 * Tests how fast {@link MapCSSStyleSource} finds the right style candidates for one object.
    1820 * @author Michael Zangl
    1921 */
    20 @Timeout(value = 15, unit = TimeUnit.MINUTES)
     22@Main
     23@Projection
     24@Timeout(value = 5, unit = TimeUnit.MINUTES)
    2125class MapCSSStyleSourceFilterTest {
    2226
    2327    private static final int TEST_RULE_COUNT = 10000;
     
    8084
    8185    private static final int APPLY_CALLS = 100000;
    8286
    83     /**
    84      * Prepare the test.
    85      */
    86     @BeforeAll
    87     public static void createJOSMFixture() {
    88         JOSMFixture.createPerformanceTestFixture().init(true);
    89     }
    90 
    9187    /**
    9288     * Time how long it takes to evaluate [key=value] rules
    9389     */
  • core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java
    a b  
    185185        final OAuth20Authorization authorization = new OAuth20Authorization();
    186186        OAuth20Parameters parameters = (OAuth20Parameters) OAuthParameters.createDefault(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
    187187        RemoteControl.start();
    188         authorization.authorize(new OAuth20Parameters(parameters.getClientId(), parameters.getClientSecret(),
     188        authorization.authorize(new OAuth20Parameters(CLIENT_ID_VALUE, parameters.getClientSecret(),
    189189                wireMockRuntimeInfo.getHttpBaseUrl() + "/oauth2", wireMockRuntimeInfo.getHttpBaseUrl() + "/api",
    190190                parameters.getRedirectUri()), consumer::set, OsmScopes.read_gpx);
    191191        assertEquals(1, OpenBrowserMocker.getCalledURIs().size());
  • core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java
    a b  
    55import static org.junit.jupiter.api.Assertions.assertNotEquals;
    66import static org.junit.jupiter.api.Assertions.assertNotNull;
    77
     8import java.util.Collections;
     9import java.util.List;
     10
    811import org.junit.jupiter.api.extension.RegisterExtension;
    912import org.junit.jupiter.api.Test;
     13import org.junit.jupiter.params.ParameterizedTest;
     14import org.junit.jupiter.params.provider.MethodSource;
    1015import org.openstreetmap.josm.TestUtils;
    1116import org.openstreetmap.josm.spi.preferences.Config;
    1217import org.openstreetmap.josm.testutils.JOSMTestRules;
     
    1924 * Unit tests for class {@link OAuthParameters}.
    2025 */
    2126class OAuthParametersTest {
    22 
    23     /**
    24      * Setup test.
    25      */
    26     @RegisterExtension
    27     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    28     public JOSMTestRules test = new JOSMTestRules();
    29 
    3027    /**
    3128     * Unit test of method {@link OAuthParameters#createDefault}.
    3229     */
    3330    @Test
    3431    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
    3532    void testCreateDefault() {
    36         OAuthParameters def = OAuthParameters.createDefault();
     33        IOAuthParameters def = OAuthParameters.createDefault();
    3734        assertNotNull(def);
    38         assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl()));
    39         OAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api");
     35        assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20));
     36        IOAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api", OAuthVersion.OAuth20);
    4037        assertNotNull(dev);
    4138        assertNotEquals(def, dev);
    4239        Logging.setLogLevel(Logging.LEVEL_TRACE); // enable trace for line coverage
    43         assertEquals(def, OAuthParameters.createDefault("wrong_url"));
    44         OAuthParameters dev2 = new OAuthParameters(dev);
    45         assertEquals(dev, dev2);
     40        assertEquals(def, OAuthParameters.createDefault("wrong_url", OAuthVersion.OAuth20));
     41    }
     42
     43    static List<Class<? extends IOAuthParameters>> testEqualsContract() {
     44        return Collections.singletonList(OAuth20Parameters.class);
    4645    }
    4746
    4847    /**
    4948     * Unit test of methods {@link OAuthParameters#equals} and {@link OAuthParameters#hashCode}.
    5049     */
    51     @Test
    52     void testEqualsContract() {
     50    @ParameterizedTest
     51    @MethodSource
     52    void testEqualsContract(Class<? extends IOAuthParameters> clazz) {
    5353        TestUtils.assumeWorkingEqualsVerifier();
    54         EqualsVerifier.forClass(OAuthParameters.class).usingGetClass().verify();
     54        EqualsVerifier.forClass(clazz).usingGetClass().verify();
    5555    }
    5656}
  • deleted file core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java

    diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.data.oauth;
    3 
    4 import static org.junit.jupiter.api.Assertions.assertEquals;
    5 import static org.junit.jupiter.api.Assertions.assertNotNull;
    6 
    7 import org.junit.jupiter.api.Test;
    8 import org.openstreetmap.josm.TestUtils;
    9 
    10 import nl.jqno.equalsverifier.EqualsVerifier;
    11 import oauth.signpost.OAuthConsumer;
    12 
    13 /**
    14  * Unit tests for class {@link OAuthToken}.
    15  */
    16 class OAuthTokenTest {
    17 
    18     /**
    19      * Unit test of method {@link OAuthToken#createToken}.
    20      */
    21     @Test
    22     void testCreateToken() {
    23         OAuthConsumer defCon = OAuthParameters.createDefault().buildConsumer();
    24         assertNotNull(defCon);
    25         OAuthToken defTok = OAuthToken.createToken(defCon);
    26         assertNotNull(defTok);
    27         assertEquals(defCon.getToken(), defTok.getKey());
    28         assertEquals(defCon.getTokenSecret(), defTok.getSecret());
    29         assertEquals(defTok, new OAuthToken(defTok));
    30     }
    31 
    32     /**
    33      * Unit test of methods {@link OAuthToken#equals} and {@link OAuthToken#hashCode}.
    34      */
    35     @Test
    36     void testEqualsContract() {
    37         TestUtils.assumeWorkingEqualsVerifier();
    38         EqualsVerifier.forClass(OAuthToken.class).usingGetClass().verify();
    39     }
    40 }
  • deleted file core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java

    diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.data.oauth;
    3 
    4 import static org.junit.jupiter.api.Assertions.assertEquals;
    5 import static org.junit.jupiter.api.Assertions.assertNotNull;
    6 import static org.junit.jupiter.api.Assertions.assertNull;
    7 import static org.junit.jupiter.api.Assertions.assertThrows;
    8 
    9 import java.io.IOException;
    10 import java.net.MalformedURLException;
    11 import java.net.URL;
    12 
    13 import org.junit.jupiter.api.Test;
    14 import org.junit.jupiter.api.extension.RegisterExtension;
    15 import org.openstreetmap.josm.data.oauth.SignpostAdapters.HttpRequest;
    16 import org.openstreetmap.josm.data.oauth.SignpostAdapters.HttpResponse;
    17 import org.openstreetmap.josm.data.oauth.SignpostAdapters.OAuthConsumer;
    18 import org.openstreetmap.josm.testutils.JOSMTestRules;
    19 import org.openstreetmap.josm.tools.HttpClient;
    20 
    21 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    22 import net.trajano.commons.testing.UtilityClassTestUtil;
    23 
    24 /**
    25  * Unit tests for class {@link SignpostAdapters}.
    26  */
    27 class SignpostAdaptersTest {
    28 
    29     /**
    30      * Setup test.
    31      */
    32     @RegisterExtension
    33     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    34     public JOSMTestRules test = new JOSMTestRules().https();
    35 
    36     private static HttpClient newClient() throws MalformedURLException {
    37         return HttpClient.create(new URL("https://www.openstreetmap.org"));
    38     }
    39 
    40     /**
    41      * Tests that {@code SignpostAdapters} satisfies utility class criteria.
    42      * @throws ReflectiveOperationException if an error occurs
    43      */
    44     @Test
    45     void testUtilityClass() throws ReflectiveOperationException {
    46         UtilityClassTestUtil.assertUtilityClassWellDefined(SignpostAdapters.class);
    47     }
    48 
    49     /**
    50      * Unit test of method {@link SignpostAdapters.OAuthConsumer#wrap}.
    51      * @throws MalformedURLException never
    52      */
    53     @Test
    54     void testOAuthConsumerWrap() throws MalformedURLException {
    55         assertNotNull(new OAuthConsumer("", "").wrap(newClient()));
    56     }
    57 
    58     /**
    59      * Unit test of method {@link SignpostAdapters.HttpRequest#getMessagePayload}.
    60      * @throws IOException never
    61      */
    62     @Test
    63     void testHttpRequestGetMessagePayload() throws IOException {
    64         assertNull(new HttpRequest(newClient()).getMessagePayload());
    65     }
    66 
    67     /**
    68      * Unit test of method {@link SignpostAdapters.HttpRequest#setRequestUrl}.
    69      */
    70     @Test
    71     void testHttpRequestSetRequestUrl() {
    72         assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).setRequestUrl(null));
    73     }
    74 
    75     /**
    76      * Unit test of method {@link SignpostAdapters.HttpRequest#getAllHeaders}.
    77      */
    78     @Test
    79     void testHttpRequestGetAllHeaders() {
    80         assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).getAllHeaders());
    81     }
    82 
    83     /**
    84      * Unit test of method {@link SignpostAdapters.HttpRequest#unwrap}.
    85      */
    86     @Test
    87     void testHttpRequestUnwrap() {
    88         assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).unwrap());
    89     }
    90 
    91     /**
    92      * Unit test of method {@link SignpostAdapters.HttpResponse#getReasonPhrase()}.
    93      * @throws Exception never
    94      */
    95     @Test
    96     void testHttpResponseGetReasonPhrase() throws Exception {
    97         assertEquals("OK", new HttpResponse(new HttpRequest(newClient()).request.connect()).getReasonPhrase());
    98     }
    99 
    100     /**
    101      * Unit test of method {@link SignpostAdapters.HttpResponse#unwrap}.
    102      */
    103     @Test
    104     void testHttpResponseUnwrap() {
    105         assertThrows(IllegalStateException.class, () -> new HttpResponse(new HttpRequest(newClient()).request.connect()).unwrap());
    106     }
    107 }
  • core/test/unit/org/openstreetmap/josm/gui/io/importexport/OsmPbfImporterTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/io/importexport/OsmPbfImporterTest.java b/core/test/unit/org/openstreetmap/josm/gui/io/importexport/OsmPbfImporterTest.java
    a b  
    1818
    1919import org.junit.jupiter.api.BeforeAll;
    2020import org.junit.jupiter.api.Test;
    21 import org.junit.jupiter.params.ParameterizedTest;
    22 import org.junit.jupiter.params.provider.ValueSource;
    2321import org.openstreetmap.josm.TestUtils;
    2422import org.openstreetmap.josm.data.coor.ILatLon;
    2523import org.openstreetmap.josm.data.coor.LatLon;
  • core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java b/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java
    a b  
    55import static org.junit.jupiter.api.Assertions.assertNotNull;
    66import static org.junit.jupiter.api.Assertions.assertNull;
    77import static org.junit.jupiter.api.Assertions.assertTrue;
     8import static org.junit.jupiter.api.Assumptions.assumeTrue;
    89
    910import java.awt.GraphicsEnvironment;
    1011import java.net.URL;
    1112import java.util.Collections;
     13import java.util.HashMap;
     14import java.util.Map;
    1215
    1316import javax.swing.JOptionPane;
    1417import javax.swing.JPanel;
     
    2124import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
    2225import org.openstreetmap.josm.spi.preferences.Config;
    2326import org.openstreetmap.josm.testutils.JOSMTestRules;
     27import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
     28import org.openstreetmap.josm.testutils.annotations.OsmApi;
    2429import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
    2530import org.openstreetmap.josm.testutils.mockers.WindowMocker;
    2631import org.openstreetmap.josm.tools.UserCancelException;
     32import org.openstreetmap.josm.tools.Utils;
    2733
    2834import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     35import jdk.nashorn.internal.scripts.JO;
    2936import mockit.Invocation;
    3037import mockit.Mock;
    3138import mockit.MockUp;
     
    3340/**
    3441 * Unit tests of {@link DownloadOpenChangesetsTask} class.
    3542 */
     43@BasicPreferences
     44@OsmApi(OsmApi.APIType.DEV)
    3645class DownloadOpenChangesetsTaskTest {
    37 
    38     /**
    39      * Setup tests
    40      */
    41     @RegisterExtension
    42     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    43     public JOSMTestRules test = new JOSMTestRules().preferences().devAPI();
    44 
    4546    /**
    4647     * OAuth wizard mocker.
    4748     */
     
    6970        }
    7071    }
    7172
    72     /**
    73      * These tests were written with {@link org.openstreetmap.josm.data.oauth.OAuthVersion#OAuth10a} as the default auth method.
    74      */
    75     @BeforeEach
    76     void setup() {
    77         Config.getPref().put("osm-server.auth-method", "oauth");
    78     }
    79 
    8073    /**
    8174     * Test of {@link DownloadOpenChangesetsTask} class when anonymous.
    8275     */
     
    8679        if (GraphicsEnvironment.isHeadless()) {
    8780            new WindowMocker();
    8881        }
    89         final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
    90         final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
    91             Collections.singletonMap(
    92                 "<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
     82        final Map<String, Object> optionPaneMock = new HashMap<>(2);
     83        optionPaneMock.put("<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
    9384                + "your identity.<br>You have either chosen to work anonymously or you are not "
    94                 + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION
    95             )
    96         );
     85                + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION);
     86        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
     87        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
    9788
    9889        DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
    9990        assertNull(task.getChangesets());
     
    10293        task.run();
    10394        assertNull(task.getChangesets());
    10495
    105         assertEquals(1, jopsMocker.getInvocationLog().size());
    106         Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     96        assertEquals(2, jopsMocker.getInvocationLog().size());
     97        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
    10798        assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
    10899        assertEquals("Missing user identity", invocationLogEntry[2]);
    109100
    110         assertTrue(oaWizardMocker.called);
     101        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     102        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
     103        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
    111104    }
    112105
    113106    /**
     
    119112        if (GraphicsEnvironment.isHeadless()) {
    120113            new WindowMocker();
    121114        }
    122         final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
    123         final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
    124             Collections.singletonMap("There are no open changesets", JOptionPane.OK_OPTION)
    125         );
     115        final Map<String, Object> optionPaneMock = new HashMap<>(2);
     116        optionPaneMock.put("There are no open changesets", JOptionPane.OK_OPTION);
     117        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
     118        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
    126119
    127120        DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
    128121        UserIdentityManager.getInstance().setPartiallyIdentified(System.getProperty("osm.username", "josm_test"));
     
    130123        task.run();
    131124        assertNotNull(task.getChangesets());
    132125
    133         assertEquals(1, jopsMocker.getInvocationLog().size());
    134         Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     126        assertEquals(2, jopsMocker.getInvocationLog().size());
     127        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
    135128        assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
    136129        assertEquals("No open changesets", invocationLogEntry[2]);
    137130
    138         assertTrue(oaWizardMocker.called);
     131        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     132        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
     133        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
    139134    }
    140135}
  • core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.oauth;
    33
    4 import static org.junit.jupiter.api.Assertions.assertNotNull;
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    55
     6import org.junit.jupiter.params.ParameterizedTest;
     7import org.junit.jupiter.params.provider.EnumSource;
     8import org.openstreetmap.josm.data.oauth.OAuthVersion;
    69import org.openstreetmap.josm.gui.MainApplication;
    710import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    811
    9 import org.junit.jupiter.api.Test;
    10 
    1112/**
    1213 * Unit tests of {@link FullyAutomaticAuthorizationUI} class.
    1314 */
     
    1617    /**
    1718     * Unit test of {@link FullyAutomaticAuthorizationUI#FullyAutomaticAuthorizationUI}.
    1819     */
    19     @Test
    20     void testFullyAutomaticAuthorizationUI() {
    21         assertNotNull(new FullyAutomaticAuthorizationUI("", MainApplication.worker));
     20    @ParameterizedTest
     21    @EnumSource(OAuthVersion.class)
     22    void testFullyAutomaticAuthorizationUI(OAuthVersion version) {
     23        assertDoesNotThrow(() -> new FullyAutomaticAuthorizationUI("", MainApplication.worker, version));
    2224    }
    2325}
  • core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.oauth;
    33
    4 import static org.junit.jupiter.api.Assertions.assertNotNull;
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    55
    66import org.junit.jupiter.api.Test;
     7import org.openstreetmap.josm.data.oauth.OAuthVersion;
    78import org.openstreetmap.josm.gui.MainApplication;
    89import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    910
     
    1718     */
    1819    @Test
    1920    void testManualAuthorizationUI() {
    20         assertNotNull(new ManualAuthorizationUI("", MainApplication.worker));
     21        assertDoesNotThrow(() -> new ManualAuthorizationUI("", MainApplication.worker, OAuthVersion.OAuth20));
    2122    }
    2223}
  • deleted file core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java

    diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
    5 import static com.github.tomakehurst.wiremock.client.WireMock.get;
    6 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
    7 import static org.junit.jupiter.api.Assertions.assertEquals;
    8 import static org.junit.jupiter.api.Assertions.assertNotNull;
    9 import static org.junit.jupiter.api.Assertions.assertNull;
    10 
    11 import java.net.CookieHandler;
    12 import java.net.CookieManager;
    13 import java.net.URI;
    14 import java.util.Collections;
    15 
    16 import org.junit.jupiter.api.Test;
    17 import org.junit.jupiter.api.Timeout;
    18 import org.openstreetmap.josm.data.oauth.OAuthParameters;
    19 import org.openstreetmap.josm.data.oauth.OAuthToken;
    20 import org.openstreetmap.josm.io.OsmTransferCanceledException;
    21 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    22 import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
    23 import org.openstreetmap.josm.testutils.annotations.HTTP;
    24 
    25 import com.github.tomakehurst.wiremock.WireMockServer;
    26 
    27 /**
    28  * Unit tests of {@link OsmOAuthAuthorizationClient} class.
    29  */
    30 @Timeout(20)
    31 @BasicWiremock
    32 // Needed for OAuthParameters
    33 @BasicPreferences
    34 @HTTP
    35 class OsmOAuthAuthorizationClientTest {
    36     /**
    37      * HTTP mock.
    38      */
    39     @BasicWiremock
    40     WireMockServer wireMockServer;
    41 
    42     /**
    43      * Unit test of {@link OsmOAuthAuthorizationClient}.
    44      * @throws OsmOAuthAuthorizationException if OAuth authorization error occurs
    45      * @throws OsmTransferCanceledException  if OSM transfer error occurs
    46      */
    47     @Test
    48     void testOsmOAuthAuthorizationClient() throws OsmTransferCanceledException, OsmOAuthAuthorizationException {
    49         // request token
    50         wireMockServer.stubFor(get(urlEqualTo("/oauth/request_token"))
    51                 .willReturn(aResponse().withStatus(200).withBody(String.join("&",
    52                         "oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR",
    53                         "oauth_token_secret=nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB"))));
    54         OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(OAuthParameters.createDefault(
    55                 wireMockServer.url("/api")));
    56 
    57         OAuthToken requestToken = client.getRequestToken(null);
    58         assertEquals("entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR", requestToken.getKey(), "requestToken.key");
    59         assertEquals("nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB", requestToken.getSecret(), "requestToken.secret");
    60         String url = client.getAuthoriseUrl(requestToken);
    61         assertEquals(wireMockServer.url("/oauth/authorize?oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR"), url, "url");
    62 
    63         // access token
    64         wireMockServer.stubFor(get(urlEqualTo("/oauth/access_token"))
    65                 .willReturn(aResponse().withStatus(200).withBody(String.join("&",
    66                         "oauth_token=eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX",
    67                         "oauth_token_secret=nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB"))));
    68 
    69         OAuthToken accessToken = client.getAccessToken(null);
    70         assertEquals("eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX", accessToken.getKey(), "accessToken.key");
    71         assertEquals("nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB", accessToken.getSecret(), "accessToken.secret");
    72     }
    73 
    74     /**
    75      * Unit test for correct cookie handling when logging in to the OSM website.
    76      *
    77      * https://josm.openstreetmap.de/ticket/12584
    78      * @throws Exception if any error occurs
    79      */
    80     @Test
    81     void testCookieHandlingMock() throws Exception {
    82         wireMockServer.stubFor(get(urlEqualTo("/login?cookie_test=true"))
    83                 .willReturn(aResponse()
    84                         .withStatus(200)
    85                         .withHeader("Set-Cookie", "_osm_session=7fe8e2ea36c6b803cb902301b28e0a; path=/; HttpOnly; SameSite=Lax")
    86                 .withBody("<input type=\"hidden\" " +
    87                         "name=\"authenticity_token\" " +
    88                         "value=\"fzp6CWJhp6Vns09re3s2Tw==\" />")));
    89         final OAuthParameters parameters = OAuthParameters.createDefault(wireMockServer.url("/api"));
    90         final OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(parameters);
    91         final OsmOAuthAuthorizationClient.SessionId sessionId = client.fetchOsmWebsiteSessionId();
    92         assertNotNull(sessionId);
    93         assertEquals("7fe8e2ea36c6b803cb902301b28e0a", sessionId.id, "sessionId.id");
    94         assertEquals("fzp6CWJhp6Vns09re3s2Tw==", sessionId.token, "sessionId.token");
    95         assertNull(sessionId.userName, "sessionId.userName");
    96     }
    97 
    98     /**
    99      * Unit test for correct cookie handling when logging in to the OSM website.
    100      *
    101      * https://josm.openstreetmap.de/ticket/12584
    102      * @throws Exception if any error occurs
    103      */
    104     @Test
    105     void testCookieHandlingCookieManager() throws Exception {
    106         // emulate Java Web Start behaviour
    107         // see https://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/accessingCookies.html
    108         final OAuthParameters parameters = OAuthParameters.createDefault();
    109         final OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(parameters);
    110         final CookieManager cm = new CookieManager();
    111         cm.put(new URI(parameters.getOsmLoginUrl()),
    112                 Collections.singletonMap("Cookie", Collections.singletonList("_osm_session=" + String.valueOf(Math.PI).substring(2))));
    113         CookieHandler.setDefault(cm);
    114         assertNotNull(client.fetchOsmWebsiteSessionId());
    115     }
    116 }
  • deleted file core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java

    diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java
    deleted file mode 100644
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.oauth;
    3 
    4 import static org.junit.jupiter.api.Assertions.assertNotNull;
    5 
    6 import org.junit.jupiter.api.Test;
    7 import org.openstreetmap.josm.gui.MainApplication;
    8 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    9 
    10 /**
    11  * Unit tests of {@link SemiAutomaticAuthorizationUI} class.
    12  */
    13 @BasicPreferences
    14 class SemiAutomaticAuthorizationUITest {
    15     /**
    16      * Unit test of {@link SemiAutomaticAuthorizationUI#SemiAutomaticAuthorizationUI}.
    17      */
    18     @Test
    19     void testSemiAutomaticAuthorizationUI() {
    20         assertNotNull(new SemiAutomaticAuthorizationUI("", MainApplication.worker));
    21     }
    22 }
  • core/test/unit/org/openstreetmap/josm/gui/preferences/display/GPXPreferenceTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/preferences/display/GPXPreferenceTest.java b/core/test/unit/org/openstreetmap/josm/gui/preferences/display/GPXPreferenceTest.java
    a b  
    33
    44import static org.junit.jupiter.api.Assertions.assertNotNull;
    55
    6 import org.junit.jupiter.api.BeforeAll;
    76import org.junit.jupiter.api.Test;
    8 import org.openstreetmap.josm.JOSMFixture;
    97import org.openstreetmap.josm.gui.preferences.PreferencesTestUtils;
     8import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    109
    1110/**
    1211 * Unit tests of {@link GPXPreference} class.
    1312 */
     13@BasicPreferences
    1414class GPXPreferenceTest {
    15 
    16     /**
    17      * Setup test.
    18      */
    19     @BeforeAll
    20     public static void setUpBeforeClass() {
    21         JOSMFixture.createUnitTestFixture().init();
    22     }
    23 
    2415    /**
    2516     * Unit test of {@link GPXPreference.Factory}.
    2617     */
  • core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java b/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java
    a b  
    2020import org.junit.jupiter.api.AfterEach;
    2121import org.junit.jupiter.params.ParameterizedTest;
    2222import org.junit.jupiter.params.provider.EnumSource;
    23 import org.openstreetmap.josm.data.oauth.IOAuthToken;
    2423import org.openstreetmap.josm.data.oauth.OAuth20Exception;
    2524import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    2625import org.openstreetmap.josm.data.oauth.OAuth20Token;
    2726import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    28 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2927import org.openstreetmap.josm.data.oauth.OAuthVersion;
    3028import org.openstreetmap.josm.io.OsmApi;
    3129import org.openstreetmap.josm.io.auth.CredentialsAgentException;
     
    4644        }
    4745        List<Exception> exceptionList = new ArrayList<>();
    4846        try {
    49             CredentialsManager.getInstance().storeOAuthAccessToken(null);
     47            CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
    5048        } catch (CredentialsAgentException exception) {
    5149            exceptionList.add(exception);
    5250        }
     
    6058    }
    6159
    6260    @ParameterizedTest
    63     @EnumSource(value = OAuthVersion.class, names = {"OAuth10a", "OAuth20"})
     61    @EnumSource(value = OAuthVersion.class, names = {"OAuth20"})
    6462    void testRemoveToken(OAuthVersion oAuthVersion) throws ReflectiveOperationException, CredentialsAgentException, OAuth20Exception {
    6563        final OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel(oAuthVersion);
    6664        final Field pnlNotYetAuthorised = OAuthAuthenticationPreferencesPanel.class.getDeclaredField("pnlNotYetAuthorised");
     
    7573        panel.initFromPreferences();
    7674        assertSame(pnlAlreadyAuthorised.get(panel), holder.getComponent(0), "Authentication should now be set");
    7775        assertNotNull(getAuthorization(oAuthVersion));
    78         final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(6);
    79         final JButton action = (JButton) buttons.getComponent(oAuthVersion == OAuthVersion.OAuth10a ? 2 : 1);
     76        final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(5);
     77        final JButton action = (JButton) buttons.getComponent(2);
    8078        assertEquals(tr("Remove token"), action.getText(), "The selected button should be for removing the token");
    8179        action.getAction().actionPerformed(null);
    8280        panel.saveToPreferences(); // Save to preferences should make the removal permanent
     
    9694     */
    9795    private static void addAuthorization(OAuthVersion oAuthVersion) throws CredentialsAgentException, OAuth20Exception {
    9896        switch (oAuthVersion) {
    99             case OAuth10a:
    100                 CredentialsManager.getInstance().storeOAuthAccessToken(new OAuthToken("fake_key", "fake_secret"));
    101                 break;
    10297            case OAuth20:
    10398            case OAuth21:
    10499                CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getHost(),
     
    116111     */
    117112    private static Object getAuthorization(OAuthVersion oAuthVersion) {
    118113        OAuthAccessTokenHolder.getInstance().clear();
    119         OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getHost(), (IOAuthToken) null);
     114        OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
    120115        OAuthAccessTokenHolder.getInstance().init(CredentialsManager.getInstance());
    121116        // Ensure that we are not saving authorization data
    122         switch (oAuthVersion) {
    123             case OAuth10a:
    124                 return OAuthAccessTokenHolder.getInstance().getAccessToken();
    125             case OAuth20:
    126             case OAuth21:
    127                 return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getHost(), oAuthVersion);
    128             default:
    129                 throw new AssertionError("OAuth version not understood");
    130         }
     117        return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getServerUrl(), oAuthVersion);
    131118    }
    132119}
  • core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java b/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java
    a b  
    1818import org.openstreetmap.josm.data.oauth.OAuth20Exception;
    1919import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    2020import org.openstreetmap.josm.data.oauth.OAuth20Token;
    21 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2221import org.openstreetmap.josm.io.OsmApi;
    2322import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    2423
     
    7574        assertNull(agent.lookup(null, null));
    7675    }
    7776
    78     @Test
    79     default void testLookUpAndStoreOAuth10() throws CredentialsAgentException {
    80         final T agent = createAgent();
    81         assertNull(agent.lookupOAuthAccessToken());
    82         final OAuthToken token = new OAuthToken("foo", "bar");
    83         agent.storeOAuthAccessToken(token);
    84         final OAuthToken actual = agent.lookupOAuthAccessToken();
    85         assertEquals(token, actual);
    86         agent.storeOAuthAccessToken(null);
    87         assertNull(agent.lookupOAuthAccessToken());
    88     }
    89 
    9077    @ParameterizedTest
    9178    @MethodSource("getHosts")
    9279    default void testLookupAndStoreOAuthTokens(final String host) throws CredentialsAgentException, OAuth20Exception {
  • core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java b/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java
    a b  
    5454        public void afterEach(ExtensionContext context) throws Exception {
    5555            if (AnnotationSupport.isAnnotated(context.getElement(), BasicPreferences.class)) {
    5656                this.afterAll(context);
     57                if (AnnotationSupport.isAnnotated(context.getTestClass(), BasicPreferences.class)) {
     58                    this.beforeAll(context);
     59                }
    5760            }
    5861        }
    5962
  • core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java b/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java
    a b  
    1818import org.junit.jupiter.api.extension.ExtensionContext;
    1919import org.openstreetmap.josm.TestUtils;
    2020import org.openstreetmap.josm.data.UserIdentityManager;
     21import org.openstreetmap.josm.data.oauth.OAuth20Token;
     22import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
     23import org.openstreetmap.josm.data.oauth.OAuthParameters;
     24import org.openstreetmap.josm.data.osm.User;
    2125import org.openstreetmap.josm.io.auth.CredentialsManager;
    2226import org.openstreetmap.josm.spi.preferences.Config;
    2327import org.openstreetmap.josm.tools.Utils;
     
    4751        @Override
    4852        public void beforeEach(ExtensionContext context) throws Exception {
    4953            assumeTrue(TestUtils.areCredentialsProvided(),
    50                     "OSM DEV API credentials not provided. Please define them with -Dosm.username and -Dosm.password");
    51             final String username = Utils.getSystemProperty("osm.username");
    52             final String password = Utils.getSystemProperty("osm.password");
    53             assumeTrue(username != null && !username.isEmpty(), "Please add -Dosm.username for the OSM DEV API");
    54             assumeTrue(password != null && !password.isEmpty(), "Please add -Dosm.password for the OSM DEV API");
    55             Config.getPref().put("osm-server.auth-method", "basic");
     54                    "OSM DEV API credentials not provided. Please define them with -Dosm.oauth2");
     55            final String oauth2 = Utils.getSystemProperty("osm.oauth2");
     56            Config.getPref().put("osm-server.auth-method", "oauth20");
    5657
    5758            // don't use atomic upload, the test API server can't cope with large diff uploads
    5859            Config.getPref().putBoolean("osm-server.atomic-upload", false);
    59             CredentialsManager.getInstance().store(Authenticator.RequestorType.SERVER, org.openstreetmap.josm.io.OsmApi.getOsmApi().getHost(),
    60                     new PasswordAuthentication(username, password.toCharArray()));
     60            final String serverUrl = org.openstreetmap.josm.io.OsmApi.getOsmApi().getServerUrl();
     61            final OAuth20Token token = new OAuth20Token(OAuthParameters.createDefault(), "{\"token_type\":\"bearer\", \"access_token\": \"" + oauth2 + "\"}");
     62            OAuthAccessTokenHolder.getInstance().setAccessToken(serverUrl, token);
     63            CredentialsManager.getInstance().storeOAuthAccessToken(serverUrl, token);
     64            if (!UserIdentityManager.getInstance().isFullyIdentified()) {
     65                UserIdentityManager.getInstance().initFromOAuth();
     66            }
    6167        }
    6268    }
    6369}
  • core/test/unit/org/openstreetmap/josm/testutils/FakeOsmApi.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/testutils/FakeOsmApi.java b/core/test/unit/org/openstreetmap/josm/testutils/FakeOsmApi.java
    a b  
    109109
    110110    /**
    111111     * Gets and caches an instance of this API.
    112      * @return The API intance. Always the same object.
     112     * @return The API instance. Always the same object.
    113113     */
    114114    public static synchronized FakeOsmApi getInstance() {
    115115        if (instance == null) {
    116116            instance = new FakeOsmApi();
    117             cacheInstance(instance);
    118         }
     117        }
     118        cacheInstance(instance);
    119119        return instance;
    120120    }
    121121}
  • core/test/unit/org/openstreetmap/josm/tools/date/DateUtilsTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/tools/date/DateUtilsTest.java b/core/test/unit/org/openstreetmap/josm/tools/date/DateUtilsTest.java
    a b  
    2424import org.junit.jupiter.params.ParameterizedTest;
    2525import org.junit.jupiter.params.provider.ValueSource;
    2626import org.openstreetmap.josm.testutils.JOSMTestRules;
     27import org.openstreetmap.josm.testutils.annotations.I18n;
    2728import org.openstreetmap.josm.tools.UncheckedParseException;
    2829
    2930/**
    3031 * Unit tests of {@link DateUtils} class.
    3132 */
     33@I18n
    3234public class DateUtilsTest {
    33 
    34     /**
    35      * Set the timezone and timeout.
    36      * <p>
    37      * Timeouts need to be disabled because we change the time zone.
    38      */
    39     @RegisterExtension
    40     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    41     public JOSMTestRules test = new JOSMTestRules().i18n().preferences();
    42 
    4335    /**
    4436     * Tests that {@code DateUtils} satisfies utility class criteria.
    4537     * @throws ReflectiveOperationException if an error occurs
  • core/test/unit/org/openstreetmap/josm/TestUtils.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/test/unit/org/openstreetmap/josm/TestUtils.java b/core/test/unit/org/openstreetmap/josm/TestUtils.java
    a b  
    658658
    659659    /**
    660660     * Determines if OSM DEV_API credential have been provided. Required for functional tests.
    661      * @return {@code true} if {@code osm.username} and {@code osm.password} have been defined on the command line
     661     * @return {@code true} if {@code osm.oauth2} have been defined on the command line
    662662     */
    663663    public static boolean areCredentialsProvided() {
    664         return Utils.getSystemProperty("osm.username") != null && Utils.getSystemProperty("osm.password") != null;
     664        return Utils.getSystemProperty("osm.oauth2") != null;
    665665    }
    666666
    667667    /**
  • core/ivy.xml

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/core/ivy.xml b/core/ivy.xml
    a b  
    3535        <dependency conf="api->default" org="com.drewnoakes" name="metadata-extractor" rev="2.18.0" transitive="false"/>
    3636        <dependency conf="api->default" org="com.formdev" name="svgSalamander" rev="1.1.4"/>
    3737        <dependency conf="api->default" org="ch.poole" name="OpeningHoursParser" rev="0.27.0"/>
    38         <dependency conf="api->default" org="oauth.signpost" name="signpost-core" rev="2.1.1"/>
    3938        <!-- Don't forget to update org.openstreetmap.josm.tools.Tag2Link#PREF_SOURCE -->
    4039        <dependency conf="api->default" org="org.webjars.npm" name="tag2link" rev="2022.11.28"/>
    4140        <!-- sources->sources -->
     
    5251        <dependency conf="sources->sources" org="com.drewnoakes" name="metadata-extractor" rev="2.18.0" transitive="false"/>
    5352        <dependency conf="sources->sources" org="com.formdev" name="svgSalamander" rev="1.1.4"/>
    5453        <dependency conf="sources->sources" org="ch.poole" name="OpeningHoursParser" rev="0.27.0"/>
    55         <dependency conf="sources->sources" org="oauth.signpost" name="signpost-core" rev="2.1.1"/>
    5654        <dependency conf="sources->default" org="org.webjars.npm" name="tag2link" rev="2022.11.28"/><!-- sources->default sic! (tag2link-sources.jar is empty, see #19335) -->
    5755        <!-- commonslang->default -->
    5856        <dependency conf="commonslang->default" org="org.apache.commons" name="commons-lang3" rev="3.13.0"/>
  • plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java
    a b  
    4040import javax.swing.border.EtchedBorder;
    4141
    4242import org.netbeans.spi.keyring.KeyringProvider;
    43 import org.openstreetmap.josm.data.oauth.OAuthToken;
    4443import org.openstreetmap.josm.gui.MainApplication;
    4544import org.openstreetmap.josm.gui.util.WindowGeometry;
    4645import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    4746import org.openstreetmap.josm.io.DefaultProxySelector;
    48 import org.openstreetmap.josm.io.OsmApi;
    4947import org.openstreetmap.josm.io.auth.CredentialsAgentException;
    5048import org.openstreetmap.josm.io.auth.CredentialsManager;
    5149import org.openstreetmap.josm.spi.preferences.Config;
     
    5553
    5654public class InitializationWizard extends JDialog {
    5755
    58     protected boolean canceled = false;
     56    protected boolean canceled;
    5957    protected JButton btnCancel, btnBack, btnNext;
    6058    protected Action nextAction, finishAction;
    6159    protected JPanel cardPanel;
     
    6664    private CardLayout cardLayout;
    6765   
    6866    public InitializationWizard() {
    69         super(JOptionPane.getFrameForComponent(MainApplication.getMainFrame()), tr("Native password manager plugin"), ModalityType.DOCUMENT_MODAL);
     67        super(JOptionPane.getFrameForComponent(MainApplication.getMainFrame()),
     68                tr("Native password manager plugin"), ModalityType.DOCUMENT_MODAL);
    7069        build();
    7170        NPMType npm = detectNativePasswordManager();
    7271        WizardPanel firstPanel;
     
    145144        /* The action to execute, when the user finall hits 'OK' and not 'Cancel' */
    146145        void onOkAction();
    147146    }
    148    
    149     abstract private static class AbstractWizardPanel implements WizardPanel {
     147
     148    private abstract static class AbstractWizardPanel implements WizardPanel {
    150149       
    151150        /**
    152151         * Put a logo to the left, as is customary for wizard dialogs
     
    174173            return getClass().getCanonicalName();
    175174        }
    176175
    177         abstract protected JPanel getContentPanel();
     176        protected abstract JPanel getContentPanel();
    178177    }
    179178   
    180179    private static class NothingFoundPanel extends AbstractWizardPanel {
     
    228227   
    229228    private static class SelectionPanel extends AbstractWizardPanel implements ActionListener {
    230229       
    231         private NPMType type;
    232         private InitializationWizard wizard;
     230        private final NPMType type;
     231        private final InitializationWizard wizard;
    233232       
    234233        private JRadioButton rbManage, rbPlain;
    235234               
     
    349348        public void onOkAction() {
    350349           
    351350            CredentialsManager cm = CredentialsManager.getInstance();
    352            
    353             String server_username = Config.getPref().get("osm-server.username", null);
    354             String server_password = Config.getPref().get("osm-server.password", null);
    355             if (server_username != null || server_password != null) {
    356                 try {
    357                     cm.store(RequestorType.SERVER, OsmApi.getOsmApi().getHost(), new PasswordAuthentication(string(server_username), toCharArray(server_password)));
    358                     if (rbClear.isSelected()) {
    359                         Config.getPref().put("osm-server.username", null);
    360                         Config.getPref().put("osm-server.password", null);
    361                     }
    362                 } catch (CredentialsAgentException ex) {
    363                     Logging.error(ex);
    364                 }
    365             }
    366            
    367             String proxy_username = Config.getPref().get(DefaultProxySelector.PROXY_USER, null);
    368             String proxy_password = Config.getPref().get(DefaultProxySelector.PROXY_PASS, null);
    369             String proxy_host = Config.getPref().get(DefaultProxySelector.PROXY_HTTP_HOST, null);
    370             if (proxy_username != null || proxy_password != null) {
     351
     352            String proxyUsername = Config.getPref().get(DefaultProxySelector.PROXY_USER, null);
     353            String proxyPassword = Config.getPref().get(DefaultProxySelector.PROXY_PASS, null);
     354            String proxyHost = Config.getPref().get(DefaultProxySelector.PROXY_HTTP_HOST, null);
     355            if (proxyUsername != null || proxyPassword != null) {
    371356                try {
    372                     cm.store(RequestorType.PROXY, proxy_host, new PasswordAuthentication(string(proxy_username), toCharArray(proxy_password)));
     357                    cm.store(RequestorType.PROXY, proxyHost, new PasswordAuthentication(string(proxyUsername), toCharArray(proxyPassword)));
    373358                    if (rbClear.isSelected()) {
    374359                        Config.getPref().put(DefaultProxySelector.PROXY_USER, null);
    375360                        Config.getPref().put(DefaultProxySelector.PROXY_PASS, null);
     
    378363                    Logging.error(ex);
    379364                }
    380365            }
    381            
    382             String oauth_key = Config.getPref().get("oauth.access-token.key", null);
    383             String oauth_secret = Config.getPref().get("oauth.access-token.secret", null);
    384             if (oauth_key != null || oauth_secret != null) {
    385                 try {
    386                     cm.storeOAuthAccessToken(new OAuthToken(string(oauth_key), string(oauth_secret)));
    387                     if (rbClear.isSelected()) {
    388                         Config.getPref().put("oauth.access-token.key", null);
    389                         Config.getPref().put("oauth.access-token.secret", null);
    390                     }
    391                 } catch (CredentialsAgentException ex) {
    392                     Logging.error(ex);
    393                 }
    394             }
    395366        }
    396367    }
    397368
    398     private final static String NPM = "Native Password Manager Plugin: ";
     369    private static final String NPM = "Native Password Manager Plugin: ";
    399370
    400371    private static NPMType detectNativePasswordManager() {
    401372        NPMType[] potentialManagers;
     
    444415                            new Dimension(600,400)
    445416                    )
    446417            ).applySafe(this);
    447         } else if (!visible && isShowing()){
     418        } else if (isShowing()){
    448419            new WindowGeometry(this).remember(getClass().getName() + ".geometry");
    449420        }
    450421        super.setVisible(visible);
     
    492463        @Override
    493464        public void actionPerformed(ActionEvent evt) {
    494465            if (panelIndex <= 0)
    495                 throw new RuntimeException();
     466                // Java 9 will let us pass the panelIndex by itself
     467                throw new IndexOutOfBoundsException("Index out of range: " + panelIndex);
    496468            panelIndex--;
    497469            cardLayout.show(cardPanel, panels.get(panelIndex).getId());
    498470            updateButtons();
  • plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java
    a b  
    2424import org.openstreetmap.josm.data.oauth.OAuth20Exception;
    2525import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    2626import org.openstreetmap.josm.data.oauth.OAuth20Token;
    27 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2827import org.openstreetmap.josm.data.oauth.OAuthVersion;
    2928import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    3029import org.openstreetmap.josm.io.DefaultProxySelector;
     
    5150     * In contrast, this cache avoids read request the backend in general.
    5251     */
    5352    private final Map<RequestorType, PasswordAuthentication> credentialsCache = new EnumMap<>(RequestorType.class);
    54     private OAuthToken oauthCache;
     53
    5554
    5655    /**
    5756     * Create a new {@link NPMCredentialsAgent}
     
    188187        }
    189188    }
    190189
    191     @Override
    192     public OAuthToken lookupOAuthAccessToken() {
    193         if (oauthCache != null)
    194             return oauthCache;
    195         String prolog = getOAuthDescriptor();
    196         char[] key = getProvider().read(prolog+".key");
    197         char[] secret = getProvider().read(prolog+".secret");
    198         return new OAuthToken(stringNotNull(key), stringNotNull(secret));
    199     }
    200 
    201190    @Override
    202191    public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
    203192        String prolog = getOAuthDescriptor();
     
    221210        return null;
    222211    }
    223212
    224     @Override
    225     public void storeOAuthAccessToken(OAuthToken oat) {
    226         String key, secret;
    227         if (oat == null) {
    228             key = null;
    229             secret = null;
    230         } else {
    231             key = oat.getKey();
    232             secret = oat.getSecret();
    233         }
    234         String prolog = getOAuthDescriptor();
    235         if (key == null || key.isEmpty() || secret == null || secret.isEmpty()) {
    236             getProvider().delete(prolog+".key");
    237             getProvider().delete(prolog+".secret");
    238             oauthCache = null;
    239         } else {
    240             getProvider().save(prolog+".key", key.toCharArray(), tr("JOSM/OAuth/OSM API/Key"));
    241             getProvider().save(prolog+".secret", secret.toCharArray(), tr("JOSM/OAuth/OSM API/Secret"));
    242             oauthCache = new OAuthToken(key, secret);
    243         }
    244     }
    245 
    246213    @Override
    247214    public void storeOAuthAccessToken(String host, IOAuthToken accessToken) {
    248215        String prolog = getOAuthDescriptor();
  • plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java b/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java
    a b  
    1212import javax.swing.text.html.HTMLEditorKit;
    1313
    1414import org.openstreetmap.josm.data.oauth.IOAuthToken;
    15 import org.openstreetmap.josm.data.oauth.OAuthToken;
    1615import org.openstreetmap.josm.gui.io.CredentialDialog;
    1716import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    1817import org.openstreetmap.josm.io.DefaultProxySelector;
     
    8281        }
    8382    }
    8483
    85     /**
    86      * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
    87      * Access Token is currently managed by this CredentialManager.
    88      *
    89      * @return the current OAuth Access Token to access the OSM server.
    90      */
    91     @Override
    92     public OAuthToken lookupOAuthAccessToken() {
    93         String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);
    94         String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);
    95         if (accessTokenKey == null && accessTokenSecret == null)
    96             return null;
    97         return new OAuthToken(accessTokenKey, accessTokenSecret);
    98     }
    99 
    10084    @Override
    10185    public IOAuthToken lookupOAuthAccessToken(String host) {
    10286        throw new UnsupportedOperationException("SDS does not support OAuth tokens");
     
    126110        return tr("Save user and password (unencrypted)");
    127111    }
    128112
    129     @Override
    130     public void storeOAuthAccessToken(OAuthToken accessToken) {
    131         // no-op
    132     }
    133 
    134113    @Override
    135114    public void storeOAuthAccessToken(String host, IOAuthToken accessToken) {
    136115        throw new UnsupportedOperationException("SDS does not support OAuth tokens");