001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.oauth;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.io.IOException;
008
009import javax.swing.JOptionPane;
010
011import org.openstreetmap.josm.Main;
012import org.openstreetmap.josm.data.oauth.OAuthParameters;
013import org.openstreetmap.josm.data.oauth.OAuthToken;
014import org.openstreetmap.josm.gui.HelpAwareOptionPane;
015import org.openstreetmap.josm.gui.PleaseWaitRunnable;
016import org.openstreetmap.josm.gui.help.HelpUtil;
017import org.openstreetmap.josm.gui.util.GuiHelper;
018import org.openstreetmap.josm.io.OsmTransferCanceledException;
019import org.openstreetmap.josm.io.OsmTransferException;
020import org.openstreetmap.josm.tools.CheckParameterUtil;
021import org.xml.sax.SAXException;
022
023/**
024 * Asynchronous task for retrieving an Access Token.
025 *
026 */
027public class RetrieveAccessTokenTask extends PleaseWaitRunnable {
028
029    private boolean canceled;
030    private OAuthToken accessToken;
031    private final OAuthParameters parameters;
032    private OsmOAuthAuthorizationClient client;
033    private final OAuthToken requestToken;
034    private final Component parent;
035
036    /**
037     * Creates the task
038     *
039     * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog
040     * is displayed
041     * @param parameters the OAuth parameters. Must not be null.
042     * @param requestToken the request token for which an Access Token is retrieved. Must not be null.
043     * @throws IllegalArgumentException if parameters is null.
044     * @throws IllegalArgumentException if requestToken is null.
045     */
046    public RetrieveAccessTokenTask(Component parent, OAuthParameters parameters, OAuthToken requestToken) {
047        super(parent, tr("Retrieving OAuth Access Token..."), false /* don't ignore exceptions */);
048        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
049        CheckParameterUtil.ensureParameterNotNull(requestToken, "requestToken");
050        this.parameters = parameters;
051        this.requestToken = requestToken;
052        this.parent = parent;
053    }
054
055    @Override
056    protected void cancel() {
057        canceled = true;
058        synchronized (this) {
059            if (client != null) {
060                client.cancel();
061            }
062        }
063    }
064
065    @Override
066    protected void finish() { /* not used in this task */}
067
068    protected void alertRetrievingAccessTokenFailed(OsmOAuthAuthorizationException e) {
069        HelpAwareOptionPane.showOptionDialog(
070                parent,
071                tr(
072                        "<html>Retrieving an OAuth Access Token from ''{0}'' failed.</html>",
073                        parameters.getAccessTokenUrl()
074                ),
075                tr("Request Failed"),
076                JOptionPane.ERROR_MESSAGE,
077                HelpUtil.ht("/OAuth#NotAuthorizedException")
078        );
079    }
080
081    @Override
082    protected void realRun() throws SAXException, IOException, OsmTransferException {
083        try {
084            synchronized (this) {
085                client = new OsmOAuthAuthorizationClient(parameters, requestToken);
086            }
087            accessToken = client.getAccessToken(getProgressMonitor().createSubTaskMonitor(0, false));
088        } catch (OsmTransferCanceledException e) {
089            return;
090        } catch (final OsmOAuthAuthorizationException e) {
091            Main.error(e);
092            GuiHelper.runInEDT(new Runnable() {
093                @Override
094                public void run() {
095                    alertRetrievingAccessTokenFailed(e);
096                }
097            });
098            accessToken = null;
099        } finally {
100            synchronized (this) {
101                client = null;
102            }
103        }
104    }
105
106    /**
107     * Replies true if the task was canceled.
108     *
109     * @return {@code true} if user aborted operation
110     */
111    public boolean isCanceled() {
112        return canceled;
113    }
114
115    /**
116     * Replies the retrieved Access Token. null, if something went wrong.
117     *
118     * @return the retrieved Access Token
119     */
120    public OAuthToken getAccessToken() {
121        return accessToken;
122    }
123}