Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
fluximpl.TwitterActionImpl Maven / Gradle / Ivy
package fluximpl;
import flux.*;
import flux.logging.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TwitterApi;
import org.scribe.model.*;
import org.scribe.oauth.OAuthService;
import org.scribe.utils.Preconditions;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static org.scribe.utils.StreamUtils.getStreamContents;
/**
* Implementation for TwitterAction.
*
* @author [email protected]
*/
public class TwitterActionImpl extends ActionImpl implements TwitterAction {
private static final String ACTION_VARIABLE = "TWITTER_ACTION_VARIABLE";
private static final String AUTHORIZE_URL = "https://twitter.com/oauth/authorize";
private static final String SEARCH_URL = "http://search.twitter.com/search.json";
public TwitterActionImpl() {
super(new FlowChartImpl(), "Twitter Action");
}
public TwitterActionImpl(FlowChartImpl fc, String name) {
super(fc, name);
}
public Set getHiddenVariableNames() {
// The returned raw type is a Set of String.
@SuppressWarnings("unchecked")
Set set = super.getHiddenVariableNames();
set.add(ACTION_VARIABLE);
return set;
}
public String getConsumerKey() {
return getVariable().consumerKey;
}
@Override
public void setConsumerKey(String apiKey) {
TwitterVariable var = getVariable();
var.consumerKey = apiKey;
putVariable(var);
}
public int getCount() {
return getVariable().count;
}
@Override
public void setCount(int count) {
TwitterVariable var = getVariable();
var.count = count;
putVariable(var);
}
public int getPage() {
return getVariable().page;
}
@Override
public void setPage(int page) {
TwitterVariable var = getVariable();
var.page = page;
putVariable(var);
}
public String getConsumerSecret() {
return getVariable().consumerSecret;
}
public Properties getParameters() {
return getVariable().parameters;
}
@Override
public void setParameters(Properties parameters) {
TwitterVariable var = getVariable();
var.parameters = parameters;
putVariable(var);
}
public StringMapEntry getIndexedParameters(int index) {
Properties bodyProperties = getVariable().parameters;
return BodyPropertiesHelper.getIndexedBodyProperties(index, bodyProperties);
}
public StringMapEntry[] getIndexedParameters() {
Properties queryParams = getVariable().parameters;
return BodyPropertiesHelper.getIndexedBodyProperties(queryParams);
}
public void setIndexedParameters(StringMapEntry[] queryParameters) throws EngineException {
TwitterVariable var = getVariable();
Properties variableQueryParameters = var.parameters;
BodyPropertiesHelper.setIndexedBodyProperties(queryParameters, variableQueryParameters);
putVariable(var);
}
public void setIndexedParameters(int index, StringMapEntry arg) throws EngineException {
TwitterVariable var = getVariable();
Properties queryParams = var.parameters;
BodyPropertiesHelper.setIndexedBodyProperties(index, arg, queryParams);
putVariable(var);
}
@Override
public void setConsumerSecret(String apiSecret) {
TwitterVariable var = getVariable();
var.consumerSecret = apiSecret;
putVariable(var);
}
public boolean getOAuthEnabled() {
return getVariable().oAuthEnabled;
}
@Override
public void setOAuthEnabled(boolean oAuthEnabled) {
TwitterVariable var = getVariable();
var.oAuthEnabled = oAuthEnabled;
putVariable(var);
}
public String getSearchQuery() {
return getVariable().searchQuery;
}
@Override
public void setSearchQuery(String searchQuery) {
TwitterVariable var = getVariable();
var.searchQuery = searchQuery;
putVariable(var);
}
public RestActionType getRequestMethod() {
return RestActionType.valueOf(getVariable().requestMethod);
}
@Override
public void setRequestMethod(RestActionType actionType) {
TwitterVariable var = getVariable();
var.requestMethod = actionType.toString();
putVariable(var);
}
public String getResourceUrl() {
return getVariable().resourceUrl;
}
@Override
public void setResourceUrl(String resourceUrl) {
TwitterVariable var = getVariable();
var.resourceUrl = resourceUrl;
putVariable(var);
}
public String getUsername() {
return getVariable().username;
}
@Override
public void setUsername(String username) {
TwitterVariable var = getVariable();
var.username = username;
putVariable(var);
}
public String getPassword() {
Password password = getVariable().password;
if (password != null) {
return password.getEncryptedPassword();
}
return null;
}
@Override
public void setPassword(String password) {
TwitterVariable var = getVariable();
if (password != null) {
var.password = Password.makePassword(password);
}
putVariable(var);
}
private boolean isSearchRequest() {
return getResourceUrl().equals(SEARCH_URL) && getRequestMethod().equals(RestActionType.GET);
}
@Override
public Object execute(FlowContext flowContext) throws Exception {
TwitterActionResult result;
if (getOAuthEnabled()) {
result = processOAuthRequest(flowContext);
} else {
Map queryParams = new HashMap();
if (getCount() > 0) {
queryParams.put("rpp", Integer.toString(getCount()));
}
if (getPage() > 0) {
queryParams.put("page", Integer.toString(getPage()));
}
if (isSearchRequest()) {
queryParams.put("q", getSearchQuery());
for (Map.Entry entry : getParameters().entrySet()) {
queryParams.put((String) entry.getKey(), (String) entry.getValue());
}
result = processRequest(flowContext, queryParams);
} else {
result = processRequest(flowContext, queryParams);
}
}
return result;
}
private TwitterActionResult processRequest(FlowContext flowContext, Map queryParams) throws EngineException {
Logger log = flowContext.getLogger();
TwitterActionResult result = new TwitterActionResult();
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(getResourceUrl()).openConnection();
connection.setRequestMethod(getRequestMethod().name());
String content = formURLEncodeMap(queryParams);
log.info("Performing " + getRequestMethod().name() + " operation on " + getResourceUrl());
if (!StringUtil.isNullOrEmpty(content)) {
log.info("Encoded query params : " + content);
connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
connection.setDoOutput(true);
connection.getOutputStream().write(content.getBytes());
}
connection.connect();
int code = connection.getResponseCode();
log.info("Response status : " + code);
String body = getStreamContents(connection.getInputStream());
result.responseCode = code;
result.response = body;
} catch (Exception e) {
log.severe("Failed to process request. " + e.getMessage());
} finally {
if (connection != null)
connection.disconnect();
}
return result;
}
private TwitterActionResult processOAuthRequest(FlowContext flowContext) throws EngineException {
Logger log = flowContext.getLogger();
OAuthService service = new ServiceBuilder()
.provider(TwitterApi.class)
.apiKey(getConsumerKey())
.apiSecret(getConsumerSecret())
// .debug()
.build();
Token requestToken = service.getRequestToken();
String oauthToken = requestToken.getToken();
TwitterActionResult result = new TwitterActionResult();
HttpURLConnection connection = null;
try {
//Authorize Step1: GET
connection = (HttpURLConnection) new URL(AUTHORIZE_URL).openConnection();
connection.setRequestMethod(Verb.GET.name());
Map bodyParams = new HashMap();
bodyParams.put("oauth_token", oauthToken);
String content = formURLEncodeMap(bodyParams);
connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
connection.setDoOutput(true);
connection.getOutputStream().write(content.getBytes());
// Perform Authorization using oauth_token
connection.connect();
int code = connection.getResponseCode();
log.info("Authorize GET Response code : " + code);
String body = getStreamContents(connection.getInputStream());
log.finest("Authorize POST Response body : " + body);
String authenticityToken = getAuthenticityTokenFromTwitterResponse(body);
if (StringUtil.isNullOrEmpty(authenticityToken)) {
throw new EngineException("Error authorizing consumer.");
}
//Authorize Step2: POST
connection = (HttpURLConnection) new URL(AUTHORIZE_URL).openConnection();
connection.setRequestMethod(Verb.POST.name());
bodyParams = new HashMap();
bodyParams.put("authenticity_token", authenticityToken);
bodyParams.put("oauth_token", oauthToken);
String password = getVariable().password.getClearTextPassword();
bodyParams.put("session[password]", password);
bodyParams.put("session[username_or_email]", getUsername());
content = formURLEncodeMap(bodyParams);
connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
connection.setDoOutput(true);
connection.getOutputStream().write(content.getBytes());
// Perform Authorize using authenticity_token, oauth_token, username, password
connection.connect();
code = connection.getResponseCode();
log.info("Authorize POST Response code : " + code);
body = getStreamContents(connection.getInputStream());
log.finest("Authorize POST Response body : " + body);
String pin = getPinFromTwitterResponse(body, log);
Verifier verifier = new Verifier(pin);
//Retrieve accessToken using verifier PIN.
Token accessToken = service.getAccessToken(requestToken, verifier);
String endpoint = null;
Map queryParams = null;
if (getRequestMethod().equals(RestActionType.GET)) {
queryParams = new HashMap();
for (Map.Entry entry : getParameters().entrySet()) {
queryParams.put((String) entry.getKey(), (String) entry.getValue());
}
if (getCount() > 0) {
queryParams.put("count", Integer.toString(getCount()));
}
if (getPage() > 0) {
queryParams.put("page", Integer.toString(getPage()));
}
if (queryParams.size() > 0) {
endpoint = getResourceUrl() + "?" + formURLEncodeMap(queryParams);
} else {
endpoint = getResourceUrl();
}
} else if (getRequestMethod().equals(RestActionType.POST)) {
queryParams = new HashMap();
for (Map.Entry entry : getParameters().entrySet()) {
queryParams.put((String) entry.getKey(), (String) entry.getValue());
}
endpoint = getResourceUrl();
}
OAuthRequest request = new OAuthRequest(Verb.valueOf(getRequestMethod().name()), endpoint);
for (Map.Entry entry : queryParams.entrySet()) {
request.getBodyParams().add(entry.getKey(), entry.getValue());
}
service.signRequest(accessToken, request);
log.info("Performing " + getRequestMethod().name() + " operation on " + endpoint);
Response response = request.send();
log.info("Response status : " + code);
result.responseCode = response.getCode();
result.response = response.getBody();
log.finest("Response body : " + result.response);
} catch (IOException e) {
throw new EngineException("Error opening connection. Reason: " + e.getMessage());
} finally {
if (connection != null)
connection.disconnect();
}
return result;
}
/**
* Parses HTML response and fetches the authenticity token from Twitter.
* A hacky way, but it works.
*
* @param html HTML response returned by Twitter.
* @return authenticity token from Twitter.
*/
private String getAuthenticityTokenFromTwitterResponse(String html) throws EngineException {
Document document = Jsoup.parse(html, "UTF-8");
Element element = document.body();
try {
element = element.select("div").select("form input:eq(0)").first();
} catch (NullPointerException e) {
throw new EngineException("Error retrieving authenticity token.");
}
return element.attr("value");
}
/**
* Parses HTML response and fetches the verifier PIN from Twitter.
* A hacky way, but works as long as Twitter response format remains same.
*
* @param html HTML response returned by Twitter.
* @param log Logger
* @return verifier PIN from Twitter.
* @throws flux.EngineException If an error occurs.
*/
private String getPinFromTwitterResponse(String html, Logger log) throws EngineException {
Document document = Jsoup.parse(html, "UTF-8");
Element element = document.body();
log.info("Response from Twitter : " + element.text());
try {
element = element.select("div:matches((?i)PIN)").last();
element = element.getElementsByTag("code").first();
} catch (NullPointerException e) {
throw new EngineException("Error retrieving consumer PIN.");
}
return element.text();
}
@Override
public void verify() throws EngineException {
if (StringUtil.isNullOrEmpty(getRequestMethod().name())) {
throw new EngineException("Expected \"Request method\" to be non-null or non-empty, but it was null or empty.");
} // if
if (getPage() < 0 || getCount() < 0) {
throw new EngineException("Invalid page number or count.");
}
if (StringUtil.isNullOrEmpty(getResourceUrl())) {
throw new EngineException("Expected \"Resource URL\" to be non-null or non-empty, but it was null or empty.");
} // if
if (isSearchRequest() && StringUtil.isNullOrEmpty(getSearchQuery())) {
throw new EngineException("Expected \"Search query\" to be non-null or non-empty, but it was null or empty.");
} // if
if (getOAuthEnabled()) {
if (StringUtil.isNullOrEmpty(getConsumerKey())) {
throw new EngineException("Expected \"Consumer Key\" to be non-null or non-empty, but it was null or empty.");
} // if
if (StringUtil.isNullOrEmpty(getConsumerSecret())) {
throw new EngineException("Expected \"Consumer Secret\" to be non-null or non-empty, but it was null or empty.");
} // if
if (StringUtil.isNullOrEmpty(getUsername())) {
throw new EngineException("Expected \"Username\" to be non-null or non-empty, but it was null or empty.");
} // if
if (StringUtil.isNullOrEmpty(getPassword())) {
throw new EngineException("Expected \"Password\" to be non-null or non-empty, but it was null or empty.");
} // if
}
}
private TwitterVariable getVariable() {
if (!getVariableManager().contains(ACTION_VARIABLE)) {
getVariableManager().put(ACTION_VARIABLE, new TwitterVariable());
}
return (TwitterVariable) getVariableManager().get(ACTION_VARIABLE);
}
private void putVariable(TwitterVariable variable) {
getVariableManager().put(ACTION_VARIABLE, variable);
}
private static final String EMPTY_STRING = "";
private static final String PAIR_SEPARATOR = "=";
private static final String PARAM_SEPARATOR = "&";
private static final String UTF_8 = "UTF-8";
private static final String ERROR_MSG = String.format("Cannot find specified encoding: %s", UTF_8);
public String formURLEncodeMap(Map map) {
Preconditions.checkNotNull(map, "Cannot url-encode a null object");
return (map.size() <= 0) ? EMPTY_STRING : doFormUrlEncode(map);
}
private String doFormUrlEncode(Map map) {
StringBuilder encodedString = new StringBuilder(map.size() * 20);
for (String key : map.keySet()) {
encodedString.append(PARAM_SEPARATOR).append(formURLEncode(key));
if (map.get(key) != null) {
encodedString.append(PAIR_SEPARATOR).append(formURLEncode(map.get(key)));
}
}
return encodedString.toString().substring(1);
}
private String formURLEncode(String string) {
Preconditions.checkNotNull(string, "Cannot encode null string");
try {
return URLEncoder.encode(string, UTF_8);
} catch (UnsupportedEncodingException uee) {
throw new IllegalStateException(ERROR_MSG, uee);
}
}
}