net.awairo.favdler.oauth.TwitterOAuth.java Source code

Java tutorial

Introduction

Here is the source code for net.awairo.favdler.oauth.TwitterOAuth.java

Source

/*
 * FavDownloader
 *
 * (c) 2014 alalwww
 * https://github.com/alalwww
 *
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 */

package net.awairo.favdler.oauth;

import java.util.Optional;
import java.util.function.Consumer;

import lombok.extern.log4j.Log4j2;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.RequestToken;

import net.awairo.common.exception.AppException;
import net.awairo.common.javafx.FxUtils;
import net.awairo.common.javafx.MyTask;
import net.awairo.common.javafx.TaskExecutor;
import net.awairo.common.util.Desktop;
import net.awairo.favdler.twitter.TwitterAccessor;

/**
 * Twitter?.
 *
 * @author alalwww
 */
@Log4j2
/* package */final class TwitterOAuth {

    private static final String CALLBACK = "http://localhost:%s/auth";
    private final TaskExecutor executor = new TaskExecutor() {
    };

    private final OAuthCallbackReceiveServer server;

    private Optional<MyTask<RequestToken>> rTokenGetterTask = Optional.empty();
    private Optional<MyTask<TwitterAccessor>> aTokenGetterTask = Optional.empty();

    private Optional<Twitter> twitter = Optional.empty();
    private Optional<RequestToken> rToken = Optional.empty();

    private Optional<Consumer<TwitterAccessor>> succeededHandler = Optional.empty();
    private Optional<Consumer<Throwable>> failedHandler = Optional.empty();

    //------------------------------------------

    /**
     * Constructor.
     */
    public TwitterOAuth() {
        FxUtils.checkFxApplicationThread();

        server = new OAuthCallbackReceiveServer().ifRunning(this::createRequestTokenGetterTask)
                .ifRunning(() -> rTokenGetterTask.ifPresent(executor::execute)).ifFailed(this::cancel)
                .ifFailed(this::onFailed).ifSucceeded(this::createAccessTokenGetterTask)
                .ifSucceeded(() -> aTokenGetterTask.ifPresent(executor::execute)).ifDone(this::stopServer);
    }

    //------------------------------------------

    /**
     * ??.
     *
     * @param handler ?
     * @return ??
     */
    public TwitterOAuth onSucceeded(Consumer<TwitterAccessor> handler) {
        FxUtils.checkFxApplicationThread();

        succeededHandler = Optional.ofNullable(handler);
        return this;
    }

    /**
     * ??.
     *
     * @param handler ?
     * @return ??
     */
    public TwitterOAuth onFailed(Consumer<Throwable> handler) {
        FxUtils.checkFxApplicationThread();

        failedHandler = Optional.ofNullable(handler);
        return this;
    }

    //------------------------------------------

    /**
     * ?????.
     */
    public void cancel() {
        FxUtils.checkFxApplicationThread();

        rTokenGetterTask.ifPresent(task -> task.cancel());
        aTokenGetterTask.ifPresent(task -> task.cancel());

        rTokenGetterTask = Optional.empty();
        aTokenGetterTask = Optional.empty();

        stopServer();
        clearTwitterResources();
    }

    /**
     * ????.
     */
    public void start() {
        FxUtils.checkFxApplicationThread();

        twitter = Optional.ofNullable(new TwitterFactory().getInstance());
        server.restart();
    }

    //------------------------------------------

    private void createRequestTokenGetterTask() {
        if (!twitter.isPresent()) {
            log.debug(" twitter={}", twitter);
            return;
        }

        rTokenGetterTask = Optional.ofNullable(MyTask.of(getRequestToken(twitter.get())).ifFailed(this::cancel)
                .ifFailed(this::onFailed).ifSucceeded(this::setRequestToken).ifSucceeded(this::openTwitterOAuth)
                .ifDone(() -> rTokenGetterTask = Optional.empty()));
    }

    private void createAccessTokenGetterTask(String oauthVerifier) {
        if (!twitter.isPresent() || !rToken.isPresent()) {
            log.debug(" twitter={}, rToken={}", twitter, rToken);
            return;
        }

        Twitter t = twitter.get();
        RequestToken rt = rToken.get();

        aTokenGetterTask = Optional.ofNullable(MyTask.of(getTwitterAccessor(t, rt, oauthVerifier))
                .ifFailed(this::cancel).ifFailed(this::onFailed).ifSucceeded(this::onSucceeded)
                .ifDone(() -> aTokenGetterTask = Optional.empty()).ifDone(this::clearTwitterResources));
    }

    private MyTask.Function<RequestToken> getRequestToken(Twitter t) {
        return () -> {
            try {
                return t.getOAuthRequestToken(String.format(CALLBACK, server.getLocalPort()));
            } catch (TwitterException e) {
                throw new AppException(e);
            }
        };
    }

    private void setRequestToken(RequestToken rToken) {
        this.rToken = Optional.ofNullable(rToken);
    }

    private void openTwitterOAuth(RequestToken rToken) {
        Desktop.openURI(rToken.getAuthorizationURL());
    }

    private MyTask.Function<TwitterAccessor> getTwitterAccessor(Twitter t, RequestToken token,
            String oauthVerifier) {
        return () -> {
            t.getOAuthAccessToken(token, oauthVerifier);
            return new TwitterAccessor(t);
        };
    }

    private void stopServer() {
        server.cancel();
        server.reset();
    }

    private void clearTwitterResources() {
        rToken = Optional.empty();
        twitter = Optional.empty();
    }

    private void onFailed(Throwable t) {
        failedHandler.ifPresent(h -> h.accept(t));
    }

    private void onSucceeded(TwitterAccessor accessor) {
        succeededHandler.ifPresent(h -> h.accept(accessor));
    }

}