package com.uservoice; import java.util.HashMap; import java.util.Map; import net.sf.json.JSONObject; import org.scribe.builder.ServiceBuilder; import org.scribe.model.OAuthConstants; import org.scribe.model.OAuthRequest; import org.scribe.model.Response; import org.scribe.model.Token; import org.scribe.model.Verb; import org.scribe.model.Verifier; import org.scribe.oauth.OAuthService; public class Client { private String serverLocation; private OAuthService service; private Token requestToken; private Token token; public Client(String subdomainName, String apiKey) { this(subdomainName, apiKey, null); } public Client(String subdomainName, String apiKey, String apiSecret) { this(subdomainName, apiKey, apiSecret, null); } public Client(String subdomainName, String apiKey, String apiSecret, String callback) { this(subdomainName, apiKey, apiSecret, callback, "", ""); } public Client(String subdomainName, String apiKey, String apiSecret, String callback, String token, String secret) { this(subdomainName, apiKey, apiSecret, callback, token, secret, "uservoice.com"); } public Client(String subdomainName, String apiKey, String apiSecret, String callback, String token, String secret, String uservoiceDomain) { this(subdomainName, apiKey, apiSecret, callback, token, secret, uservoiceDomain, "https"); } public Client(String subdomainName, String apiKey, String apiSecret, String callback, String token, String secret, String uservoiceDomain, String protocol) { this(getValueOrDefault(protocol, "https") + "://" + subdomainName + "." + getValueOrDefault(uservoiceDomain, "uservoice.com"), new ServiceBuilder() .provider( new UserVoiceApi(getValueOrDefault(protocol, "https") + "://" + subdomainName + "." + getValueOrDefault(uservoiceDomain, "uservoice.com"))).apiKey(apiKey) .apiSecret(getValueOrDefault(apiSecret, apiKey)) .callback(getValueOrDefault(callback, OAuthConstants.OUT_OF_BAND)).build(), new Token(getValueOrDefault(token, ""), getValueOrDefault(secret, ""))); } private static String getValueOrDefault(String value, String defaultValue) { if (value == null) { return defaultValue; } return value; } public Client(String serverLocation, OAuthService service, Token token) { this.serverLocation = serverLocation; this.service = service; this.token = token; } public String authorizeUrl() { requestToken = service.getRequestToken(); return service.getAuthorizationUrl(requestToken); } public Client loginWithAccessToken(String token, String secret) { return new Client(serverLocation, service, new Token(token, secret)); } /** * Logins as the first UserVoice account owner of the subdomain. * * @return The client instance for making API calls as the owner * @throws APIError */ @SuppressWarnings("serial") public Client loginAsOwner() throws APIError { requestToken = service.getRequestToken(); JSONObject token = post("/api/v1/users/login_as_owner", new HashMap<String, Object>() { { put("request_token", requestToken.getToken()); } }); if (token != null && !token.getJSONObject("token").isNullObject()) { return loginWithAccessToken(token.getJSONObject("token").getString("oauth_token"), token.getJSONObject("token").getString("oauth_token_secret")); } else { throw new Unauthorized("Could not get Request Token"); } } /** * Logins as the specified email address. * * @param email * The email of the user to be logged in as * @return The client instance for making API calls as the owner * @throws APIError */ @SuppressWarnings({ "serial" }) public Client loginAs(final String email) throws APIError { requestToken = service.getRequestToken(); JSONObject token = post("/api/v1/users/login_as", new HashMap<String, Object>() { { put("request_token", requestToken.getToken()); put("user", new HashMap<String, String>() { { put("email", email); } }); } }); if (token != null && !token.getJSONObject("token").isNullObject()) { return loginWithAccessToken(token.getJSONObject("token").getString("oauth_token"), token.getJSONObject("token").getString("oauth_token_secret")); } else { throw new Unauthorized("Could not get Request Token"); } } public JSONObject request(Verb method, String path, Map<String, Object> params) throws APIError { OAuthRequest request = new OAuthRequest(method, serverLocation + path); request.addHeader("Content-Type", "application/json"); request.addHeader("API-Client", "uservoice-java-${project.version}"); request.addHeader("Accept", "application/json"); if (params != null) { request.addPayload(JSONObject.fromObject(params).toString()); } service.signRequest(token, request); Response response = request.send(); JSONObject result = JSONObject.fromObject(response.getBody()); if (result != null && !result.getJSONObject("errors").isNullObject()) { String errorType = result.getJSONObject("errors").getString("type"); if ("unauthorized".equals(errorType)) { throw new Unauthorized(result.getJSONObject("errors").getString("message")); } else if ("record_not_found".equals(errorType)) { throw new NotFound(result.getJSONObject("errors").getString("message")); } else if ("application_error".equals(errorType)) { throw new ApplicationError(result.getJSONObject("errors").getString("message")); } else { throw new APIError(result.getJSONObject("errors").getString("message")); } } return result; } /** * Retrieve a client instance for making calls as the user who gave * permission in UserVoice site. * * @param verifier * the verifier that was passed as a GET paramter or received in * Out-Of-Band fashion * @return The client for making calls as the authorized and verified user */ public Client loginWithVerifier(String verifier) { Token token = service.getAccessToken(requestToken, new Verifier(verifier)); return loginWithAccessToken(token.getToken(), token.getSecret()); } /** * Make a GET API call. * * @param path * The GET path. Include the GET parameters after ? * @return A JSON object. * @throws APIError * If an error occurs. */ public JSONObject get(String path) throws APIError { return request(Verb.GET, path, null); } /** * Make a DELETE API call. * * @param path * The GET path. Include the GET parameters after ? * @return A JSON object. * @throws APIError * If an error occurs. */ public JSONObject delete(String path) throws APIError { return request(Verb.DELETE, path, null); } /** * Make a GET POST call. * * @param path * The GET path. Include the GET parameters after ? * @param params * The parameters to be passed in the body of the call as JSON * @return A JSON object. * @throws APIError * If an error occurs. */ public JSONObject post(String path, Map<String, Object> params) throws APIError { return request(Verb.POST, path, params); } /** * Make a PUT API call. * * @param path * The GET path. Include the GET parameters after ? * @param params * The parameters to be passed in the body of the call as JSON * @return A JSON object. * @throws APIError * If an error occurs. */ public JSONObject put(String path, Map<String, Object> params) throws APIError { return request(Verb.PUT, path, params); } public Collection getCollection(String path, Integer limit) { return new Collection(this, path, limit); } public Collection getCollection(String path) { return getCollection(path, null); } }