Java

2010年11月24日 (水)

動画共有サイトのコメントをヒートマップで表示するソフト

 一年半以上前のものですが、ニコニコ動画などのコメント(xmlファイル)を読み込んでヒートマップ表示するソフトを作りました。
 これはサーモグラフィーのように、投稿されたコメントの盛り上がりを可視化するソフトで、コメントが過密なところは赤く、逆に過疎っていうところは青く表示されるようになっています。

 これにより「視聴者がいつの時間帯に視聴しているか」「動画の何分何秒に多くの反応を示しているか」を知ることができます。主に動画投稿者が、視聴者の傾向や映像作品の反響を知りたいとき使えるんじゃないかと思います。

 似た機能を持つものとして、FireFoxのGreasemonekyスクリプトである、heat_the_nicovideo_up があります。こちらはWebサイト上にてプレイヤーと一緒にヒートマップを表示するタイプのもので、直近数百件のコメントを読み込んでヒートマップ表示することができます。

 こちらのCommentHeatMapでは、xmlのコメントファイルを読み込み、現実世界の時系列動画の再生時間とでコメントの分布を見ることができます。一つのアプリケーションとして機能しWeb上で動画プレイヤーと連携などはしません。また、コメントファイル(xml)についても自動ダウンロード機能はつけていないので、各自で用意してください。

 つけようかと思ったんですが、負荷をかけると怒られそうな気がしたのでつけてません(;´∀`)
 xmlファイルのダウンロードなどは運営サイト様に迷惑のかからないようにお願いします。また、ダウンロード方法についての問い合わせには答えることはしないので、それぞれ自己責任でお願いします。このソフトウェアを使用することによって生じる損害や賠償などの責任は一切負いかねますのでご了承ください(お約束)

 だいたい2MB、17000コメントのxmlをドラッグアンドドロップで読み込ませた結果が以下。ソフト的には7MB程度のxmlまで読み込めますが、それ以上は固まってしまいます。そのときは×で終了させてください。(Buggyな仕様)

スクリーンショット:
Heat01_2

 

Heat02_3

ダウンロード:

jarファイル
「HeatMapv02x.jar」をダウンロード

exeファイルの方が良い方はこちら
「CommentHeatMap_v02.zip」をダウンロード

 

2010年9月29日 (水)

Javaでサーモグラフィーの色のグラデーションを再現(6)

前回 からの続きです

 Javaで「サーモグラフィーの色のグラデーションを再現」のまとめとして作成したソースコードを載せます。

「HeatmapUtility.java」をダウンロード

このクラスは3つのコンストラクタを持っています。

public HeatmapUtility(int max)
public HeatmapUtility(int max, boolean reverse)
public HeatmapUtility(int min, int max, boolean reverse)

 maxは最大値を、minは最小値、reverseはスケールの反転を指定します。
最大値のみを指定する場合には、最小値は0、スケール反転無しになります

HeatmapUtility util = new HeatmapUtility(128);

 最大値128、最小値-128、反転無しとしてインスタンスを作成する場合以下のようになります。

HeatmapUtility util = new HeatmapUtility(-128, 128, false);

 インスタンス化した後、色を取得するにはint getColor()メソッドを使います。

public int getColor(int value)

 コンストラクタで指定した最大値と最小値の範囲で値をvalueに指定すると、サーモグラフィーの色域で対応したint型の色を取得できます。引数に最大値、最小値を超える値を指定した場合は、それぞれ最大値、最小値として扱われます。

 取得したint型の色は、他クラスで色の指定に使ってください。

int colorValue = util.getColor(64);

 java.awt.Colorのコンストラクタへ渡しColorのインスタンスを作成できます。

Color color = new Color(colorValue);

 ソースの中に記述がありますが、今回は単純なマッピングを行っており他にcosを用いたものと、三次関数によって近似したものとが注釈してあります。参考程度に見てみてください。

 温度分布を表すグラデーションには、様々な色の表現方法があるようです。今回紹介した色の移り変わりは一般的なもので、RGB値の移り変わりから見ても妥当だと思われます。しかしながら、紫と橙を用いたヒートマップの表現系や、水色を省いた色域を用いたものなど、企業・製品・研究領域によって変わってくると思われます。

 今後はそういったサーモグラフィーの表現方法の違いを調べ、それらを実装する方法についてまとめようと考えています。

2010年9月26日 (日)

どうしてJaveでCookieが取得できないんだろう?(5)

前回 からの続きです。

 前回はJavaでログインサイトからのセッションIDを取得する際に、クッキーが取得できないという問題について述べました。これは各ログインサイトが行っている複数の古いクッキーの上書き処理が、Java側のクッキー適用順の違いによって新しいクッキーまで消してしまっているためで、これによりセッションIDを含んだクッキーを取得できませんでした。

今回はこの問題について再度、発生する条件をまとめ、対策について触れていきます。

 さて、前回の「クッキー適用順の怪」問題でしたが、まずは”Set-Cookie”ヘッダについて、”Set-Cookie”ヘッダはHTTPヘッダに複数含めることができます。しかしながら、複数存在する”Set-Cookie”ヘッダをどの順番で適用するかの条件は調べても見当たりませんでした。

Javaでは、この複数のSet-Cookieヘッダの文字列を取得すると、なぜか、先頭と後尾が順序逆転したリストで得られます。そのため、複数のクッキーヘッダを上から順番に処理し、上書きするということを暗黙的に期待して構築されているWebサイトでは、問題が起こる可能性があります。

 いくらSet-Cookieヘッダはどの順番で適用するか決まってないと言ったとしても、ここはJavaのクッキーヘッダの適用順序が一般的でないことが問題なのでしょう。

・対策

 ということで、Javaで正常にSet-Cookieヘッダをクッキーとして取得できるように簡単な修正を施します。修正を施すのは、CookieManagerです。このCookieManagerを修正することで、順序が逆転しているクッキーヘッダを正しい順序で処理するように変更します。

 ここでの注意としましては、クッキーヘッダの順序が逆転しているからといってそれを単純に逆転し直すということはしません。なぜか? それはこの問題は今後Javaのアップデートによって修正される可能性があるからです。目標としては、クッキーヘッダの順序の取り扱いが正しくなったとしても動作するように実装します。単にJavaのバージョンによる依存を残したくないからなんですが。

「CorrectedCookieManager.java」をダウンロード

 このクラスはCookieManagerを継承しており、クッキーを格納する際に呼び出されるpublic void put(URI uri, Map<String, List<String>> responseHeader)をオーバーライドしています。

 内部ではSet-Cookieヘッダのリストを、expireの日付順にソートし直し、古いものが先頭にくるようにしています。なお、取得できるヘッダのリストやマップは変更不可なので、それぞれコピーを作成してからソートし、その後スーパークラスであるCookieManagerへ丸投げしています。

 またこのクラスには、第一のexpire解析失敗バグについても対策が施されています。まずpublic static boolean isParsable() というメソッドが定義されており、クッキーのexpire解析のテストを行えます。もしも正しく解析できない場合には、実際のクッキー解析の際にLocation.setDefault(Locale.US)を実行したり、元のロケールに戻したりということを行います。

 実際の使い方ですが、

CorrectedCookieManager manager = new CorrectedCookieManager();
CookieHandler.setDefault(manager);

 これで、以降のHttpURLConnectionでのクッキー処理は正しく行われます。ほとんどの機能はCookieManagerに準じていますし、変更も30行程度の追加だけなので、誰でも簡単に実装できると思います。

 ちなみにCorrectedCookieManager.javaにはデモプログラムとしてmainメソッドが記述されていますので、CookieManagerとして使う以外にも、自身のJVMのクッキー処理の様子などを見ることができます。よかったら実行して見てください。エンコーディングはUTF-8です。

 これでやっとJavaの基本の処理機構をを用いてのWebプログラミングの準備が整ったと言えます。これで「どうしてJavaでCookieが取得できないんだろう?」を終えて、次はJavaで作るシンプルなHTTPclient編に挑戦したいと思います。それでは。

2010年9月18日 (土)

どうしてJaveでCookieが取得できないんだろう?(4)

 前回からの続きです

前回はJavaの「expire解析失敗バグ」について触れました。これは有効期限が読み取れないためにクッキーが消滅してしまうもので、対策としてJavaのロケーションを日本からUSへ変更することをあげました。他の方法としてはJavaのバージョンを最新のものへアップデートしてください。2010年9月現在、Javaの最新版は「1.6.0_21」となっています。
自分で使う分にはアップデートだけでいいんですが、ソフトウェアの配布をする場合には利用者へ周知したり、対策する必要があるかと思います。

さてでは今回はもう一つのバグ、「クッキー適用順の怪」について触れていきます。

みなさんはJavaでログインサイトにアクセスし、ログインする際にどのようにプログラムしているでしょうか? ログインとはWebサイトからSessionIDを取得するまでのことです。

例えばmixiの場合は、http://mixi.jp/login.plというURLへ「email=abcd@example.jp&password=abcdefg&next_url=./home.pl」という文字列を「POST」します。そして帰ってきたレスポンスの中のクッキーからSessionIDを取得します。

他にはニコニコ動画の場合は、https://secure.nicovideo.jp/secure/login?site=niconicoというURLへ「mail=abcd@example.jp&password=abcdefg&next_url=」という文字列を「POST」します。そして同様にレスポンスの中のクッキーからSessionIDを取得します。

実は今回指摘するバグは、この特定のサイトのログイン時でのSessionIDの取得ができないというものです。ここで注意すべきは、セッションID取得時以外のクッキーは通常通り取得できるということです。かなり厄介ですね。

さて、よくあるログインサイトで行われる手法に、古いSessionIDを消すためにわざと有効期限の切れたCookieを送信して上書きし、新しいSessionIDをクッキーに格納するものがあります。その上書き用のクッキーはdeletedという値がよく使われます。そのあたりの詳しい事情はPHPやdeletedで検索することで知ることができます。

さて、今回Javaで問題となるのは、この古いクッキーの上書き処理です。下を見てください。

HTTP/1.1 302 Found
Date: Sat, 18 Sep 2010 11:44:27 GMT
Server: Apache
X-Powered-By: PHP/5.2.9
x-niconico-authflag: 0
Set-Cookie: user_session=deleted; expires=Fri, 18-Sep-2009 11:44:26 GMT
Set-Cookie: user_session=deleted; expires=Fri, 18-Sep-2009 11:44:26 GMT; path=/
Set-Cookie: user_session=deleted; expires=Fri, 18-Sep-2009 11:44:26 GMT; path=/; domain=.nicovideo.jp
Set-Cookie: user_session=user_session_5432109_123456789012345678; expires=Mon, 18-Oct-2010 11:44:27 GMT; path=/; domain=.nicovideo.jp
Location: http://www.nicovideo.jp/
Content-Length: 0
Connection: close
Content-Type: text/html

これは古いクッキーの上書き用のクッキーと、新しく格納するセッションIDを含んだCookieヘッダの例です。上から順に、丁寧に上書きしているのが分かります。そして最後の行に新しい(有効期限の切れていない)セッションIDが含まれているわけです。

ここで恐ろしいのは、誰もが当たり前のように上から順にクッキーが適用されていくはずだと考えることです。サイト側の人もまさにそう考え、最後にセッションIDだけが残ると考えているはずです。しかしながらここで悲劇は起こります。

以下はクッキーがCookieStoreへ格納される際に呼び出された出力です。
Java内にてクッキーが格納される順番を御覧ください。

boolean shouldAccept(URI uri, HttpCookie cookie)
uri           : https://secure.nicovideo.jp/secure/login?site=niconico
cookie name   : user_session
       value  :
user_session_5432109_123456789012345678
       domain : .nicovideo.jp
       path   : /
       maxage : 2592002
       secure : false
       port   : null

boolean shouldAccept(URI uri, HttpCookie cookie)
uri           : https://secure.nicovideo.jp/secure/login?site=niconico
cookie name   : user_session
       value  :
deleted
       domain : .nicovideo.jp
       path   : /
       maxage : -31535998
       secure : false
       port   : null

boolean shouldAccept(URI uri, HttpCookie cookie)
uri           : https://secure.nicovideo.jp/secure/login?site=niconico
cookie name   : user_session
       value  :
deleted
       domain : secure.nicovideo.jp
       path   : /
       maxage : -31535998
       secure : false
       port   : null

boolean shouldAccept(URI uri, HttpCookie cookie)
uri           : https://secure.nicovideo.jp/secure/login?site=niconico
cookie name   : user_session
       value  :
deleted
       domain : secure.nicovideo.jp
       path   : /secure/
       maxage : -31535998
       secure : false
       port   : null

 

・・・最初にセッションIDを格納し、あろうことか同ヘッダー内の上書き用クッキーにて上書きされています。セッションIDは消去され、上書き用クッキーも前述の理由で直ちに削除され、最後には何も残りません。

なぜこうなるのか? 実は複数のクッキーヘッダが存在した場合、クッキーの適用順が後尾から先頭順になっているようなのです。Java内部の実装を詳しく調べたわけではなく、今のところは明白な理由は不明です。ただHttpURLConnectionのgetHeaderFieldsによって取得できるSet-Cookieヘッダの文字列のListは既に逆順になっていました。
これはCookieManagerやCookieStoreの問題ではなく、URLConnection側の問題な気がします。

さて、このセッションIDが取得できない理屈を理解していただけたでしょうか。今回は少し長くなりましたが、私はこの問題に気づくまで1年半ぐらいかかりました。ということで「クッキー適用順の怪」の解説を終え、次回はこの問題が発生するサイトや条件をまとめ、このバグへの対処方法を検討していきます。お疲れ様でした。

次回へ続く

 

2010年8月23日 (月)

どうしてJaveでCookieが取得できないんだろう?(3)

 前回からの続きです

 これまでJavaでWebサイトにアクセスし、クッキーを取得するためのクラスや、その使い方を見てきました。そして実際に取得し、内容を表示するというところまで紹介しました。そして今回はJavaでクッキーを取得できないという第一のバグ、クッキーの「expire解析失敗バグ」について紹介します。

 最初に以下のクッキー内容取得の実行結果を見てください

java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)

Locale.setDefault(Locale.US)無し

uri           : http://www.google.co.jp/
cookie name   : PREF
cookie value  : ID=7bd227444e93a18e:TM=1280988476:LM=1280988476:S=bokonC_ksiGm2V3A
cookie domain : .google.co.jp
cookie path   : /
cookie maxage : 0 - (Thu Aug 05 15:07:56 JST 2010)
cookie secure : false
cookie port   : null

Locale.setDefault(Locale.US)有り

uri           : http://www.google.co.jp/
cookie name   : PREF
cookie value  : ID=010eb8da414554a5:TM=1280988552:LM=1280988552:S=yh0MOlC2T0sHbAi9
cookie domain : .google.co.jp
cookie path   : /
cookie maxage : 63071999 - (Sat Aug 04 15:09:11 JST 2012)
cookie secure : false
cookie port   : null

 これは、クッキーの有効期限であるexpireの解析が失敗し、値を読み込めていない状態と、成功して正常に読み込めている2つの実行結果を示しています。

 この2つの実行結果の違いはなんでしょうか? 赤字で示されていますが、CookieのMaxage値が異なっています。一方は0で、もう一方は63071999です。実行環境は同じなのですが、どうしてこのように実行結果に違いが出たのでしょうか?
 違いについては既に示してあるのですが、Javaのデフォルトのロケーションに変更を行っています。実はJavaはロケーションがJapanのままだと、expireの解析に失敗します。(※ちなみにJREのバージョン"1.6.0_20"ではこの問題が修正されています!
参考リンク
 
 
 実はJavaは、クッキーヘッダの有効期限を解析する際に、各地域の言語に合わせて読み込もうとしています。なので、標準の書式である
 Sat, 04-Aug-2012 15:09:11 GMT

というヘッダ内の有効期限を、日本国内では

土, 04-8-2012 15:09:11 GMT
と認識しようとしているのです。
 当たり前ですがこのようなクッキーヘッダは存在しませんから、100%解析に失敗します。
expireの解析に失敗するとどうなるでしょう?MaxAgeとは、クッキーの残り有効秒数のことです。この値に0が格納されるため、このクッキーは直ちに削除されます。
(上の実行結果はどうやって取得したのかというと、クッキーの削除はCookieStoreが担っているので、CookieStoreへ格納するかの是非を判定するCookiePolicyをラップし、内容を表示してから真偽を返すように実装してあります。)

 以上のことから、日本国内ではHttpURLConnectionを使ってクッキーを扱う際には、その前にLocale.setDefault(Locale.US)を実行する必要があります。JavaVMに、ここはアメリカだよ~と教えておくことで、英語でexpireを解析してくれるようになります。

 さて、これで少なくともクッキー取得できない現象は回避できるようになりましたか?対策もばっちりですね。しかし! まだ我々には問題が立ちはだかっているのです。次回は、現在進行形で存在する問題、「クッキー適用順の怪」について触れていきたいと思います。

2010年8月 5日 (木)

どうしてJaveでCookieが取得できないんだろう?(2)

 前回の記事からの続きです。

 前回Webサイト上の通信にはCookie処理が必要不可欠だということを述べました。そこでCookieをJavaで扱えるようにして、色々なWebサイトやAPIと通信するようなプログラムを作るぞ!と思っていたのですが、ここで大きな壁が立ちはだかっていました。

 検索すると多くのページが見つかると思いますが、Java標準のCookie処理機構を用いたプログラムではCookieや、それに含まれているSessionIDの取得がうまくできないということが多く起こります。

 なぜ取得できないのか? 現象としては、いざJavaを使いWebページへログインしてSessionIDの入ったCookieを受け取った!という段階で、実際にCookieの格納場所を見てみると空っぽ、ということが起こるのです。

 この現象については皆さんそれぞれ工夫されているようで、自力で応答ヘッダからCookieとSessionIDを読み取って、それを送信時にリクエストヘッダにセットし直すなどの対処をしている人が多いようです。この方法は確実ですし、手っ取り早いのでいいのですが、根本的な解決ではありませんし、なにより毎回の作業が増えてしまいます。

 なんとかしてこのJavaのCookie処理機構の遺産を活かすことができないか…というのがこのシリーズの目標です。

・JavaでのHTTPクッキーの取得方法

 まず本題であるJavaのCookie処理のバグについて話す前に、前提であるCookie処理のクラスやその基本の使い方を説明しておきたいと思います。

 Webサイトへアクセスする際にはHttpURLConnectionが使われますが、このクラスは前回紹介したCookieManagerと見えないところで連携しており、Webサイトへアクセスする際には送信するCookieが無いかCookieManagerへ問い合わせ、自動でリクエストヘッダへCookieをセットしてくれます。

 逆に、サイトへアクセスした後、サーバからクッキーが送られてきた場合にもHttpURLConnectionは受け取ったCookieをCookieManagerへ渡してくれます。CookieManager内ではサーバのドメインごとに送るCookieを選んだり、色々な条件に基づいてCookieを削除したりといった作業を行っています。

 最終的に保存されたCookieを取得するには、CookieManagergetCookieStore()メソッドを使い、CookieStoreを取り出します。これが実質のCookie保存場所であり、この中からgetCookies()メソッドを使うことでHttpCookieのリストを得ることができます。

 CookieManagerは複数作ることができて、状況に応じて切り替えるといったことができます。CookieHandler.setDefault(CookieManager)というメソッドでCookieManagerを指定することで、HttpURLConnectionにて呼び出されるCookieManagerが切り替わります。

CookieManager man = new CookieManager();
CookieHandler.setDefault(man);
URL url = new URL("http://www.yahoo.co.jp")
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.getResponseCode();

CookieStore store = man.getCookieStore();
List<HttpCookie> cookies = store.getCookies();

 

 クッキーの内容を表示してみた結果は下のようになります

url : http://www.yahoo.co.jp/
cookie

name : B
value : b5vq21165l7m8&b=3&s=gs
domain : .yahoo.co.jp
path : /
maxage : 63189418
secure : false
port : null 

 ちゃんと取得できてるようですね!

 え?取得できない?
 もしかしたら、このような単純なクッキー取得でさえも上手くいかない人がいるかもしれません。次回は、第一のバグ、クッキーの解析失敗バグについて触れたいと思います。

どうしてJaveでCookieが取得できないんだろう?(1)

 Javaは数多くのAPIが用意されており、ネットワーク関連においてもそれは大いに言えることです。

HTTPでWebサイトのページを取得するのも、

URL url = new URL("http://www.google.co.jp/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
InputStream in = con.getInputStream();

これでストリームからHTMLページを読み込むことができます。

 単純にHTMLを読み込むだけならこの方法で済みますが、しかし最近のWebサイトはCookieを使ってMyページや履歴を管理するといったことをしています。Googleのトップページを取得するよりも、自分の管理ページなどにアクセスして操作できた方がプログラムの幅も広がるというものです。

 ということで、WebへのアクセスにはCookieの処理が必要不可欠となります。今回の記事ではJavaに搭載されている標準のCookie処理機構を使ってWebページへのログイン処理について触れていきます。と同時に、現在のJavaに潜むCookieが取得できないという謎のバグについても追求していき、その原因と解決方法を紹介したいと思います。

HttpURLConnectionCookieManager

 Javaには標準でCookieを自動で処理してくれる機構が備わっています。これはJava6.0から導入されたもので、代表的なクラスとインタフェースは
 CookieHandler
 CookieManager
 CookiePolicy
 CookieStore
です。

 これらは普段意識せずとも自動で使われており、もしも細かい設定やデータが欲しいというときには事細かに自分で実装し直すことができる優れものとなっています。その細かい設定については省略して、まずは使い方、そして実際にCookieの取得と送信を自動でやってくれている様子を次回見たいと思います。

 ちなみに、各クラスとインタフェースの役割はこちら

CookieHandler
どのCookie管理マネージャを使っているのか取得したり、切り替えなどを行う機能を提供

CookieManager
Cookie管理をする本体で、クッキーを実際に保存したり選択したりするクラス

CookiePolicy
Cookieを受け入れるかどうかのルールを定義してある、CookieManagerの手下1

CookieStore
Cookieが実際に格納される場所、CookieManagerの手下2

 それではまた次回

2010年4月27日 (火)

Javaでクッキーを使えるHTTPクライアント(2)

 前回の記事からの続きです。
 前回はJavaで使えるHTTPクライアントとしてJakarta Commons HttpClientを紹介しました。
 というわけでこれからいろいろなインターネット上の会員サービスへログインしてみましょう。

 しかしちょっと待ってください。そもそもウェブサイト上でログインする、というのは具体的にはどのような処理が必要でしょうか? IDとパスワードを入力しログインボタンを押す、といった処理が思い浮かびますが、プログラムからログイン処理をするにはどうすればよいのでしょうか。

 なのでJavaプログラムを書く前に、ここでは具体的なログインの仕組みや、手続きについて調べたことを書いておきます。

ログインとは?

そもそもログインとは、ID,パスワードをサーバに送信しユーザを特定してもらうことです。
普通はIDとパスワードを入力して送信し終わると、次からは自分専用に用意されたページを利用できるようになります。

このときのサーバとクライアントのやり取りの図を以下に示します。

Sessionid480resize

 図のようにクライアントは、ログインサーバへHTTP(プロトコル)のPOSTメソッドというコマンドを使ってIDとパスワードを送信します。これは通常、Webページに入力フォームが用意してあり、ボタンを押すだけでお手軽に送信できるようになっているので、日ごろ意識することはありません。

 そしてサーバ側では、送られてきたIDとパスワードを確認し、それが正しければユーザへセッションIDを送ります。このセッションIDというものはIDとパスワードの代わりにユーザを特定するためのもので、ユーザは受け取ったセッションIDを保存しておきます。これは普段はブラウザが自動でやってくれています。

 このとき、セッションIDはクッキーと言う仕組みを用いてブラウザに保存されています。クッキーとはサイトごとにブラウザにデータを保存しておける領域のようなものです。ブラウザは保存しておいたセッションIDを次回から毎回Webページにアクセスするときに一緒にサーバへ送ります。これによりサーバ側は利用者が誰なのかを判別して、メンバー専用ページを表示したり、サービスの提供を行えるようになります。

 以上が現在広く利用されているWebサービスの典型的な形になります。
いずれもブラウザを介してWebページにアクセスしている時には深く意識しないものばかりですが、これらの処理をすべてJavaアプリケーションを通じて行うには、上記の処理すべてをコード上でで行わなければなりません。

 幸い、クッキーなどある程度自動で処理してくれるライブラリがすでに揃っており、Jakarta Commons HttpClientもその一つです。次回は実際にHttpClientのクラスやメソッドを紹介して、ブラウザのログイン処理を代替させてみたいと思います。

2009年4月10日 (金)

Javaでクッキーを使えるHTTPクライアント(1)

やりたいこと:
Javaアプリケーションでどこかのサイトへログイン、通信する

そのために必要なもの:
クッキーの処理機能を備えたHTTPクライアント


 Javaでクッキーを自動で処理してくれるHTTPクライアントを用意したいと思い、色々調べたことを書きたいと思います。

 まあ、結果的に言うと既にJavaベースで動くクッキーを扱えるHTTPクライアントが数多く作られていて、その中でも Jakarta Commons HttpClient というのがなかなかいい感じです。

Jakarta Commons HttpClient

 クッキーを自動で処理してくれる!!

 POSTやGETリクエストをURLConnectionやSocketなんかで送ることは簡単ですが、サーバから帰ってくるCookieを読み取り、クッキーの追加、選択などをして、また次のリクエストにはクッキー付きで送るといった作業はかなり面倒ですね。
 クッキーの扱いもHTMLプロトコルをちゃんと勉強しないといけないし、いろいろな属性値の意味や値も考えなければならなくなるだろうし、しかもそれをSocketでひたすら組もうというのはなかなか、楽しそうではあります。
 ですが今回はネット上のサイトでログイン処理とその他の通信を実現することを目的としているので、HTTPクライアントを作るのは別の機会ということに。

 ということで次回からちょこっとこのHttpClientの使い方をメモっておくことにします。


※10/04/27 リンクが切れていたので修正

.

2009年4月 7日 (火)

Javaでサーモグラフィーの色のグラデーションを再現(5)

 前回からの続きでたぶん今回で最後です。

 今まで考えてきた色調の再現方法やJavaの知識を使い、どうやってクラスを作るかを考えます。これはあくまで自分なりの方法なので、違う形でクラスを作ることも全然構わないと思います。みなさんなりに書いてみてください。
 まずクラスの初期設定として

 ・全部で何段階の階調か
 ・スケールの反転

 などがあればよいかと思います。
 サーモグラフィーの色調を全何段階で表現するか、というわけでここでは128や1024など、つまり最大値を設定します。0=黒、最大値=白というわけです。
 スケールの反転というのは、0=赤、最大値=黒、という風に設定することで、色の設定を反転するわけです。この設定はあとからメソッドで変更できるようにして、コンストラクタでも省略できるようにしておけばいいでしょう。あくまでオプションです。

 メソッドとしては引数に0から最大値までのintの値を取り、戻り値としてsRGB値を持つintを返すものが考えられます。Colorクラスのオブジェクトを返してもいいでしょう。
 そしてその中身ですが、指定された値が最大値の何%かを考えて、色と色の間6通りの段階のどの部分に当たるかを出します。さらに、その色域における256段階で何段階目かを計算します。ここまでの計算は共通なので短い記述で済みますが、色域によって色を作るのに6通り処理を記述する必要があります。
 ここについてはもっといい方法がありそうなんですが、とりあえず簡単なのでこうしました。

RGB値:
白 : 赤100% 緑100% 青100%
 ~赤のGBに0-255を乗せる~
赤 : 赤100% 緑  0% 青  0%
 ~赤のGに255-(0-255)を乗せる~
黄 : 赤100% 緑100% 青  0%
 ~緑のRに0-255を乗せる~
緑 : 赤  0% 緑100% 青  0%
 ~緑のBに255-(0-255)を乗せる~
水 : 赤  0% 緑100% 青100%
 ~青のGに0-255を乗せる~
青 : 赤  0% 緑  0% 青100%
 ~黒のBに0-255を乗せる~
黒 : 赤  0% 緑  0% 青  0%

 なんともお粗末なことになってますが、このようにしました。
 基本の7色は事前に定義しておき、各パターン時に各RGBを適宜上書きする感じで、実際は赤緑青黒しか使いません。ううん、どうにも綺麗にいきません。
 とりあえずこの条件分岐先で色を作り最後に色を返します。
 以上が主となるメソッドです。最初の方に反転設定されているかによって引数値を最大値の半分の値に対して反転するする処理を入れておき、後からでも変更できるようにしておけばよいでしょう。
 そして別途その反転設定をするメソッドを付け加えておけば、当初の目的となるクラスはだいたい完成すると思います。

 長々と書いてきましたが、実際はかなり短く、簡単なことですね。とりあえずここまでとして、また後で作ったクラスなどソースで紹介したいです。寝よう。