001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.server;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import org.openstreetmap.josm.Main;
007import org.openstreetmap.josm.data.Preferences;
008import org.openstreetmap.josm.data.oauth.OAuthToken;
009import org.openstreetmap.josm.io.auth.CredentialsAgent;
010import org.openstreetmap.josm.io.auth.CredentialsAgentException;
011import org.openstreetmap.josm.tools.CheckParameterUtil;
012
013/**
014 * Class holding OAuth access token key and secret.
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 pref the preferences. Must not be null.
146     * @param cm the credential manager. Must not be null.
147     * @throws IllegalArgumentException if cm is null
148     */
149    public void init(Preferences pref, CredentialsAgent cm) {
150        CheckParameterUtil.ensureParameterNotNull(pref, "pref");
151        CheckParameterUtil.ensureParameterNotNull(cm, "cm");
152        OAuthToken token = null;
153        try {
154            token = cm.lookupOAuthAccessToken();
155        } catch (CredentialsAgentException e) {
156            Main.error(e);
157            Main.warn(tr("Failed to retrieve OAuth Access Token from credential manager"));
158            Main.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
159        }
160        saveToPreferences = pref.getBoolean("oauth.access-token.save-to-preferences", true);
161        if (token != null) {
162            accessTokenKey = token.getKey();
163            accessTokenSecret = token.getSecret();
164        }
165    }
166
167    /**
168     * Saves the content of this holder to the preferences and a credential store managed
169     * by a credential manager.
170     *
171     * @param preferences the preferences. Must not be null.
172     * @param cm the credentials manager. Must not be null.
173     * @throws IllegalArgumentException if preferences is null
174     * @throws IllegalArgumentException if cm is null
175     */
176    public void save(Preferences preferences, CredentialsAgent cm) {
177        CheckParameterUtil.ensureParameterNotNull(preferences, "preferences");
178        CheckParameterUtil.ensureParameterNotNull(cm, "cm");
179        preferences.put("oauth.access-token.save-to-preferences", saveToPreferences);
180        try {
181            if (!saveToPreferences) {
182                cm.storeOAuthAccessToken(null);
183            } else {
184                cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret));
185            }
186        } catch (CredentialsAgentException e) {
187            Main.error(e);
188            Main.warn(tr("Failed to store OAuth Access Token to credentials manager"));
189            Main.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
190        }
191    }
192
193    /**
194     * Clears the content of this holder
195     */
196    public void clear() {
197        accessTokenKey = null;
198        accessTokenSecret = null;
199    }
200}