br.com.porcelli.hornetq.integration.twitter.outgoing.impl.OutgoingTwitterHandler.java Source code

Java tutorial

Introduction

Here is the source code for br.com.porcelli.hornetq.integration.twitter.outgoing.impl.OutgoingTwitterHandler.java

Source

/**
 * Copyright (c) 2010 Alexandre Porcelli <alexandre.porcelli@gmail.com>
 *
 * 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 br.com.porcelli.hornetq.integration.twitter.outgoing.impl;

import static br.com.porcelli.hornetq.integration.twitter.support.TweetMessageConverterSupport.buildMessage;

import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.hornetq.api.core.PropertyConversionException;
import org.hornetq.api.core.SimpleString;
import org.hornetq.core.filter.Filter;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.postoffice.Binding;
import org.hornetq.core.postoffice.PostOffice;
import org.hornetq.core.server.ConnectorService;
import org.hornetq.core.server.Consumer;
import org.hornetq.core.server.HandleStatus;
import org.hornetq.core.server.MessageReference;
import org.hornetq.core.server.Queue;
import org.hornetq.core.server.ServerMessage;
import org.hornetq.utils.ConfigurationHelper;

import twitter4j.DirectMessage;
import twitter4j.GeoLocation;
import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import br.com.porcelli.hornetq.integration.twitter.TwitterConstants;
import br.com.porcelli.hornetq.integration.twitter.TwitterConstants.MessageType;
import br.com.porcelli.hornetq.integration.twitter.data.InternalTwitterConstants;
import br.com.porcelli.hornetq.integration.twitter.outgoing.jmx.TwitterOutgoingManagement;

/**
 * OutgoingTwitterHandler consumes from configured HornetQ address and forwards to the twitter.
 */
public class OutgoingTwitterHandler implements Consumer, ConnectorService {
    private static final Logger log = Logger.getLogger(OutgoingTwitterHandler.class);

    private final String connectorName;

    private final PostOffice postOffice;

    private final Queue errorQueue;

    private final Queue sentQueue;

    private final Queue queue;

    private final Twitter twitter;

    private boolean isStarted = false;

    private final AtomicLong tweetSent = new AtomicLong();
    private final AtomicLong dmSent = new AtomicLong();
    private final AtomicLong totalSent = new AtomicLong();

    private final TwitterOutgoingManagement mbean;

    private final String ERROR_MESSAGE_NOT_FILLED = "aa";
    private final String ERROR_MESSAGE_SIZE_EXCEED = "bb";
    private final String ERROR_INVALID_MESSAGE_TYPE = "cc";
    private final String ERROR_DM_DESTINY_NOT_FOUND = "dd";

    public OutgoingTwitterHandler(final String connectorName, final Map<String, Object> configuration,
            final PostOffice postOffice) {

        this.connectorName = connectorName;

        this.mbean = new TwitterOutgoingManagement(this);

        try {
            MBeanServer mbServer = ManagementFactory.getPlatformMBeanServer();
            ObjectName mbeanName = new ObjectName("org.hornetq:module=ConnectorService,name=" + connectorName);
            mbServer.registerMBean(mbean, mbeanName);
        } catch (Exception e) {
            log.error("Error on registering JMX info.", e);
        }

        final Configuration conf = new ConfigurationBuilder()
                .setOAuthConsumerKey(ConfigurationHelper
                        .getStringProperty(InternalTwitterConstants.PROP_CONSUMER_KEY, null, configuration))
                .setOAuthConsumerSecret(ConfigurationHelper
                        .getStringProperty(InternalTwitterConstants.PROP_CONSUMER_SECRET, null, configuration))
                .setOAuthAccessToken(ConfigurationHelper
                        .getStringProperty(InternalTwitterConstants.PROP_ACCESS_TOKEN, null, configuration))
                .setOAuthAccessTokenSecret(ConfigurationHelper
                        .getStringProperty(InternalTwitterConstants.PROP_ACCESS_TOKEN_SECRET, null, configuration))
                .build();

        this.postOffice = postOffice;
        this.twitter = new TwitterFactory(conf).getInstance();

        final String queueName = ConfigurationHelper.getStringProperty(InternalTwitterConstants.PROP_QUEUE_NAME,
                null, configuration);

        final String errorQueueName = ConfigurationHelper
                .getStringProperty(InternalTwitterConstants.PROP_ERROR_QUEUE_NAME, null, configuration);

        final String sentQueueName = ConfigurationHelper
                .getStringProperty(InternalTwitterConstants.PROP_SENT_QUEUE_NAME, null, configuration);

        final Binding queueBinding = postOffice.getBinding(new SimpleString(queueName));
        if (queueBinding == null) {
            throw new RuntimeException(connectorName + ": queue " + queueName + " not found");
        }
        queue = (Queue) queueBinding.getBindable();

        if (errorQueueName != null && errorQueueName.trim().length() > 0) {
            final Binding errorQueueBinding = postOffice.getBinding(new SimpleString(errorQueueName));
            if (errorQueueBinding == null) {
                throw new RuntimeException(connectorName + ": queue " + errorQueueName + " not found");
            }
            errorQueue = (Queue) errorQueueBinding.getBindable();
        } else {
            errorQueue = null;
        }

        if (sentQueueName != null && sentQueueName.trim().length() > 0) {
            final Binding sentQueueBinding = postOffice.getBinding(new SimpleString(sentQueueName));
            if (sentQueueBinding == null) {
                throw new RuntimeException(connectorName + ": queue " + sentQueueName + " not found");
            }
            sentQueue = (Queue) sentQueueBinding.getBindable();
        } else {
            sentQueue = null;
        }
    }

    @Override
    public synchronized void start() throws Exception {
        if (isStarted) {
            return;
        }

        queue.addConsumer(this);

        queue.deliverAsync();
        isStarted = true;
        log.debug(connectorName + ": started");
    }

    @Override
    public boolean isStarted() {
        return isStarted;
    }

    @Override
    public synchronized void stop() throws Exception {
        if (!isStarted) {
            return;
        }

        log.debug(connectorName + ": receive shutdown request");

        queue.removeConsumer(this);

        isStarted = false;
        log.debug(connectorName + ": shutdown");
    }

    @Override
    public String getName() {
        return connectorName;
    }

    @Override
    public Filter getFilter() {
        return null;
    }

    @Override
    public HandleStatus handle(final MessageReference ref) {
        System.out.println("Entrando no handle()");
        synchronized (this) {
            ref.handled();
            final ServerMessage message = ref.getMessage();
            try {
                String text2publish;
                if (message.containsProperty(TwitterConstants.KEY_TEXT)) {
                    text2publish = message.getStringProperty(TwitterConstants.KEY_TEXT);
                } else {
                    text2publish = message.getBodyBuffer().readString();
                }

                if (text2publish == null || text2publish.trim().length() <= 0) {
                    log.error(ERROR_MESSAGE_NOT_FILLED);
                    throw new Exception(ERROR_MESSAGE_NOT_FILLED);
                } else if (text2publish.length() > 140) {
                    log.warn(ERROR_MESSAGE_SIZE_EXCEED);
                    text2publish = text2publish.substring(0, 139);
                }

                MessageType type = MessageType.TWEET;
                try {
                    if (message.containsProperty(TwitterConstants.KEY_MSG_TYPE)) {
                        type = MessageType
                                .valueOf(message.getStringProperty(TwitterConstants.KEY_MSG_TYPE).toUpperCase());
                    }
                } catch (Exception e) {
                    log.warn(ERROR_INVALID_MESSAGE_TYPE);
                }

                if (type == MessageType.DM) {
                    if (!message.containsProperty(TwitterConstants.KEY_TO_USER_ID)
                            && !message.containsProperty(TwitterConstants.KEY_TO_USER_SCREEN_NAME)) {
                        log.error(ERROR_DM_DESTINY_NOT_FOUND);
                        throw new Exception(ERROR_DM_DESTINY_NOT_FOUND);
                    }

                    DirectMessage sentMessage = null;
                    if (message.containsProperty(TwitterConstants.KEY_TO_USER_ID)) {
                        int userId = -1;
                        try {
                            userId = message.getIntProperty(TwitterConstants.KEY_TO_USER_ID);
                        } catch (PropertyConversionException e) {
                            userId = Integer.valueOf(message.getStringProperty(TwitterConstants.KEY_TO_USER_ID));
                        }
                        sentMessage = twitter.sendDirectMessage(userId, text2publish);
                        dmSent.incrementAndGet();
                        totalSent.incrementAndGet();
                    } else if (message.containsProperty(TwitterConstants.KEY_TO_USER_SCREEN_NAME)) {
                        String userScreenName = message.getStringProperty(TwitterConstants.KEY_TO_USER_SCREEN_NAME);
                        sentMessage = twitter.sendDirectMessage(userScreenName, text2publish);
                        dmSent.incrementAndGet();
                        totalSent.incrementAndGet();
                    }
                    if (sentMessage != null && sentQueue != null) {
                        final ServerMessage msg = buildMessage(sentQueue.getName().toString(), sentMessage);
                        msg.setAddress(sentQueue.getName());
                        msg.setDurable(true);
                        postOffice.route(msg, false);
                    }
                } else {
                    final StatusUpdate status = new StatusUpdate(text2publish);

                    if (message.containsProperty(TwitterConstants.KEY_IN_REPLY_TO_STATUS_ID)) {
                        long reply2StatusId = 0L;
                        try {
                            reply2StatusId = message.getLongProperty(TwitterConstants.KEY_IN_REPLY_TO_STATUS_ID);
                        } catch (PropertyConversionException e) {
                            reply2StatusId = Long
                                    .valueOf(message.getStringProperty(TwitterConstants.KEY_IN_REPLY_TO_STATUS_ID));
                        }
                        status.setInReplyToStatusId(reply2StatusId);
                    }

                    if (message.containsProperty(TwitterConstants.KEY_GEO_LATITUDE)
                            && message.containsProperty(TwitterConstants.KEY_GEO_LONGITUDE)) {
                        double geolat = 0.0D;
                        double geolong = 0.0D;
                        try {
                            geolat = message.getDoubleProperty(TwitterConstants.KEY_GEO_LATITUDE);
                        } catch (PropertyConversionException e) {
                            geolat = Double.valueOf(message.getStringProperty(TwitterConstants.KEY_GEO_LATITUDE));
                        }
                        try {
                            geolong = message.getDoubleProperty(TwitterConstants.KEY_GEO_LONGITUDE);
                        } catch (PropertyConversionException e) {
                            geolong = Double.valueOf(message.getStringProperty(TwitterConstants.KEY_GEO_LONGITUDE));
                        }

                        status.setLocation(new GeoLocation(geolat, geolong));
                    }

                    if (message.containsProperty(TwitterConstants.KEY_PLACE_ID)) {
                        status.setPlaceId(message.getStringProperty(TwitterConstants.KEY_PLACE_ID));
                    }

                    if (message.containsProperty(TwitterConstants.KEY_DISPLAY_COODINATES)) {
                        boolean displayCoordinated = false;
                        try {
                            displayCoordinated = message
                                    .getBooleanProperty(TwitterConstants.KEY_DISPLAY_COODINATES);
                        } catch (PropertyConversionException e) {
                            displayCoordinated = Boolean
                                    .valueOf(message.getStringProperty(TwitterConstants.KEY_DISPLAY_COODINATES));
                        }
                        status.setDisplayCoordinates(displayCoordinated);
                    }
                    Status sentMessage = twitter.updateStatus(status);
                    tweetSent.incrementAndGet();
                    totalSent.incrementAndGet();
                    if (sentMessage != null && sentQueue != null) {
                        final ServerMessage msg = buildMessage(sentQueue.getName().toString(), sentMessage);
                        msg.setAddress(sentQueue.getName());
                        msg.setDurable(true);
                        postOffice.route(msg, false);
                    }
                }
            } catch (Exception e) {
                mbean.notifyException(e);
                log.error("Error sending message.", e);
                if (errorQueue != null) {
                    final ServerMessage msg = message.copy();
                    msg.setAddress(errorQueue.getName());
                    msg.setDurable(true);
                    try {
                        postOffice.route(msg, false);
                    } catch (Exception e1) {
                        mbean.notifyException(e1);
                    }
                }
            }
            try {
                queue.acknowledge(ref);
            } catch (Exception e) {
                mbean.notifyException(e);
                log.error("Error acknowledging message.", e);
            }
            return HandleStatus.HANDLED;
        }
    }

    public long getDMSent() {
        return dmSent.get();
    }

    public long getTweetSent() {
        return tweetSent.get();
    }

    public long getTotalSent() {
        return totalSent.get();
    }
}