001package org.openimaj.picslurper;
002
003import java.io.FileNotFoundException;
004import java.io.IOException;
005import java.io.InputStream;
006
007import org.apache.http.HttpResponse;
008import org.apache.http.HttpVersion;
009import org.apache.http.auth.AuthScope;
010import org.apache.http.auth.UsernamePasswordCredentials;
011import org.apache.http.client.ClientProtocolException;
012import org.apache.http.client.methods.HttpGet;
013import org.apache.http.conn.scheme.Scheme;
014import org.apache.http.conn.scheme.SchemeRegistry;
015import org.apache.http.conn.ssl.SSLSocketFactory;
016import org.apache.http.impl.client.DefaultHttpClient;
017import org.apache.http.impl.conn.PoolingClientConnectionManager;
018import org.apache.http.params.BasicHttpParams;
019import org.apache.http.params.HttpConnectionParams;
020import org.apache.http.params.HttpProtocolParams;
021import org.apache.log4j.Logger;
022
023/**
024 * Factory provides input streams to twitter, managing the disconnection of old
025 * streams
026 *
027 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
028 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk),
029 *
030 */
031public class TwitterInputStreamFactory {
032        private static final Logger logger = Logger.getLogger(TwitterInputStreamFactory.class);
033        private static final String TWITTER_SAMPLE_URL = "https://stream.twitter.com/1/statuses/sample.json";
034        private static TwitterInputStreamFactory staticFactory;
035        private InputStream inputStream;
036        private PoolingClientConnectionManager manager;
037        private BasicHttpParams params;
038        private SchemeRegistry registry;
039
040        /**
041         * @return a new source of twitter input streams
042         */
043        public static TwitterInputStreamFactory streamFactory() {
044                if (staticFactory == null) {
045                        try {
046                                staticFactory = new TwitterInputStreamFactory();
047                        } catch (Exception e) {
048                                e.printStackTrace();
049                                System.err.println("Error creating TwitterInputStreamFactory: " + e.getMessage());
050                                return null;
051                        }
052                }
053                return staticFactory;
054        }
055
056        private TwitterInputStreamFactory() throws FileNotFoundException, IOException {
057                PicSlurper.loadConfig();
058                this.params = new BasicHttpParams();
059                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
060                HttpProtocolParams.setContentCharset(params, "utf-8");
061                HttpConnectionParams.setConnectionTimeout(params, 1000);
062                HttpConnectionParams.setSoTimeout(params, 1000);
063                this.registry = new SchemeRegistry();
064                registry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
065        }
066
067        private void reconnect() throws ClientProtocolException, IOException {
068                logger.debug("Reconnecting, closing expired clients");
069
070                logger.debug("Constructing new client");
071                DefaultHttpClient client = new DefaultHttpClient(manager, params);
072
073                UsernamePasswordCredentials twitterUserPassword = new UsernamePasswordCredentials(
074                                System.getProperty("twitter.user"),
075                                System.getProperty("twitter.password")
076                                );
077                client.getCredentialsProvider().setCredentials(new AuthScope("stream.twitter.com", 443), twitterUserPassword);
078                HttpGet get = new HttpGet(TWITTER_SAMPLE_URL);
079                HttpResponse resp = client.execute(get);
080                logger.debug("Done!");
081                this.inputStream = resp.getEntity().getContent();
082        }
083
084        /**
085         * @return Attempt to disconnect any previous streams and reconnect
086         * @throws IOException
087         */
088        public InputStream nextInputStream() throws IOException {
089                logger.debug("Attempting to get next input twitter input stream!");
090                if (this.inputStream != null) {
091                        logger.debug("Closing old stream...");
092                        manager.shutdown();
093                        this.inputStream.close();
094                }
095                this.manager = new PoolingClientConnectionManager(registry);
096                reconnect();
097                return this.inputStream;
098        }
099}