mx.bigdata.t4j.TwitterStreamImpl.java Source code

Java tutorial

Introduction

Here is the source code for mx.bigdata.t4j.TwitterStreamImpl.java

Source

/*
 * Copyright 2007 Yusuke Yamamoto
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package mx.bigdata.t4j;

import twitter4j.*;
import twitter4j.auth.Authorization;
import twitter4j.conf.Configuration;
import twitter4j.auth.AccessToken;
import twitter4j.auth.NullAuthorization;
import twitter4j.auth.OAuthSupport;
import twitter4j.auth.OAuthAuthorization;
import twitter4j.internal.http.HttpClientWrapper;
import twitter4j.internal.http.HttpClientWrapperConfiguration;
import twitter4j.internal.http.HttpParameter;
import twitter4j.internal.util.T4JInternalStringUtil;
import twitter4j.internal.http.HttpResponse;
import twitter4j.internal.json.DataObjectFactoryUtil;

import java.net.SocketTimeoutException;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import static twitter4j.internal.http.HttpResponseCode.FORBIDDEN;
import static twitter4j.internal.http.HttpResponseCode.NOT_ACCEPTABLE;

/**
 * A java representation of the <a href="http://dev.twitter.com/pages/streaming_api_methods">Streaming API: Methods</a><br>
 * Note that this class is NOT compatible with Google App Engine as GAE
 * is not capable of handling requests longer than 30 seconds.
 *
 * @author Yusuke Yamamoto - yusuke at mac.com
 * @since Twitter4J 2.0.4
 */
class TwitterStreamImpl implements TwitterStream {
    protected Authorization auth;
    protected Configuration conf;

    private final HttpClientWrapper http;
    private final static Logger logger = Logger.getLogger(TwitterStreamImpl.class.getName());

    private final StreamListener streamListener;

    TwitterStreamImpl(Configuration conf, Authorization auth, StreamListener streamListener) {
        //super(conf, auth);
        this.conf = conf;
        this.auth = auth;
        init();
        this.http = new HttpClientWrapper(new StreamingReadTimeoutConfiguration(conf));
        this.streamListener = streamListener;
    }

    TwitterStreamImpl(Configuration conf, StreamListener streamListener) {
        //super(conf);
        this.conf = conf;
        init();
        this.http = new HttpClientWrapper(new StreamingReadTimeoutConfiguration(conf));
        this.streamListener = streamListener;
    }

    private void init() {
        if (null == auth) {
            // try to populate OAuthAuthorization if available in the configuration
            String consumerKey = conf.getOAuthConsumerKey();
            String consumerSecret = conf.getOAuthConsumerSecret();
            // try to find oauth tokens in the configuration
            if (null != consumerKey && null != consumerSecret) {
                OAuthAuthorization oauth = new OAuthAuthorization(conf);
                String accessToken = conf.getOAuthAccessToken();
                String accessTokenSecret = conf.getOAuthAccessTokenSecret();
                if (null != accessToken && null != accessTokenSecret) {
                    oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
                }
                this.auth = oauth;
            } else {
                this.auth = NullAuthorization.getInstance();
            }
        }
    }
    /* Streaming API */

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer firehose(final int count) {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getFirehoseStream(count);
            }
        }, streamListener);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getFirehoseStream(int count) throws TwitterException {
        ensureAuthorizationEnabled();
        return getCountStream("statuses/firehose.json", count);
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer links(final int count) {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getLinksStream(count);
            }
        }, streamListener);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getLinksStream(int count) throws TwitterException {
        ensureAuthorizationEnabled();
        return getCountStream("statuses/links.json", count);
    }

    private StatusStream getCountStream(String relativeUrl, int count) throws TwitterException {
        ensureAuthorizationEnabled();
        try {
            return new StatusStreamImpl(http.post(conf.getStreamBaseURL() + relativeUrl,
                    new HttpParameter[] { new HttpParameter("count", String.valueOf(count)) }, auth));
        } catch (IOException e) {
            throw new TwitterException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer retweet() {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getRetweetStream();
            }
        }, streamListener);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getRetweetStream() throws TwitterException {
        ensureAuthorizationEnabled();
        try {
            return new StatusStreamImpl(
                    http.post(conf.getStreamBaseURL() + "statuses/retweet.json", new HttpParameter[] {}, auth));
        } catch (IOException e) {
            throw new TwitterException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer sample() {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getSampleStream();
            }
        }, streamListener);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getSampleStream() throws TwitterException {
        ensureAuthorizationEnabled();
        try {
            return new StatusStreamImpl(http.post(conf.getStreamBaseURL() + "statuses/sample.json",
                    new HttpParameter[] { new HttpParameter("delimited", "length") }, auth));
        } catch (IOException e) {
            throw new TwitterException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer user() {
        return user(null);
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer user(final String[] track) {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getUserStream(track);
            }
        }, streamListener);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getUserStream() throws TwitterException {
        return getUserStream(null);
    }

    /**
     * {@inheritDoc}
     */
    public StatusStream getUserStream(String[] track) throws TwitterException {
        ensureAuthorizationEnabled();
        try {
            List<HttpParameter> params = new ArrayList<HttpParameter>();
            if (conf.isUserStreamRepliesAllEnabled()) {
                params.add(new HttpParameter("replies", "all"));
            }
            if (null != track) {
                params.add(new HttpParameter("track", T4JInternalStringUtil.join(track)));
            }
            return new StatusStreamImpl(http.post(conf.getUserStreamBaseURL() + "user.json",
                    params.toArray(new HttpParameter[params.size()]), auth));
        } catch (IOException e) {
            throw new TwitterException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer site(final boolean withFollowings, final long[] follow) {
        ensureOAuthEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                try {
                    return new StatusStreamImpl(getSiteStream(withFollowings, follow));
                } catch (IOException e) {
                    throw new TwitterException(e);
                }
            }
        }, streamListener);
    }

    InputStream getSiteStream(boolean withFollowings, long[] follow) throws TwitterException {
        ensureOAuthEnabled();
        return http.post(conf.getSiteStreamBaseURL() + "site.json",
                new HttpParameter[] { new HttpParameter("with", withFollowings ? "followings" : "user"),
                        new HttpParameter("follow", T4JInternalStringUtil.join(follow)) },
                auth).asStream();
    }

    /**
     * {@inheritDoc}
     */
    public TwitterStreamConsumer filter(final FilterQuery query) {
        ensureAuthorizationEnabled();
        ensureListenerIsSet();
        return startHandler(new StatusStreamProvider() {
            public StatusStream getStream() throws TwitterException {
                return getFilterStream(query);
            }
        }, streamListener);
    }

    StatusStream getFilterStream(FilterQuery query) throws TwitterException {
        ensureAuthorizationEnabled();
        try {
            List<HttpParameter> params = new ArrayList(Arrays.asList(query.asHttpParameterArray()));
            params.add(new HttpParameter("delimited", "length"));
            return new StatusStreamImpl(http.post(conf.getStreamBaseURL() + "statuses/filter.json",
                    params.toArray(new HttpParameter[0]), auth));
        } catch (IOException e) {
            throw new TwitterException(e);
        }
    }

    protected final void ensureAuthorizationEnabled() {
        if (!auth.isEnabled()) {
            throw new IllegalStateException("Authentication credentials are missing. "
                    + "See http://twitter4j.org/configuration.html for the detail.");
        }
    }

    protected final void ensureOAuthEnabled() {
        if (!(auth instanceof OAuthAuthorization)) {
            throw new IllegalStateException("OAuth required. Authentication credentials are missing."
                    + " See http://twitter4j.org/configuration.html for the detail.");
        }
    }

    /**
     * check if any listener is set. Throws IllegalStateException if no listener is set.
     *
     * @throws IllegalStateException when no listener is set.
     */

    private void ensureListenerIsSet() {
        if (streamListener == null) {
            throw new IllegalStateException("No listener is set.");
        }
    }

    private TwitterStreamConsumer startHandler(StatusStreamProvider provider, StreamListener listener) {
        TwitterStreamConsumer handler = new TwitterStreamConsumerImpl(provider, listener);
        handler.start();
        return handler;
    }

    private static final class StatusStreamImpl implements StatusStream {

        private final DataInputStream in;
        private final HttpResponse response;

        StatusStreamImpl(InputStream stream, HttpResponse response) throws IOException {
            this.in = new DataInputStream(stream);
            this.response = response;
        }

        StatusStreamImpl(InputStream stream) throws IOException {
            this(stream, null);
        }

        StatusStreamImpl(HttpResponse response) throws IOException {
            this(response.asStream(), response);
        }

        public DataInputStream getInputStream() {
            return in;
        }

        public void close() throws IOException {
            in.close();
            if (response != null) {
                response.disconnect();
            }
        }
    }
}

class StreamingReadTimeoutConfiguration implements HttpClientWrapperConfiguration {
    Configuration nestedConf;

    StreamingReadTimeoutConfiguration(Configuration httpConf) {
        this.nestedConf = httpConf;
    }

    public String getHttpProxyHost() {
        return nestedConf.getHttpProxyHost();
    }

    public int getHttpProxyPort() {
        return nestedConf.getHttpProxyPort();
    }

    public String getHttpProxyUser() {
        return nestedConf.getHttpProxyUser();
    }

    public String getHttpProxyPassword() {
        return nestedConf.getHttpProxyPassword();
    }

    public int getHttpConnectionTimeout() {
        return nestedConf.getHttpConnectionTimeout();
    }

    public int getHttpReadTimeout() {
        // this is the trick that overrides connection timeout
        return nestedConf.getHttpStreamingReadTimeout();
    }

    public int getHttpRetryCount() {
        return nestedConf.getHttpRetryCount();
    }

    public int getHttpRetryIntervalSeconds() {
        return nestedConf.getHttpRetryIntervalSeconds();
    }

    public int getHttpMaxTotalConnections() {
        return nestedConf.getHttpMaxTotalConnections();
    }

    public int getHttpDefaultMaxPerRoute() {
        return nestedConf.getHttpDefaultMaxPerRoute();
    }

    public Map<String, String> getRequestHeaders() {
        return nestedConf.getRequestHeaders();
    }

    public boolean isPrettyDebugEnabled() {
        return nestedConf.isPrettyDebugEnabled();
    }

    public boolean isGZIPEnabled() {
        return nestedConf.isGZIPEnabled();
    }

}