001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.oauth;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import org.openstreetmap.josm.io.auth.CredentialsAgent;
007import org.openstreetmap.josm.io.auth.CredentialsAgentException;
008import org.openstreetmap.josm.spi.preferences.Config;
009import org.openstreetmap.josm.tools.CheckParameterUtil;
010import org.openstreetmap.josm.tools.Logging;
011
012/**
013 * Class holding OAuth access token key and secret.
014 * @since 12686 (moved from {@code gui.preferences.server} package)
015 */
016public class OAuthAccessTokenHolder {
017    private static OAuthAccessTokenHolder instance;
018
019    /**
020     * Replies the unique instance.
021     * @return The unique instance of {@code OAuthAccessTokenHolder}
022     */
023    public static synchronized OAuthAccessTokenHolder getInstance() {
024        if (instance == null) {
025            instance = new OAuthAccessTokenHolder();
026        }
027        return instance;
028    }
029
030    private boolean saveToPreferences;
031    private String accessTokenKey;
032    private String accessTokenSecret;
033
034    /**
035     * Replies true if current access token should be saved to the preferences file.
036     *
037     * @return true if current access token should be saved to the preferences file.
038     */
039    public boolean isSaveToPreferences() {
040        return saveToPreferences;
041    }
042
043    /**
044     * Sets whether the current access token should be saved to the preferences file.
045     *
046     * If true, the access token is saved in clear text to the preferences file. The same
047     * access token can therefore be used in multiple JOSM sessions.
048     *
049     * If false, the access token isn't saved to the preferences file. If JOSM is closed,
050     * the access token is lost and new token has to be generated by the OSM server the
051     * next time JOSM is used.
052     *
053     * @param saveToPreferences {@code true} to save to preferences file
054     */
055    public void setSaveToPreferences(boolean saveToPreferences) {
056        this.saveToPreferences = saveToPreferences;
057    }
058
059    /**
060     * Replies the access token key. null, if no access token key is currently set.
061     *
062     * @return the access token key
063     */
064    public String getAccessTokenKey() {
065        return accessTokenKey;
066    }
067
068    /**
069     * Sets the access token key. Pass in null to remove the current access token key.
070     *
071     * @param accessTokenKey the access token key
072     */
073    public void setAccessTokenKey(String accessTokenKey) {
074        this.accessTokenKey = accessTokenKey;
075    }
076
077    /**
078     * Replies the access token secret. null, if no access token secret is currently set.
079     *
080     * @return the access token secret
081     */
082    public String getAccessTokenSecret() {
083        return accessTokenSecret;
084    }
085
086    /**
087     * Sets the access token secret. Pass in null to remove the current access token secret.
088     *
089     * @param accessTokenSecret access token secret, or null
090     */
091    public void setAccessTokenSecret(String accessTokenSecret) {
092        this.accessTokenSecret = accessTokenSecret;
093    }
094
095    /**
096     * Replies the access token.
097     * @return the access token, can be {@code null}
098     */
099    public OAuthToken getAccessToken() {
100        if (!containsAccessToken())
101            return null;
102        return new OAuthToken(accessTokenKey, accessTokenSecret);
103    }
104
105    /**
106     * Sets the access token hold by this holder.
107     *
108     * @param accessTokenKey the access token key
109     * @param accessTokenSecret the access token secret
110     */
111    public void setAccessToken(String accessTokenKey, String accessTokenSecret) {
112        this.accessTokenKey = accessTokenKey;
113        this.accessTokenSecret = accessTokenSecret;
114    }
115
116    /**
117     * Sets the access token hold by this holder.
118     *
119     * @param token the access token. Can be null to clear the content in this holder.
120     */
121    public void setAccessToken(OAuthToken token) {
122        if (token == null) {
123            this.accessTokenKey = null;
124            this.accessTokenSecret = null;
125        } else {
126            this.accessTokenKey = token.getKey();
127            this.accessTokenSecret = token.getSecret();
128        }
129    }
130
131    /**
132     * Replies true if this holder contains an complete access token, consisting of an
133     * Access Token Key and an Access Token Secret.
134     *
135     * @return true if this holder contains an complete access token
136     */
137    public boolean containsAccessToken() {
138        return accessTokenKey != null && accessTokenSecret != null;
139    }
140
141    /**
142     * Initializes the content of this holder from the Access Token managed by the
143     * credential manager.
144     *
145     * @param cm the credential manager. Must not be null.
146     * @throws IllegalArgumentException if cm is null
147     */
148    public void init(CredentialsAgent cm) {
149        CheckParameterUtil.ensureParameterNotNull(cm, "cm");
150        OAuthToken token = null;
151        try {
152            token = cm.lookupOAuthAccessToken();
153        } catch (CredentialsAgentException e) {
154            Logging.error(e);
155            Logging.warn(tr("Failed to retrieve OAuth Access Token from credential manager"));
156            Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
157        }
158        saveToPreferences = Config.getPref().getBoolean("oauth.access-token.save-to-preferences", true);
159        if (token != null) {
160            accessTokenKey = token.getKey();
161            accessTokenSecret = token.getSecret();
162        }
163    }
164
165    /**
166     * Saves the content of this holder to the preferences and a credential store managed
167     * by a credential manager.
168     *
169     * @param cm the credentials manager. Must not be null.
170     * @throws IllegalArgumentException if cm is null
171     */
172    public void save(CredentialsAgent cm) {
173        CheckParameterUtil.ensureParameterNotNull(cm, "cm");
174        Config.getPref().putBoolean("oauth.access-token.save-to-preferences", saveToPreferences);
175        try {
176            if (!saveToPreferences) {
177                cm.storeOAuthAccessToken(null);
178            } else {
179                cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret));
180            }
181        } catch (CredentialsAgentException e) {
182            Logging.error(e);
183            Logging.warn(tr("Failed to store OAuth Access Token to credentials manager"));
184            Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
185        }
186    }
187
188    /**
189     * Clears the content of this holder
190     */
191    public void clear() {
192        accessTokenKey = null;
193        accessTokenSecret = null;
194    }
195}