/*
* Copyright 2013-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Amazon Software License (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/asl/
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.kinesis.dataviz.twitter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.amazonaws.kinesis.dataviz.producer.ProducerBuilder;
import com.amazonaws.kinesis.dataviz.producer.ProducerClient;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.twitter.hbc.ClientBuilder;
import com.twitter.hbc.core.Client;
import com.twitter.hbc.core.Constants;
import com.twitter.hbc.core.endpoint.Location;
import com.twitter.hbc.core.endpoint.Location.Coordinate;
import com.twitter.hbc.core.endpoint.StatusesFilterEndpoint;
import com.twitter.hbc.core.processor.StringDelimitedProcessor;
import com.twitter.hbc.httpclient.auth.Authentication;
import com.twitter.hbc.httpclient.auth.OAuth1;
public class TwitterProducer {
private static final String TWIT_SECRET = "twitter.secret";
private static final String TWIT_TOKEN = "twitter.token";
private static final String TWIT_CONSUMER_SECRET = "twitter.consumerSecret";
private static final String TWIT_CONSUMER_KEY = "twitter.consumerKey";
private static final String HASHTAGS = "twitter.hashtags";
private static final String STREAM_NAME = "aws.streamName";
private static final String DEFAULT_PROP_FILE_NAME = "AwsUserData";
private static final String REGION_NAME = "aws.regionName";
private static final Log LOG = LogFactory.getLog(TwitterProducer.class);
public static void main(String[] args) {
TwitterProducer client = new TwitterProducer();
String arg = args.length == 1 ? args[0] : null;
client.run(arg);
}
public void run(String propFilePath) {
loadFileProperties(propFilePath, DEFAULT_PROP_FILE_NAME);
String consumerKey = System.getProperty(TWIT_CONSUMER_KEY);
String consumerSecret = System.getProperty(TWIT_CONSUMER_SECRET);
String token = System.getProperty(TWIT_TOKEN);
String secret = System.getProperty(TWIT_SECRET);
String streamName = System.getProperty(STREAM_NAME);
String regionName = System.getProperty(REGION_NAME);
while (true) {
/**
* Set up your blocking queues: Be sure to size these properly based
* on expected TPS of your stream
*/
BlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>(
10000);
/**
* Declare the host you want to connect to, the endpoint, and
* authentication (basic auth or oauth)
*/
StatusesFilterEndpoint endpoint = new StatusesFilterEndpoint();
// Track anything that is geo-tagged
endpoint.addQueryParameter("locations", "-180,-90,180,90");
// These secrets should be read from a config file
Authentication hosebirdAuth = new OAuth1(consumerKey,
consumerSecret, token, secret);
// create a new basic client - by default gzip is enabled
Client client = new ClientBuilder().hosts(Constants.STREAM_HOST)
.endpoint(endpoint).authentication(hosebirdAuth)
.processor(new StringDelimitedProcessor(msgQueue)).build();
client.connect();
LOG.info("Got connection to Twitter");
// create producer
ProducerClient producer = new ProducerBuilder()
.withName("Twitter")
.withStreamName(streamName)
.withRegion(regionName)
.withThreads(10)
.build();
producer.connect();
LOG.info("Got connection to Kinesis");
try {
if (process(msgQueue, producer)) {
break;
}
} catch (Exception e) {
// if we get here, our client has broken, throw away and
// recreate
e.printStackTrace();
}
// also, if we make it here, we have had a problem, so start again
client.stop();
}
}
private boolean process(BlockingQueue<String> msgQueue, ProducerClient producer) {
int exceptionCount = 0;
while (true) {
try {
// get message HBC from queue
String msg = msgQueue.take();
// use 'random' partition key
String key = String.valueOf(System.currentTimeMillis());
// send to Kinesis
producer.post(key, msg);
} catch (Exception e) {
// didn't get record - move on to next\
e.printStackTrace();
if(++exceptionCount > 5) {
// too many exceptions - lets reconnect and try again
return false;
}
}
}
}
private void loadFileProperties(String propFilePath, String defaultName) {
try {
if(propFilePath == null){
String userHome = System.getProperty("user.home");
propFilePath = userHome + "/" + defaultName + ".properties";
}
InputStream propFile = new FileInputStream(propFilePath);
Properties p = new Properties(System.getProperties());
p.load(propFile);
System.setProperties(p);
// got them from the file
LOG.info("Got properties from file");
} catch (FileNotFoundException e) {
// file is not there...
} catch (IOException e) {
// can't read file
} catch (Exception e) {
e.printStackTrace();
}
}
}