はてなハイクAPIに接続するためのjavaコード
はてなハイクAPIに接続し、エントリーを投稿するJavaのソースコードです。
ソースコード
以下、ソースコードの全文です。
import java.security.*; import java.io.*; import java.util.*; import java.text.*; import java.net.*; import java.util.zip.*; /** * はてなハイクAPIに接続するためのjavaコード * @author nattou_curry */ public class HatenaHaikuAPIAccess { // はてなハイクAPIのエンコーディング private static final String ENCODING = "UTF-8"; /** * statuses/updateでエントリーを投稿する。 * @param username ユーザ名 * @param password パスワード * @param status ステータス * @param keyword キーワード */ public static void postStatusesUpdate( String username, String password, String status, String keyword ) { String html; HttpURLConnection conn; ////////////////////////////////////////////// // 認証情報を生成する。 ////////////////////////////////////////////// String authorization = createAuthorization( username, password ); ////////////////////////////////////////////// // エントリー投稿用のクエリを作成する。 ////////////////////////////////////////////// String query; try { query = "status=" + URLEncoder.encode( status, ENCODING ) + "&keyword=" + URLEncoder.encode( keyword, ENCODING ); } catch ( java.io.UnsupportedEncodingException e ) { throw new RuntimeException( e ); } ////////////////////////////////////////////// // statuses/updateでエントリーを投稿する。 ////////////////////////////////////////////// conn = null; try { // 接続を開く。 conn = openConnection( "http://h.hatena.ne.jp/api/statuses/update.xml" ); // リクエストプロパティを設定する。 conn.setRequestProperty( "Authorization", "Basic " + authorization ); // POSTリクエストを送信する。 requestPost( conn, query ); // ステータスコードが正常であることを確認する。 if ( conn.getResponseCode() != 200 ) { // 正常でない: int code = conn.getResponseCode(); String message = conn.getResponseMessage(); throw new RuntimeException( code + " " + message ); } // HTMLを取得する。 html = getHTML( conn ); } catch ( IOException e ) { // 通信エラー: throw new RuntimeException( e ); } finally { // 接続を閉じる。 closeConnection( conn ); } } /** * BASIC認証用のヘッダ文字列を作成する。 * @param in_username ユーザ名 * @param in_password パスワード * @return BASIC認証用のヘッダ文字列 */ public static String createAuthorization( String in_username, String in_password ) { String string = in_username + ":" + in_password; byte[] tmp = getAsciiBytes( string ); String encoded = base64Encode( tmp ); return encoded; } /** * 文字列をASCIIのバイト配列に変換します。 * @param text 対象の文字列 * @return 変換後のバイト配列 */ private static byte[] getAsciiBytes( String text ) { byte[] ascii; try { ascii = text.getBytes( "ASCII" ); } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } return ascii; } /** * バイト配列をBASE64エンコードします。 * @param ascii 対象のバイト配列 * @return エンコード後の文字列 */ private static String base64Encode( byte[] ascii ) { // ASCIIをビットパターンに変換します。 StringBuffer bitPattern = new StringBuffer(); for ( int i = 0; i < ascii.length; ++i ) { int i_tmp = ascii[i] & 0xff; String bin_tmp = Integer.toBinaryString( i_tmp ); while ( bin_tmp.length() < 8 ) { bin_tmp = "0" + bin_tmp; } bitPattern.append( bin_tmp ); } // ビットパターンのビット数が6の倍数にするため、末尾に0を追加します。 while ( bitPattern.length() % 6 != 0 ) { bitPattern.append( "0" ); } // 変換表 final String[] table = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" }; // 変換表を利用して、ビットパターンを4ビットずつ文字に変換します。 StringBuffer encoded = new StringBuffer(); for ( int i = 0; i < bitPattern.length(); i += 6 ) { String tmp = bitPattern.substring( i, i + 6 ); int index = Integer.parseInt( tmp, 2 ); encoded.append( table[index] ); } // 変換後の文字数を4の倍数にするため、末尾に=を追加します。 while ( encoded.length() % 4 != 0 ) { encoded.append( "=" ); } return encoded.toString(); } /** * レスポンスヘッダよりクッキーを取得し、編集用のマップに設定する。 * @param conn HTTP接続 * @param cookieMap クッキー編集用のマップ */ private static void putCookiesToMap( HttpURLConnection conn, Map<String, String> cookiesMap ) { List<String> cookies = null; // レスポンスヘッダより、クッキーを取得する。 Map<String, List<String>> header = conn.getHeaderFields(); for ( String key : header.keySet() ) { if ( key != null && key.compareToIgnoreCase( "set-cookie" ) == 0 ) { cookies = header.get( key ); break; } } if ( cookies == null ) { // クッキーが取得できない場合: return; } // クッキーを分解し、編集用のマップに設定する。 for ( int i = 0; i < cookies.size(); ++i ) { String cookieLine = cookies.get( i ); String[] keyValuePairs = cookieLine.split( "; *" ); for ( int j = 0; j < keyValuePairs.length; ++j ) { String keyValuePair = keyValuePairs[j]; String[] keyValue = keyValuePair.split( "=", 2 ); String key = keyValue[0]; String value = null; if ( keyValue.length >= 2 ) { value = keyValue[1]; } if ( "Domain".equalsIgnoreCase( key ) ) continue; if ( "HttpOnly".equalsIgnoreCase( key ) ) continue; if ( "Expires".equalsIgnoreCase( key ) ) continue; if ( "Secure".equalsIgnoreCase( key ) ) continue; if ( "Path".equalsIgnoreCase( key ) ) continue; if ( "EXPIRED".equalsIgnoreCase( value ) )continue; cookiesMap.put( key, value ); } } } /** * 編集用のマップからクッキー文字列を作成する。 * @param cookieMap クッキー編集用のマップ * @return クッキー文字列 */ private static String cookiesMapToString( Map<String, String> cookiesMap ) { StringBuffer cookie = new StringBuffer(); for ( String key: cookiesMap.keySet() ) { String value = cookiesMap.get( key ); if ( value != null ) { cookie.append( key + "=" + value + "; " ); } else { cookie.append( key + "; " ); } } return cookie.toString(); } /** * HTTP接続を開く。 * @param requestURL リクエストURL * @return HTTP接続 */ private static HttpURLConnection openConnection( String requestURL ) throws IOException { return openConnection( requestURL, null ); } /** * HTTP接続を開く。 * @param requestURL リクエストURL * @param cookie クッキー * @return HTTP接続 */ private static HttpURLConnection openConnection( String requestURL, String cookie ) throws IOException { URL url = new URL( requestURL ); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setInstanceFollowRedirects( false ); conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6" ); conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ); conn.setRequestProperty( "Accept-Language", "ja,en-us;q=0.7,en;q=0.3" ); conn.setRequestProperty( "Accept-Encoding", "gzip,deflate" ); conn.setRequestProperty( "Accept-Charset", "Shift_JIS,utf-8;q=0.7,*;q=0.7" ); conn.setRequestProperty( "Keep-Alive", "300" ); conn.setRequestProperty( "Connection", "keep-alive" ); if ( cookie != null ) { conn.setRequestProperty( "Cookie", cookie ); } return conn; } /** * HTTP接続を閉じる。 * @param conn HTTP接続 */ private static void closeConnection( HttpURLConnection conn ) { try { OutputStream out = conn.getOutputStream(); out.close(); } catch ( Exception e ) {} try { InputStream in = conn.getInputStream(); in.close(); } catch ( Exception e ) {} } /** * 接続先のHTMLを取得する。 * @param conn 接続 * @return HTML */ private static String getHTML( HttpURLConnection conn ) throws IOException { ////////////////////////////////////////////////////////////////// // レスポンスヘッダより、GZIPを使用しているか判定する。 ////////////////////////////////////////////////////////////////// boolean usingGZIP = false; List<String> contentEncodings = conn.getHeaderFields().get( "Content-Encoding" ); if ( contentEncodings != null ) { for ( int i = 0; i < contentEncodings.size(); ++i ) { String contentEncoding = contentEncodings.get( i ); if ( contentEncoding.equals( "gzip" ) ) { usingGZIP = true; break; } } } ////////////////////////////////////////////////////////////////// // レスポンスデータを取得する。 ////////////////////////////////////////////////////////////////// StringBuffer buf = new StringBuffer(); BufferedReader in = null; try { // GZIPを使用しているかどうかにより、レスポンスの入力方法を変える。 if ( usingGZIP ) { // GZIPを使用している: in = new BufferedReader( new InputStreamReader( new GZIPInputStream( conn.getInputStream() ) , ENCODING ) ); } else { // GZIP を使用していない。 in = new BufferedReader( new InputStreamReader( conn.getInputStream(), ENCODING ) ); } int c; while ( ( c = in.read() ) != -1 ) { buf.append( (char) c ); } } finally { if ( in != null ) { in.close(); } } String html = buf.toString(); return html; } /** * GETリクエストを行います。 * @param conn HTTP接続 * @param query GETするクエリ */ private static void requestGet( HttpURLConnection conn ) throws IOException { conn.setRequestMethod( "GET" ); conn.connect(); } /** * POSTリクエストを行います。 * @param conn HTTP接続 * @param query POSTするクエリ */ private static void requestPost( HttpURLConnection conn, String query ) throws IOException { conn.setRequestMethod( "POST" ); conn.setDoOutput( true ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", query.length() + "" ); conn.connect(); OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), ENCODING ); out.write( query ); out.flush(); out.close(); } /** * PUTリクエストを行います。 * @param conn HTTP接続 * @param query PUTするクエリ */ private static void requestPut( HttpURLConnection conn, String query ) throws IOException { conn.setRequestMethod( "PUT" ); conn.setDoOutput( true ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", query.length() + "" ); conn.connect(); OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), ENCODING ); out.write( query ); out.flush(); out.close(); } /** * DELETEリクエストを行います。 * @param conn HTTP接続 * @param query DELETEするクエリ */ private static void requestDelete( HttpURLConnection conn ) throws IOException { conn.setRequestMethod( "DELETE" ); conn.connect(); } /** * 【デバッグ用】レスポンスヘッダを表示する。 * @param conn HTTP接続 */ private static void printHeader( HttpURLConnection conn ) { Map<String, List<String>> header = conn.getHeaderFields(); for ( String key : header.keySet() ) { List<String> list = header.get( key ); System.out.println( "[" + key + "]" ); for ( int i = 0; i < list.size(); ++i ) { System.out.println( list.get( i ) ); } } } }