Skip to content

Instantly share code, notes, and snippets.

@zaneli
Created February 19, 2012 05:52
Show Gist options
  • Save zaneli/1862190 to your computer and use it in GitHub Desktop.
Save zaneli/1862190 to your computer and use it in GitHub Desktop.
「remember the milk API 用 Java クライアントを作る(1)」ブログ用
package com.zaneli.rtm.model.util;
import java.util.HashMap;
import java.util.Map;
import com.zaneli.rtm.RtmException;
public class AuthUtil {
private static final String URL = "http://www.rememberthemilk.com/services/auth/";
public static String createAuthUrl(
String apikey, String sharedSecret, Perms perms, String frob) throws RtmException {
Map<String, String> params = new HashMap<String, String>();
params.put("api_key", apikey);
params.put("perms", perms.getValue());
params.put("frob", frob);
params.put("api_sig", RtmUtil.createApiSig(sharedSecret, params));
return RtmUtil.createQueryUrl(URL, params);
}
public enum Perms {
READ("read"), READ_WRITE("write"), ALL("delete");
private final String value;
private Perms(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
private AuthUtil() {};
}
package com.zaneli.rtm.model;
public class GetFrobResult extends Result {
public String getFrob() {
return (String) getRsp().get("frob");
}
}
package com.zaneli.rtm.model;
import java.util.Map;
public class GetTokenResult extends Result {
public String getToken() {
return (String) getAuth().get("token");
}
public String getPerms() {
return (String) getAuth().get("perms");
}
public int getUserId() {
return ((Integer) getUser().get("id")).intValue();
}
public int getUserName() {
return ((Integer) getUser().get("username")).intValue();
}
public int getFullName() {
return ((Integer) getUser().get("fullname")).intValue();
}
@SuppressWarnings("unchecked")
private Map<String, Object> getAuth() {
return (Map<String, Object>) getRsp().get("auth");
}
@SuppressWarnings("unchecked")
private Map<String, Object> getUser() {
return (Map<String, Object>) getAuth().get("user");
}
}
package com.zaneli.rtm.model;
import java.util.Map;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.zaneli.rtm.RtmException;
public abstract class Result {
private Map<String, Object> rsp;
public String getStat() {
return (String) getRsp().get("stat");
}
@SuppressWarnings("unchecked")
public RtmException getErr() {
return new RtmException((Map<String, Object>) rsp.get("err"));
}
public void setRsp(Map<String, Object> rsp) {
this.rsp = rsp;
}
protected Map<String, Object> getRsp() {
return rsp;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}
package com.zaneli.rtm;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.arnx.jsonic.JSON;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import com.zaneli.rtm.model.GetFrobResult;
import com.zaneli.rtm.model.GetTokenResult;
import com.zaneli.rtm.model.Result;
import com.zaneli.rtm.model.util.RtmUtil;
public class RtmClient {
private static final String URL = "https://api.rememberthemilk.com/services/rest/";
private final String apikey;
private final String sharedSecret;
public RtmClient(String apikey, String sharedSecret) {
this.apikey = apikey;
this.sharedSecret = sharedSecret;
}
public GetFrobResult getFrob() throws RtmException, IOException {
Map<String, String> params = new HashMap<String, String>();
params.put("method", "rtm.auth.getFrob");
params.put("api_key", apikey);
params.put("format", "json");
params.put("api_sig", RtmUtil.createApiSig(sharedSecret, params));
HttpPost request = new HttpPost(URL);
request.setEntity(createEntity(params));
return execute(request, GetFrobResult.class);
}
public GetTokenResult getToken(String frob) throws RtmException, IOException {
Map<String, String> params = new HashMap<String, String>();
params.put("method", "rtm.auth.getToken");
params.put("api_key", apikey);
params.put("frob", frob);
params.put("format", "json");
params.put("api_sig", RtmUtil.createApiSig(sharedSecret, params));
HttpPost request = new HttpPost(URL);
request.setEntity(createEntity(params));
return execute(request, GetTokenResult.class);
}
private <T extends Result> T execute(
HttpRequestBase request,
Class<? extends T> resultClass) throws IOException, RtmException {
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
InputStream in = null;
try {
in = response.getEntity().getContent();
T result = JSON.decode(in, resultClass);
String stat = result.getStat();
if ("ok".equals(stat)) {
return result;
} else if ("fail".equals(stat)) {
throw result.getErr();
} else {
throw new IllegalStateException("stat=" + stat);
}
} finally {
if (in != null) in.close();
}
}
private UrlEncodedFormEntity createEntity(Map<String, String> params) throws RtmException {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for (Entry<String, String> entry : params.entrySet()) {
nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
try {
return new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
} catch (UnsupportedEncodingException e) {
throw new RtmException(e);
}
}
}
package com.zaneli.rtm;
import java.util.Map;
@SuppressWarnings("serial")
public class RtmException extends Exception {
public RtmException(Map<String, Object> errMap) {
super("code=" + errMap.get("code") + ", msg=" + errMap.get("msg"));
}
public RtmException(Throwable cause) {
super(cause);
}
}
package com.zaneli.rtm.model.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import com.zaneli.rtm.RtmException;
public class RtmUtil {
public static String createQueryUrl(String url, Map<String, String> queryParams) {
StringBuilder sb = new StringBuilder(url);
sb.append('?');
for (Entry<String, String> entry : queryParams.entrySet()) {
sb.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
}
return sb.substring(0, sb.length() - 1).toString();
}
public static String createApiSig(String sharedSecret, Map<String, String> params) throws RtmException {
Map<String, String> sortedParams = new TreeMap<String, String>(params);
StringBuilder sb = new StringBuilder(sharedSecret);
for (Entry<String, String> entry : sortedParams.entrySet()) {
sb.append(entry.getKey());
sb.append(entry.getValue());
}
try {
return digest(sb.toString());
} catch (NoSuchAlgorithmException e) {
throw new RtmException(e);
}
}
private static String digest(String value) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(value.getBytes());
return toHexString(md.digest());
}
private static String toHexString(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (byte b : byteArray) {
String hexStr = Integer.toHexString(b & 0xff);
if (hexStr.length() == 1) {
sb.append("0");
}
sb.append(hexStr);
}
return sb.toString();
}
private RtmUtil() {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment