NicoCache 開発者向けメモ

* NicoCache 0.20以降の構造

中核部分は特にニコニコに依存しない、
汎用のプロキシフレームワークになっています。

通信処理の面倒なことはフレームワークに任せて
必要な機能だけを実装すれば機能を追加できます。
ニコニコのキャッシュ機能も拡張機能の一つとして実装しています。

とはいえまだまだ不十分なので本体にも手を入れないといけない部分は
いろいろあると思いますが、順次整備して
(or他の開発者様に整備してもらったものを取り込んで)
いきたいと思います。

** 主要クラスの役割

フレームワークの主要なクラスの役割は以下の通りです。
処理の順番に沿って並べます。

Server: ブラウザからの接続を受け付けてConnectionManagerに渡す。
  1つのConnectionManagerオブジェクトにスレッドを1つ割り当てる。
  (ConnectionManagerはマルチスレッド処理を意識しなくてよいように)

ConnectionManager: ブラウザと接続を管理する。
  ブラウザ側のソケットと同じライフサイクルを持つ。
  リクエストの内容に応じて適切なProcessorを選択して
  処理を委譲する。
  0.1x系のConnectionProcessorのConnectionな部分を分離したもの。

Processor: リクエストの処理をする。
  Processor自体はインタフェースで、実際の処理は
  これを実装したクラスが行う。
  0.1x系のConnectionProcessorのProcessorな部分を分離したもの。

Resource: ブラウザに渡すデータとその取得方法を
  フレームワークが一律に扱えるように抽象化(統一化)する。
  Resource自体は抽象クラスで、サーバからデータと取ったり
  ファイルからデータを取ったり、文字列でレスポンスを生成するのは
  これを継承した具象クラスが行う。

** 典型的な機能拡張方法

基本的に次の流れで拡張できます。

(1) Processorの実装クラスを作る。
    どのメッソド、どのURLのリクエストが来たら呼び出して欲しいかと、
    そのリクエストが来た時の処理を実装する。
(2) Serverの中でProcessor実装クラスをnewする。
    作ったProcessor実装クラスがマルチスレッドに対応しているなら
    1個だけnewして使いまわすと性能が上がります。
    標準で入っているProcessorをnewしているところを参考に。
(3) Server#registerProcessor()でConnectionManagerに登録する。

(オプション)リソースのブラウザへの転送に割り込みたい場合は
TransferListenerの実装クラスを作ってResourceに登録します。

サーバからのレスポンスを一度全部受け取って
編集してからブラウザに送るような処理は
0.20時点だともっといろいろとコーディングする必要があります。
そういうデータの受け渡しをするResourceの具象クラスが必要でしょう。

0.20時点で、標準で次の3つのProcessor実装クラスがあります。

GetPostProcessor: GETとPOSTリクエストを素通しする。
  大部分の処理はフレームワークがやってくれるので
  GetPostProcessor全体で30行ほどです。

ConnectProcessor: CONNECTリクエストを素通しする。
  こちらも30行ほどです。

NicoCachingProcessor: ニコニコの動画をキャッシュする。
  ニコニコに依存した処理はこれとこれのヘルパークラス
  (NicoCaching*)のみに局所化されています。
  動画の転送に割り込んでキャッシュするために
  TransferListenerを使っています。

細かい説明はソースのコメントを参照してください。

将来的にはプラグインのようにして本体を全くいじらなくても
拡張できるようにしたいと考えています。

* 設定値の定義方法について

** 置き場所はシステムプロパティ

0.20までは設定値はConfigオブジェクトに格納していましたが、
0.21からはシステムプロパティに設定値を入れるようにしました。
派生版ごとに独自の設定を入れるためにConfigに修正が発生して
衝突してしまうことを避けることが目的です。

# 設定値を実行中に変えられるようにしたときにちょっと問題があるのですが
# 現時点ではコーディングの楽さを優先します。

以下のようなコードで設定値を取り出せます。

文字列の場合:
String value = System.getProperty("設定名");
真偽値として解釈する場合:
Boolean value = Boolean.getBoolean("設定名");
整数として解釈する場合:
Integer value = Ingeter.getInteger("設定名");
Integer value = Ingeter.getInteger("設定名", デフォルト値);

Configはしばらく残しておきますが、
今後新しい設定が増えたときにはシステムプロパティの方だけに入れていきます。

** デフォルト値の定義

0.21からdefaultsディレクトリにpropertiesファイルを入れておくと
設定のデフォルト値として読み込むようになりました。
派生版がそれぞれConfigを初期化するコードのためにMainなどを修正して
衝突してしまうことを避けることが目的です。

config.propertiesに設定がない場合はここで定義した値が有効になります。

NicoCacheがもともと持っている設定は「00_NicoCache.properties」
という名前で置きます。
ファイル名順に読み込むので「90_CustomNicoCache.properties」
のような名前にすれば同じ設定名の設定を上書きすることができます。
