package jfireeagle;
import java.net.URL;
import java.util.*;
import org.apache.http.client.*;
import org.apache.http.client.params.AllClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import com.thoughtworks.xstream.XStream;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import net.oauth.client.OAuthClient;
import net.oauth.client.httpclient4.HttpClient4;
import net.oauth.client.httpclient4.HttpClientPool;
import net.oauth.http.HttpMessageDecoder;
import jfireeagle.xml.*;
/**
*
*
* Fire Eagle client
*
* @author Sean C. Sullivan
*
*/
public class FireEagleClient
{
private XStream xstream;
private ClientSettings settings;
private HttpClient httpClient;
private OAuthClient authClient;
private OAuthServiceProvider authProvider;
private Token requestToken = new Token();
private boolean compressionEnabled = false;
private HttpClientPool pool;
public FireEagleClient()
{
this(new DefaultHttpClient(), null);
}
public FireEagleClient(ClientSettings cs)
{
this(new DefaultHttpClient(), cs);
}
public FireEagleClient(final HttpClient hClient)
{
this(hClient, null);
}
public FireEagleClient(final HttpClient hClient, ClientSettings cs)
{
this.httpClient = hClient;
this.setClientSettings(cs);
setUserAgent("jfireeagle");
setConnectionTimeout(15 * 1000);
setSocketTimeout(30 * 1000);
this.pool = new HttpClientPool()
{
public HttpClient getHttpClient(URL u)
{
return httpClient;
}
};
}
public void updateLocation(String freeText)
{
LocationParameters loc = new LocationParameters();
loc.setFreeText(freeText);
updateLocation(loc);
}
public void updateLocation(double latitude, double longitude)
{
GpsCoordinate coordinate = new GpsCoordinate(latitude, longitude);
LocationParameters loc = new LocationParameters();
loc.setGpsCoordinate(coordinate);
updateLocation(loc);
}
public void updateLocation(LocationParameters loc)
{
updateLocation(Util.toMap(loc));
}
protected boolean updateLocation(Map<String, String> params)
{
Response r = sendFireEagleRequest("POST", "update.xml", params, this.getUserSpecificAccessToken());
// todo : return a result???
return true;
}
public Locations lookup(String freeText)
{
LocationParameters loc = new LocationParameters();
loc.setFreeText(freeText);
return lookup(loc);
}
public Locations lookup(LocationParameters params)
{
return lookup(Util.toMap(params));
}
protected Locations lookup(Map<String, String> params)
{
Response r = sendFireEagleRequest("GET", "lookup.xml", params, this.getGeneralAccessToken());
return r.getLocations();
}
protected Token getUserSpecificAccessToken()
{
return this.getClientSettings().getUserSpecificToken();
}
/**
*
*
* Returns a list of users of the application who have updated
* their location within the past 12 hours
*
*/
public List<User> getRecentTwelveHours()
{
Calendar c = Calendar.getInstance();
c.add(Calendar.HOUR_OF_DAY, -12);
return getRecent(c);
}
/**
*
* Returns a list of users of the application who have updated
* their location within the past 24 hours
*
*/
public List<User> getRecentTwentyFourHours()
{
Calendar c = Calendar.getInstance();
c.add(Calendar.HOUR_OF_DAY, -24);
return getRecent(c);
}
/**
*
*
* "Returns a list of users of the application who have updated
* their location within the given amount of time"
*
*/
public List<User> getRecent(java.util.Calendar since)
{
return getRecent(since.getTimeInMillis());
}
/**
*
*
* "Returns a list of users of the application who have updated
* their location within the given amount of time"
*
*/
public List<User> getRecent(java.util.Date since)
{
return getRecent(since.getTime());
}
/**
*
*
* "Returns a list of users of the application who have updated
* their location within the given amount of time"
*
*/
public List<User> getRecent(long sinceTime)
{
Map<String, String> params = new LinkedHashMap<String, String>();
params.put("time", "" + sinceTime);
// Util.printTime(sinceTime);
// todo: params.put("per_page", x);
// todo: params.put("page", p);
return getRecent(params);
}
protected List<User> getRecent(Map<String, String> params)
{
Response r = sendFireEagleRequest("GET", "recent.xml", params, this.getGeneralAccessToken());
return r.getUsers();
}
public List<User> within(String freeText)
{
LocationParameters loc = new LocationParameters();
loc.setFreeText(freeText);
return within(Util.toMap(loc));
}
public List<User> within(LocationParameters loc)
{
return within(Util.toMap(loc));
}
/**
*
* Returns the location of a specific user in a location hierarchy format.
*
*/
public User getUserLocation()
{
Map<String, String> params = new LinkedHashMap<String, String>();
Response r = sendFireEagleRequest("GET", "user.xml", params, this.getUserSpecificAccessToken());
return r.getUser();
}
protected Token getGeneralAccessToken()
{
return this.getClientSettings().getGeneralToken();
}
protected List<User> within(Map<String, String> params)
{
Response r = sendFireEagleRequest("GET", "within.xml", params, this.getGeneralAccessToken());
return r.getUsers();
}
public ClientSettings getClientSettings()
{
if (this.settings == null)
{
this.settings = new ClientSettings();
}
return this.settings;
}
protected OAuthServiceProvider createOAuthServiceProvider()
{
OAuthServiceProvider p = new OAuthServiceProvider(
this.getClientSettings().getOAuthRequestTokenUrl(),
this.getClientSettings().getOAuthAuthorizeUrl(),
this.getClientSettings().getOAuthAccessTokenUrl());
return p;
}
protected OAuthServiceProvider getOAuthServiceProvider()
{
if (authProvider == null)
{
authProvider = createOAuthServiceProvider();
}
return authProvider;
}
protected OAuthAccessor createOAuthAccessor()
{
Token consumerToken = this.getConsumerToken();
String oauthCallBackUrl = this.getClientSettings().getOAuthCallbackUrl();
OAuthConsumer c = new OAuthConsumer(
oauthCallBackUrl,
consumerToken.getPublicKey(),
consumerToken.getSecret(),
getOAuthServiceProvider());
if (this.compressionEnabled)
{
c.setProperty(OAuthClient.ACCEPT_ENCODING, HttpMessageDecoder.ACCEPTED);
}
OAuthAccessor a = new OAuthAccessor(c);
return a;
}
protected OAuthClient createOAuthClient()
{
OAuthClient authClient = new OAuthClient(new HttpClient4(this.pool));
return authClient;
}
protected OAuthClient getOAuthClient()
{
if (authClient == null)
{
authClient = createOAuthClient();
}
return authClient;
}
protected Response sendFireEagleRequest(String method, String service, java.util.Map<String, String> params, Token token)
{
checkUserAccessToken();
String xml = sendHttpRequest(this.getClientSettings().getWebServiceUrl() + "/" + service, method, params, token);
Response r = fromXml(xml);
return r;
}
protected void checkUserAccessToken()
{
if ( hasValidUserAccessToken() == false)
{
if (this.requestToken.isValid())
{
fetchAccessToken();
}
else
{
String userAuthorizationUrl = getUserAuthorizationUrl();
throw new UserAuthorizationRequiredException(userAuthorizationUrl);
}
}
}
protected Token getConsumerToken()
{
return this.getClientSettings().getConsumerToken();
}
@SuppressWarnings("unchecked")
public void fetchAccessToken()
{
// System.out.println("fetchAccessToken: requestToken=" + this.getRequestToken());
OAuthClient client = getOAuthClient();
OAuthMessage responseMsg = null;
OAuthAccessor access = this.createOAuthAccessor();
try
{
//
// request the Access token
//
access.accessToken = requestToken.getPublicKey();
access.requestToken = requestToken.getPublicKey();
access.tokenSecret = requestToken.getSecret();
responseMsg = client.invoke(access, "GET", this.getClientSettings().getOAuthAccessTokenUrl(), null);
this.getUserSpecificAccessToken().setPublicKey(responseMsg.getParameter("oauth_token"));
this.getUserSpecificAccessToken().setSecret(responseMsg.getParameter("oauth_token_secret"));
} catch (Exception e) {
throw new FireEagleException(e);
}
}
public String getUserAuthorizationUrl()
{
String url = null;
OAuthClient client = getOAuthClient();
OAuthAccessor access = this.createOAuthAccessor();
try
{
this.requestToken = null;
access.requestToken = null;
access.accessToken = null;
access.tokenSecret = null;
//
// send GET request to the Request Token URL
//
client.getRequestToken(access);
// store the Request Token values
requestToken = new Token();
requestToken.setPublicKey(access.requestToken);
requestToken.setSecret(access.tokenSecret);
//
//
// build user authorization URL
//
//
url = this.getClientSettings().getOAuthAuthorizeUrl()
+ "?oauth_token=" + requestToken.getPublicKey();
if (settings.getOAuthCallbackUrl() != null)
{
url = url + "&oauth_callback="
+ settings.getOAuthCallbackUrl();
}
return url;
}
catch (Exception e)
{
throw new FireEagleException(e);
}
}
protected String sendHttpRequest(String baseUrl, String method, java.util.Map<String, String> params, Token token)
{
OAuthClient client = getOAuthClient();
OAuthMessage responseMsg = null;
OAuthAccessor access = this.createOAuthAccessor();
access.accessToken = token.getPublicKey();
access.tokenSecret = token.getSecret();
if (params == null)
{
params = new HashMap<String, String>();
}
try
{
responseMsg = client.invoke(access, method, baseUrl, params.entrySet());
return responseMsg.readBodyAsString();
}
catch (Exception e)
{
throw new FireEagleException(e);
}
}
protected boolean isEmpty(String s)
{
if (s == null)
{
return true;
}
else if (s.length() == 0)
{
return true;
}
else
{
return false;
}
}
public void setClientSettings(ClientSettings s)
{
this.settings = s;
}
protected boolean hasValidUserAccessToken()
{
return this.getUserSpecificAccessToken().isValid();
}
protected boolean generalAccessTokenIsValid()
{
return this.getGeneralAccessToken().isValid();
}
protected Response fromXml(String xmlResponse)
{
Response r = (Response) this.getXStream().fromXML(xmlResponse);
r.setXml(xmlResponse);
return r;
}
protected XStream getXStream()
{
if (xstream == null)
{
return XStreamFactory.createXStream();
}
return xstream;
}
public Token getToken()
{
return this.requestToken;
}
public void shutdown()
{
try
{
this.getHttpClient().getConnectionManager().shutdown();
}
catch (Exception ignore)
{
// ignored
}
}
public void setUserAgent(String ua)
{
getHttpClient().getParams().setParameter(AllClientPNames.USER_AGENT, ua);
}
public void setConnectionTimeout(int milliseconds)
{
getHttpClient().getParams().setIntParameter(AllClientPNames.CONNECTION_TIMEOUT, milliseconds);
}
public void setSocketTimeout(int milliseconds)
{
getHttpClient().getParams().setIntParameter(AllClientPNames.SO_TIMEOUT, milliseconds);
}
public void setCompressionEnabled(boolean b)
{
this.compressionEnabled = b;
}
public boolean getCompressionEnabled()
{
return this.compressionEnabled;
}
public Token getRequestToken()
{
return this.requestToken;
}
public void setRequestToken(Token t)
{
this.requestToken = t;
}
protected HttpClient getHttpClient()
{
return this.httpClient;
}
}