org.hornetq.integration.twitter.impl.IncomingTweetsHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.hornetq.integration.twitter.impl.IncomingTweetsHandler.java

Source

/*
 * Copyright 2005-2014 Red Hat, Inc.
 * Red Hat licenses this file to you 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 org.hornetq.integration.twitter.impl;

import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.hornetq.api.core.SimpleString;
import org.hornetq.core.persistence.StorageManager;
import org.hornetq.core.postoffice.Binding;
import org.hornetq.core.postoffice.PostOffice;
import org.hornetq.core.server.ConnectorService;
import org.hornetq.core.server.ServerMessage;
import org.hornetq.core.server.impl.ServerMessageImpl;
import org.hornetq.integration.twitter.TwitterConstants;
import org.hornetq.twitter.HornetQTwitterLogger;
import org.hornetq.utils.ConfigurationHelper;
import twitter4j.GeoLocation;
import twitter4j.Paging;
import twitter4j.Place;
import twitter4j.ResponseList;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;

/**
 * IncomingTweetsHandler consumes from twitter and forwards to the
 * configured HornetQ address.
 */
public class IncomingTweetsHandler implements ConnectorService {
    private final String connectorName;

    private final String consumerKey;

    private final String consumerSecret;

    private final String accessToken;

    private final String accessTokenSecret;

    private final String queueName;

    private final int intervalSeconds;

    private final StorageManager storageManager;

    private final PostOffice postOffice;

    private Paging paging;

    private Twitter twitter;

    private boolean isStarted = false;

    private final ScheduledExecutorService scheduledPool;

    private ScheduledFuture<?> scheduledFuture;

    public IncomingTweetsHandler(final String connectorName, final Map<String, Object> configuration,
            final StorageManager storageManager, final PostOffice postOffice,
            final ScheduledExecutorService scheduledThreadPool) {
        this.connectorName = connectorName;
        this.consumerKey = ConfigurationHelper.getStringProperty(TwitterConstants.CONSUMER_KEY, null,
                configuration);
        this.consumerSecret = ConfigurationHelper.getStringProperty(TwitterConstants.CONSUMER_SECRET, null,
                configuration);
        this.accessToken = ConfigurationHelper.getStringProperty(TwitterConstants.ACCESS_TOKEN, null,
                configuration);
        this.accessTokenSecret = ConfigurationHelper.getStringProperty(TwitterConstants.ACCESS_TOKEN_SECRET, null,
                configuration);
        this.queueName = ConfigurationHelper.getStringProperty(TwitterConstants.QUEUE_NAME, null, configuration);
        Integer intervalSeconds = ConfigurationHelper.getIntProperty(TwitterConstants.INCOMING_INTERVAL, 0,
                configuration);
        if (intervalSeconds > 0) {
            this.intervalSeconds = intervalSeconds;
        } else {
            this.intervalSeconds = TwitterConstants.DEFAULT_POLLING_INTERVAL_SECS;
        }
        this.storageManager = storageManager;
        this.postOffice = postOffice;
        this.scheduledPool = scheduledThreadPool;
    }

    public void start() throws Exception {
        Binding b = postOffice.getBinding(new SimpleString(queueName));
        if (b == null) {
            throw new Exception(connectorName + ": queue " + queueName + " not found");
        }

        paging = new Paging();
        TwitterFactory tf = new TwitterFactory();
        this.twitter = tf.getOAuthAuthorizedInstance(this.consumerKey, this.consumerSecret,
                new AccessToken(this.accessToken, this.accessTokenSecret));
        this.twitter.verifyCredentials();

        // getting latest ID
        this.paging.setCount(TwitterConstants.FIRST_ATTEMPT_PAGE_SIZE);

        // If I used annotations here, it won't compile under JDK 1.7
        ResponseList res = this.twitter.getHomeTimeline(paging);
        this.paging.setSinceId(((Status) res.get(0)).getId());
        HornetQTwitterLogger.LOGGER
                .debug(connectorName + " initialise(): got latest ID: " + this.paging.getSinceId());

        // TODO make page size configurable
        this.paging.setCount(TwitterConstants.DEFAULT_PAGE_SIZE);

        scheduledFuture = this.scheduledPool.scheduleWithFixedDelay(new TweetsRunnable(), intervalSeconds,
                intervalSeconds, TimeUnit.SECONDS);
        isStarted = true;
    }

    public void stop() throws Exception {
        if (!isStarted) {
            return;
        }
        scheduledFuture.cancel(true);
        paging = null;
        isStarted = false;
    }

    public boolean isStarted() {
        return isStarted;
    }

    private void poll() throws Exception {
        // get new tweets
        // If I used annotations here, it won't compile under JDK 1.7
        ResponseList res = this.twitter.getHomeTimeline(paging);

        if (res == null || res.size() == 0) {
            return;
        }

        for (int i = res.size() - 1; i >= 0; i--) {
            Status status = (Status) res.get(i);

            ServerMessage msg = new ServerMessageImpl(this.storageManager.generateUniqueID(),
                    TwitterConstants.INITIAL_MESSAGE_BUFFER_SIZE);
            msg.setAddress(new SimpleString(this.queueName));
            msg.setDurable(true);
            msg.encodeMessageIDToBuffer();

            putTweetIntoMessage(status, msg);

            this.postOffice.route(msg, false);
            HornetQTwitterLogger.LOGGER.debug(connectorName + ": routed: " + status.toString());
        }

        this.paging.setSinceId(((Status) res.get(0)).getId());
        HornetQTwitterLogger.LOGGER.debug(connectorName + ": update latest ID: " + this.paging.getSinceId());
    }

    private void putTweetIntoMessage(final Status status, final ServerMessage msg) {
        msg.getBodyBuffer().writeString(status.getText());
        msg.putLongProperty(TwitterConstants.KEY_ID, status.getId());
        msg.putStringProperty(TwitterConstants.KEY_SOURCE, status.getSource());

        msg.putLongProperty(TwitterConstants.KEY_CREATED_AT, status.getCreatedAt().getTime());
        msg.putBooleanProperty(TwitterConstants.KEY_IS_TRUNCATED, status.isTruncated());
        msg.putLongProperty(TwitterConstants.KEY_IN_REPLY_TO_STATUS_ID, status.getInReplyToStatusId());
        msg.putIntProperty(TwitterConstants.KEY_IN_REPLY_TO_USER_ID, status.getInReplyToUserId());
        msg.putBooleanProperty(TwitterConstants.KEY_IS_FAVORITED, status.isFavorited());
        msg.putBooleanProperty(TwitterConstants.KEY_IS_RETWEET, status.isRetweet());
        msg.putObjectProperty(TwitterConstants.KEY_CONTRIBUTORS, status.getContributors());
        GeoLocation gl;
        if ((gl = status.getGeoLocation()) != null) {
            msg.putDoubleProperty(TwitterConstants.KEY_GEO_LOCATION_LATITUDE, gl.getLatitude());
            msg.putDoubleProperty(TwitterConstants.KEY_GEO_LOCATION_LONGITUDE, gl.getLongitude());
        }
        Place place;
        if ((place = status.getPlace()) != null) {
            msg.putStringProperty(TwitterConstants.KEY_PLACE_ID, place.getId());
        }
    }

    public String getName() {
        return connectorName;
    }

    private final class TweetsRunnable implements Runnable {
        /**
         * TODO streaming API support
         * TODO rate limit support
         */
        public void run() {
            // Avoid canceling the task with RuntimeException
            try {
                poll();
            } catch (Throwable t) {
                HornetQTwitterLogger.LOGGER.errorPollingTwitter(t);
            }
        }
    }
}