
com.wordnik.swaggersocket.samples.TwitterFeed Maven / Gradle / Ivy
/**
* Copyright 2015 Reverb Technologies, Inc.
*
* 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 com.wordnik.swaggersocket.samples;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.Response;
import com.ning.http.util.Base64;
import com.sun.jersey.spi.resource.Singleton;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicy;
import org.atmosphere.jersey.SuspendResponse;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletConfig;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@Path("/search/{tagid}")
@Produces("text/html;charset=ISO-8859-1")
@Singleton
public class TwitterFeed {
private static final Logger logger = LoggerFactory.getLogger(TwitterFeed.class);
private final AsyncHttpClient asyncClient = new AsyncHttpClient();
private final ConcurrentHashMap> futures = new ConcurrentHashMap>();
private final CountDownLatch suspendLatch = new CountDownLatch(1);
@Context
private ServletConfig sc;
private boolean initialized;
private String authorizationValue;
private Exception authorizationException;
@GET
public SuspendResponse search(final @PathParam("tagid") Broadcaster feed,
final @PathParam("tagid") String tagid) {
if (tagid.isEmpty()) {
throw new WebApplicationException();
}
if (!initialized) {
initialized = true;
String key = sc.getInitParameter("com.twitter.consumer.key");
String secret = sc.getInitParameter("com.twitter.consumer.secret");
try {
Future f = asyncClient.preparePost("https://api.twitter.com/oauth2/token")
.setHeader("Authorization", "Basic " + Base64.encode((key + ":" + secret).getBytes()))
.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").setBody("grant_type=client_credentials").execute();
JSONObject jtoken = new JSONObject(f.get().getResponseBody());
authorizationValue = "Bearer " + jtoken.getString("access_token");
} catch (Exception e) {
logger.error("Unable to obtain a valid bearer token", e);
authorizationException = e;
}
}
// we avoid repeatedly invoking the above authorization tkoen retrieval call
if (authorizationValue == null) {
throw new WebApplicationException(authorizationException);
}
if (feed.getAtmosphereResources().size() == 0) {
final Future> future = feed.scheduleFixedBroadcast(new Callable() {
private final AtomicReference refreshUrl = new AtomicReference("");
public String call() throws Exception {
String query = null;
if (!refreshUrl.get().isEmpty()) {
query = refreshUrl.get();
} else {
query = "?q=" + tagid;
}
//TODO add next_results handling
asyncClient.prepareGet("https://api.twitter.com/1.1/search/tweets.json" + query)
.setHeader("Authorization", authorizationValue)
.execute(
new AsyncCompletionHandler
© 2015 - 2025 Weber Informatics LLC | Privacy Policy