2009年4月30日木曜日

BacklogのAPIを使ってみる

BacklogAPIを使ってみました。
BacklogのアクセスはXML-RPCになっています。Tracと一緒ですね。
ということで、JavaならばApache XML-RPCを使うと、あっさりプロジェクトの一覧が取得できました。
private static final String URL = "https://{使っているスペースID}.backlog.jp/XML-RPC";
private static final String USER = "{ユーザ名}";
private static final String PASSWORD = "{パスワード}";

public static void main(String[] args) {
try {
XmlRpcClientConfigImpl conf = new XmlRpcClientConfigImpl();
conf.setBasicUserName(USER);
conf.setBasicPassword(PASSWORD);
conf.setServerURL(new URL(URL));

XmlRpcClient client = new XmlRpcClient();
client.setConfig(conf);
Object ret = client.execute("backlog.getProjects", new ArrayList());

// 結果の出力
if (ret instanceof Object[]) {
for (Object o : (Object[]) ret) {
System.out.println(o);
}
}

} catch (Exception e) {
e.printStackTrace();
}
}

ポイントとしては、以下。
  1. Basic認証をする。
  2. POSTで送信する。
  3. Outputに送信するXMLを記述する。

ということで、ApacheのXML-RPCを使わないパターンで、送信時に必要な情報を再確認。
以下のコードでもアクセスできるのを確認。


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class HttpClientHttpURLConnectionAuth {
private static final String URL = "https://{使っているスペースID}.backlog.jp/XML-RPC";
private static final String USER = "{ユーザ名}";
private static final String PASSWORD = "{パスワード}";

public static void main(String[] args) throws MalformedURLException,
ProtocolException, IOException {

URL url = new URL(URL);
HttpAuthenticator httpAuthenticator = new HttpAuthenticator(USER,
PASSWORD);
Authenticator.setDefault(httpAuthenticator);

HttpURLConnection urlconn = (HttpURLConnection) url.openConnection();
urlconn.setRequestMethod("POST");
urlconn.setInstanceFollowRedirects(false);
urlconn.setRequestProperty("Content-Type", "text/xml");

urlconn.setDoOutput(true);
OutputStream os = urlconn.getOutputStream();

String postStr = "backlog.getProjects";
PrintStream ps = new PrintStream(os);
ps.print(postStr);
ps.close();

Map<String, List<String>> headers = urlconn.getHeaderFields();
Iterator<String> it = headers.keySet().iterator();
System.out.println("レスポンスヘッダ:");
while (it.hasNext()) {
String key = it.next();
System.out.println(" " + key + ": " + headers.get(key));
}

System.out.println("レスポンスコード[" + urlconn.getResponseCode() + "] "
+ "レスポンスメッセージ[" + urlconn.getResponseMessage() + "]");
System.out.println("プロンプト(realm)["
+ httpAuthenticator.myGetRequestingPrompt() + "]");
System.out.println("\n---- ボディ ----");

BufferedReader reader = new BufferedReader(new InputStreamReader(
urlconn.getInputStream()));

while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
reader.close();
urlconn.disconnect();
}
}

class HttpAuthenticator extends Authenticator {
private String username;
private String password;

public HttpAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}

protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}

public String myGetRequestingPrompt() {
return super.getRequestingPrompt();
}
}


でー、この結果をふまえ、次はAdobeAIRで挑戦。
URLConnectionで始めは試していたんだけど、何か上手く行かなくて結局URLLoader使いましたww

import flash.events.*;
import mx.utils.Base64Encoder;
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;

public function getProjects():void {
request("backlog.getProjects", null,
function (xml:XML):void {
trace(xml);
});
}

public function request(methodName:String, params:XML, callback:Function):void {
var loader:URLLoader = new URLLoader();
var request:URLRequest = createRequest();

var xml:XML = <methodCall></methodCall>;
xml.methodName = methodName;
if (params != null){
xml.params = params;
} else {
xml.params = '';
}

trace(xml);
request.data = xml;

loader.addEventListener(Event.COMPLETE,
function response(event:Event):void {
try {
var xml:XML = new XML(event.target.data);
callback(xml);
} catch (error:Error) {
trace(error);
trace(event.target.data);
}
loader.removeEventListener(ResultEvent.RESULT, response);
});

loader.load(request);
}

private function createRequest():URLRequest {
var request:URLRequest = new URLRequest("https://" + txtSpaceId.text + ".backlog.jp/XML-RPC");
request.cacheResponse = false;
request.manageCookies = false;
request.method = "POST";
request.contentType = 'text/xml';

//Basic認証用の設定
var encoder : Base64Encoder = new mx.utils.Base64Encoder();
encoder.encode(txtUser.text + ":" + txtPassword.text);
request.requestHeaders.push(new URLRequestHeader("Authorization", "Basic " + encoder.toString()));

return request;
}


プロジェクト一覧だけですが、AdobeAIR画面で表示できましたデス。
でも、XML-RPCのレスポンス形式って面倒ですねぇ。XMLなのにAIRのテーブル上にそのまま持って来れないのがなんとも残念。

んー、XML-RPC用にそぅいぅXML変換のライブラリを作っちまうかなぁ....
• • •