/src/main/java/com/tumblr/jumblr/request/RequestBuilder.java

https://gitlab.com/kevintcoughlin/jumblr · Java · 214 lines · 170 code · 26 blank · 18 comment · 38 complexity · 9b36815e47c90854923f79cd6f5e2f55 MD5 · raw file

  1. package com.tumblr.jumblr.request;
  2. import com.google.gson.Gson;
  3. import com.google.gson.GsonBuilder;
  4. import com.google.gson.JsonElement;
  5. import com.google.gson.JsonSyntaxException;
  6. import com.tumblr.jumblr.JumblrClient;
  7. import com.tumblr.jumblr.exceptions.JumblrException;
  8. import com.tumblr.jumblr.responses.JsonElementDeserializer;
  9. import com.tumblr.jumblr.responses.ResponseWrapper;
  10. import java.io.File;
  11. import java.io.IOException;
  12. import java.net.HttpURLConnection;
  13. import java.util.Map;
  14. import org.scribe.builder.ServiceBuilder;
  15. import org.scribe.builder.api.TumblrApi;
  16. import org.scribe.model.OAuthRequest;
  17. import org.scribe.model.Response;
  18. import org.scribe.model.Token;
  19. import org.scribe.model.Verb;
  20. import org.scribe.oauth.OAuthService;
  21. /**
  22. * Where requests are made from
  23. * @author jc
  24. */
  25. public class RequestBuilder {
  26. private Token token;
  27. private OAuthService service;
  28. private String hostname = "api.tumblr.com";
  29. private String xauthEndpoint = "https://www.tumblr.com/oauth/access_token";
  30. private String version = "0.0.11";
  31. private final JumblrClient client;
  32. public RequestBuilder(JumblrClient client) {
  33. this.client = client;
  34. }
  35. public String getRedirectUrl(String path) {
  36. OAuthRequest request = this.constructGet(path, null);
  37. sign(request);
  38. boolean presetVal = HttpURLConnection.getFollowRedirects();
  39. HttpURLConnection.setFollowRedirects(false);
  40. Response response = request.send();
  41. HttpURLConnection.setFollowRedirects(presetVal);
  42. if (response.getCode() == 301) {
  43. return response.getHeader("Location");
  44. } else {
  45. throw new JumblrException(response);
  46. }
  47. }
  48. public ResponseWrapper postMultipart(String path, Map<String, ?> bodyMap) throws IOException {
  49. OAuthRequest request = this.constructPost(path, bodyMap);
  50. sign(request);
  51. OAuthRequest newRequest = RequestBuilder.convertToMultipart(request, bodyMap);
  52. return clear(newRequest.send());
  53. }
  54. public ResponseWrapper post(String path, Map<String, ?> bodyMap) {
  55. OAuthRequest request = this.constructPost(path, bodyMap);
  56. sign(request);
  57. return clear(request.send());
  58. }
  59. /**
  60. * Posts an XAuth request. A new method is needed because the response from
  61. * the server is not a standard Tumblr JSON response.
  62. * @param email the user's login email.
  63. * @param password the user's password.
  64. * @return the login token.
  65. */
  66. public Token postXAuth(final String email, final String password) {
  67. OAuthRequest request = constructXAuthPost(email, password);
  68. setToken("", ""); // Empty token is required for Scribe to execute XAuth.
  69. sign(request);
  70. return clearXAuth(request.send());
  71. }
  72. // Construct an XAuth request
  73. private OAuthRequest constructXAuthPost(String email, String password) {
  74. OAuthRequest request = new OAuthRequest(Verb.POST, xauthEndpoint);
  75. request.addBodyParameter("x_auth_username", email);
  76. request.addBodyParameter("x_auth_password", password);
  77. request.addBodyParameter("x_auth_mode", "client_auth");
  78. return request;
  79. }
  80. public ResponseWrapper get(String path, Map<String, ?> map) {
  81. OAuthRequest request = this.constructGet(path, map);
  82. sign(request);
  83. return clear(request.send());
  84. }
  85. public OAuthRequest constructGet(String path, Map<String, ?> queryParams) {
  86. String url = "https://" + hostname + "/v2" + path;
  87. OAuthRequest request = new OAuthRequest(Verb.GET, url);
  88. if (queryParams != null) {
  89. for (Map.Entry<String, ?> entry : queryParams.entrySet()) {
  90. request.addQuerystringParameter(entry.getKey(), entry.getValue().toString());
  91. }
  92. }
  93. request.addHeader("User-Agent", "jumblr/" + this.version);
  94. return request;
  95. }
  96. private OAuthRequest constructPost(String path, Map<String, ?> bodyMap) {
  97. String url = "https://" + hostname + "/v2" + path;
  98. OAuthRequest request = new OAuthRequest(Verb.POST, url);
  99. for (Map.Entry<String, ?> entry : bodyMap.entrySet()) {
  100. String key = entry.getKey();
  101. Object value = entry.getValue();
  102. if (value == null || value instanceof File) { continue; }
  103. request.addBodyParameter(key,value.toString());
  104. }
  105. request.addHeader("User-Agent", "jumblr/" + this.version);
  106. return request;
  107. }
  108. public void setConsumer(String consumerKey, String consumerSecret) {
  109. service = new ServiceBuilder().
  110. provider(TumblrApi.class).
  111. apiKey(consumerKey).apiSecret(consumerSecret).
  112. build();
  113. }
  114. public void setToken(String token, String tokenSecret) {
  115. this.token = new Token(token, tokenSecret);
  116. }
  117. public void setToken(final Token token) {
  118. this.token = token;
  119. }
  120. /* package-visible for testing */ ResponseWrapper clear(Response response) {
  121. if (response.getCode() == 200 || response.getCode() == 201) {
  122. String json = response.getBody();
  123. try {
  124. Gson gson = new GsonBuilder().
  125. registerTypeAdapter(JsonElement.class, new JsonElementDeserializer()).
  126. create();
  127. ResponseWrapper wrapper = gson.fromJson(json, ResponseWrapper.class);
  128. if (wrapper == null) {
  129. throw new JumblrException(response);
  130. }
  131. wrapper.setClient(client);
  132. return wrapper;
  133. } catch (JsonSyntaxException ex) {
  134. throw new JumblrException(response);
  135. }
  136. } else {
  137. throw new JumblrException(response);
  138. }
  139. }
  140. private Token parseXAuthResponse(final Response response) {
  141. String responseStr = response.getBody();
  142. if (responseStr != null) {
  143. // Response is received in the format "oauth_token=value&oauth_token_secret=value".
  144. String extractedToken = null, extractedSecret = null;
  145. final String[] values = responseStr.split("&");
  146. for (String value : values) {
  147. final String[] kvp = value.split("=");
  148. if (kvp != null && kvp.length == 2) {
  149. if (kvp[0].equals("oauth_token")) {
  150. extractedToken = kvp[1];
  151. } else if (kvp[0].equals("oauth_token_secret")) {
  152. extractedSecret = kvp[1];
  153. }
  154. }
  155. }
  156. if (extractedToken != null && extractedSecret != null) {
  157. return new Token(extractedToken, extractedSecret);
  158. }
  159. }
  160. // No good
  161. throw new JumblrException(response);
  162. }
  163. /* package-visible for testing */ Token clearXAuth(Response response) {
  164. if (response.getCode() == 200 || response.getCode() == 201) {
  165. return parseXAuthResponse(response);
  166. } else {
  167. throw new JumblrException(response);
  168. }
  169. }
  170. private void sign(OAuthRequest request) {
  171. if (token != null) {
  172. service.signRequest(token, request);
  173. }
  174. }
  175. public static OAuthRequest convertToMultipart(OAuthRequest request, Map<String, ?> bodyMap) throws IOException {
  176. return new MultipartConverter(request, bodyMap).getRequest();
  177. }
  178. public String getHostname() {
  179. return hostname;
  180. }
  181. /**
  182. * Set hostname without protocol
  183. * @param host such as "api.tumblr.com"
  184. */
  185. public void setHostname(String host) {
  186. this.hostname = host;
  187. }
  188. }