Watcherはファイルの更新状況を監視するためのユーティリティをAgletにより実現したものです。これらは2つのAgletで構成されています。一方はWatcherで動かないエージェントです。他方はWatcherNotifierといい移動するエージェントです。WatcherNotifierはWatcherによりリモートホストに送り出され、そのサーバーにとどまってファイルが更新されるのを監視します。WatcherNotifierは普段は休止していて、定期的に起き上がりファイルが更新されたかどうかをチェックします。ファイルが更新されたらその都度WatcherNotifierはWatcherに知らせます。
のちほど述べます
少なくとも2つのAgletサーバーをネットワーク上で実行させますAgletサーバーの実行方法についてはここ をご覧ください)。
Tahitiの"new aglet"パネルでクラス名を "ibm.aglets.samples.Watcher"と指定して Watcher Agletを生成します(Agletサーバーの実行方法については Tahiti ユーザーガイドをご覧ください)。Watcher Agletが生成されるとダイアログ・ウィンドウが開きます。
リモートホストであるTahitiのURL を"Address"フィールド中に指定します(もしくはAddress Bookから選択します)。このURLは"atp://"に続いてホスト名、ドメイン名の形で指定します。ポート番号もあわせて指定することが出来ます。URLの例はこのとおりです。
atp://aglets.trl.ibm.com
またAgletサーバーがデフォルトのポート番号(434)以外で動いているなら次のようになります。
atp://aglets.trl.ibm.com:500
Agletのサンプルのトラブルシューティングに関してはここ をお読み下さい。
このプログラムは以下のクラスで構成されています。
WatcherクラスはSampleAglet抽象クラスを継承してステーショナリーなAgletとして作られます(SampleAglet 抽象クラスについてはここを参照してください)。Watcher クラスのgoメソッドでWatcherNotifier Agletが作られます。
protected void go(URL destination, double interval, double duration, boolean stay, String path) { super.go(destination); try { Notifier.create(null, NotifierClassName, getAgletContext(), this, new SeqItinerary(destination), interval, duration, stay, path); } catch (IOException ae) { ...... } } }
WatcherNotifierは単一の目的地を示す旅行計画(destinationパラメータ)と監視したいローカルファイル名(pathパラメータ)を与えられます。 あとのパラメータはチェックする時間間隔、監視し続ける時間、それから最初の変更を見つけた後も監視を続けるかどうかです。時間の単位で指定します。 Watcher Agletはノーティファイアのマスターと考えられます(Notifier.create メソッドの中ではthisという引数で表わされています)。
SampleAgletにあるデフォルトのhandleMessageメソッドは完全にオーバーライトされ、報告するメッセージ以外のメッセージはまったく受け付けないようになってます。
public boolean handleMessage(Message msg) { if ("notification".equals(msg.kind)) message((Arguments)(msg.getArg())); else super.handleMessage(msg); return true; }
報告メッセージはmessageというprivateなメソッドの中で扱われます。 受け取ったメッセージで(メッセージの中のtypeという変数を見れば)ファイルの更新があったのか、監視期間が終わったのか、それとも予期せぬエラーが起こったのかということがわかります。
private synchronized void message(Arguments message) { int type = ((Integer)message.getArgument("type")).intValue(); if (type == Notifier.NOTIFICATION) { _msw.appendResult( "UPDATE: " + (String)(message.getArgument("message")) + ", AT: " + message.getArgument("date").toString()); } else { setTheMessage((String)(message.getArgument("message"))); } }
WatcherNotifierクラスはNotifierクラスの中の抽象メソッドを実装しています。そのなかにinitializeCheck()とdoCheck()というメソッドがあります。 InitializeCheck()メソッドの中では、ノーティファイアーはファイルを見つけて最終更新時刻を記録しようとします(lastModifiedという変数です)。
protected void initializeCheck() throws AgletException { _filePath = (String)ARGUMENT; setText("checking update of " + _filePath); if ((f = new File(_filePath)) == null) { throw new AgletException("Null File object error"); } if (f.exists()) { _lastModified = f.lastModified(); MESSAGE = _filePath; return; } else { throw new AgletException("Access Non-Existing File"); } }
doCheck()メソッドの中では、ファイル更新を検出するのに現在の最終更新時刻と自分が知っている最終更新時刻(lastModified変数)とを比較します。 もし変化があれば、ファイル名をMESSAGE変数の中に記録します。そして最終的には報告メッセージとして送られます。
protected boolean doCheck() throws AgletException { long time; if (f != null) { // get the timestamp of the target file time = f.lastModified(); if (_lastModified != time) { MESSAGE = _filePath ; // update _lastModefied timestamp _lastModified = time; // file has changed on time "Date(time)" return true; } } else throw new AgletException("Null File object error"); // no change on the target file return false; }
Watcher Agletについてより詳細な情報をお望みならソースコードをお読み下さい。