第1回 JXTA ShellからJXTAを知る


パイプを使った通信と「告知」

 「Viva! JXTA 〜JXTAはネットワークを変える〜」でも紹介しましたが、JXTAの特徴の1つは、いろいろなところで「告知(advertisement)」と呼ばれるメッセージが大きな役割を果たしていることです。「告知」は、JXTA内部のさまざまなオブジェクト1つ1つに付けられた「名札」のようなものです。単なる「名札」と違うのは、オブジェクトの「名前」だけでなく、それぞれのオブジェクトに固有の特徴のある「記述」を含んでいることです。JXTAは、ネットワーク上でさまざまな種類の「告知」を交換しあいます。「告知」の情報を使えば、「告知」に対応するオブジェクトを生成することも不可能ではありません。JXTA-Shellでは、パイプを作るのにもピアグループを作るのにも「告知」を使います。

 すべてのUNIXの「プロセス」に標準入出力が定義されているように、JXTAの「ピア」には、入出力のためのパイプ・サービスが用意されています。これも、JXTAの大きな特徴の1つです。「告知」を活用して、2つのピア間でパイプを利用したメッセージの伝達を行うことは、JXTA-Shellの最も基本的な課題の1つです。

 ここでは、次のような項目について説明します。

(1)入力パイプの生成
(2)出力パイプの生成
(3)メッセージを作る
(4)Messageとput/get
(5)パイプからメッセージを受け取る

 JXTA-Shell理解の最初の関門は、このパイプを使ったメッセージの交換です。

(1)入力パイプの生成

 次のサンプルを見てください。最初のコマンドのmkadvは「告知」を生成するコマンドです。引数の-pは、パイプ用の「告知」を生成せよというオプションです。先に説明したように、イコールの右側のコマンドの実行で生成されたパイプ用の「告知」は、変数pipeadvに代入されます。このシーケンスで作られた「告知」の中身は、先にcatで見ておきましたので、もう一度目を通しておいてください。

 次のmkpipeは、パイプを生成するコマンドです。引数の-iはinputのiで、入力用のパイプ生成を指定するオプションです。重要なのは、mkpipeの2番目の引数です。これは、先に見たパイプ用の「告知」が入っている変数です。このように、パイプを生成するのに「告知」を指定するというのは、「告知」自体が簡単なコマンドで作られているだけに、二度手間のように見えて少し変に感じられるかもしれません。しかし、「Viva! JXTA〜JXTAはネットワークを変える〜」で紹介しているJavaのコードを読んでいただければ、「告知」の果たしている役割の重要性が分かりやすいでしょう。

JXTA>pipeadv = mkadv -p
JXTA>inpipe = mkpipe -i pipeadv


(2)出力パイプの生成

 パイプには両端があります。入力パイプというのは、パイプの入力側の端のことであって、その反対側は出力パイプにならないといけません。Shell -sコマンドで、JXTA-Shellのコンソールをもう1つ作ることができますので、2つ目のコンソールで出力パイプを作って、2つのコンソールの間でパイプを通じたメッセージの伝達ができること確かめてみましょう。

JXTA>Shell -s ← 最初のJXTA-Shellコンソールでこのコマンドを実行すると、2つ目のコンソールが現れる。

 2つ目のコンソールでは、まずmkpipeコマンドに-oオプションを与えて出力用パイプを作っています。ここで一番注意してほしいことは、ここで引数に与えられている変数pipeadvです。この「告知」は、先に入力用のパイプ生成に用いたのと同じものであることに注目してください。コンソールは2つに枝分かれ(fork)しましたが、forkした時点での環境変数の値は、2つのコンソールでは一致しています。ですから、2つのコンソール上の2つのpipeadvは同じものです。

 このことは、同じパイプ「告知」を使って、パイプの入力側の端点と出力側の端点の2つを作ったと考えれば分かりやすいでしょう。もともと、パイプは2つの口を持つ1つのものです。2つのパイプの1つの共通部分を、共通のパイプ「告知」が表現していると考えても同じことです。いずれにせよ、出力側と入力側を結び付けるのはこのパイプ「告知」なのです。

 2つ目のコマンドでは、転送するデータとして、jxtaConfigという名前のファイルを読み込んでmydataという変数に代入しています。これについては、先に説明しましたので説明は繰り返しません。

 以下は、2つ目のコンソールで実行した内容です。

↓2つ目のコンソールでの実行内容
JXTA>opipe = mkpipe -o pipeadv
JXTA>importfile -f jxtaConfig mydata
JXTA>cat mydata
<?xml version="1.0"?>

<ShellDoc>
<Item>
MembershipAuthenticator=NullAuthenticator
MembershipIdentity=somebody
InitialNetPeerGroupAppCode=net.jxta.impl.Shell.bin.Shell.Shell
InitialNetPeerGroupAppCodeURL=http://www.jxta.org/download/jxta.jar
#Default properties. Edit if you want.
</Item>
</ShellDoc>


(3)メッセージを作る

 パイプで送るべきデータがファイルから変数に読み込まれたのなら、さっさとそれを送ればいいように思うかもしれませんが、JXTA-Shellの回り道はまだ続きます。出力パイプからデータを送り出すのにはsendというコマンドがあるのですが、先のopipemydataについてsendを行ってみると次のようなメッセージが出てうまくいきません。どうやら送るべきデータのmydataの型が違うといっているようです。

↓2つ目のコンソールでの実行内容
JXTA>send opipe mydata
send: mydata is not a Message
java.lang.ClassCastException: net.jxta.impl.document.LiteXMLDocument

 実際、sendの第2引数はMessageという型を要求します。JXTA-Shellにはmkmsgというコマンドがあって、このコマンドを実行するとMessage型のインスタンスを1つ返します。シェルのレベルの話なので、「型」とか「インスタンス」というのは変なのですが、JXTA-Shellのシンタックスを理解するには、そのような「解釈」が一番自然なのです。実際、後でも示しますが、これらのJXTA-Shell上のコマンドは「Viva!JXTA〜JXTAはネットワークを変える〜」で紹介したJavaのコードときれいに対応しているのです。

(4)Messageとput/get

 mkmsgコマンドで返されたMessageは、中身が入っていない空のままです。手順としては、すこし面倒な回り道なのですが、空のメッセージに対してあるドキュメントを新しいタグを添付して押し込みます。put message tag documentという構文です。逆に、メッセージからあるタグを付けられたドキュメントを獲得するのにはget message tagという構文のgetコマンドを使います。正確にいえば、documentの部分にはStructuredDocumentと呼ばれる型のドキュメントがくることになります。

 putコマンドは、次のサンプルで示すように、1つのメッセージに繰り返し使えば、複数のタグとドキュメントを持つメッセージを構成することが可能となります。ここで、<ShellDoc> <Item> ....... </Item> </ShellDoc>の型を持つドキュメントが、StructuredDocumentということになっているのが分かります。

↓2つ目のコンソールでの実行内容
JXTA>msg =mkmsg

JXTA>put msg MARU data
JXTA>put msg YAMA data


JXTA>cat msg
Tag: MARU
Body:
<?xml version="1.0"?>


<ShellDoc>
<Item>
MembershipAuthenticator=NullAuthenticator
MembershipIdentity=somebody
InitialNetPeerGroupAppCode=net.jxta.impl.Shell.bin.Shell.Shell
InitialNetPeerGroupAppCodeURL=http://www.jxta.org/download/jxta.jar
#Default properties. Edit if you want.
</Item>
</ShellDoc>
Tag: YAMA
Body:
<?xml version="1.0"?>

<ShellDoc>
<Item>
MembershipAuthenticator=NullAuthenticator
MembershipIdentity=somebody
InitialNetPeerGroupAppCode=net.jxta.impl.Shell.bin.Shell.Shell
InitialNetPeerGroupAppCodeURL=http://www.jxta.org/download/jxta.jar
#Default properties. Edit if you want.
</Item>
</ShellDoc>
JXTA>

 結局のところ、出力用のパイプにデータを送る手順は次のようになります。mkmsgで空のメッセージを獲得し、putでメッセージを構成してsendで送ります。

↓2つ目のコンソールでの実行内容
JXTA>
msg = mkmsg
JXTA>put msg mytag mydata
JXTA>send opipe msg


(5)パイプからメッセージを受け取る

 Shell -sで、新しく開いたコンソールからメッセージの送り出しを行いましたので、このメッセージを受け取る手順を見てみましょう。メッセージを受け取るのは、最初のコンソールで行います。最初のコンソールでは、inpipeという名前で入力用のパイプを作ったところで終わっていると思います。

 次のサンプルを見てください。recvsendと対を成すコマンドで、入力パイプを指定してメッセージを受け取ります。recvで受け取るのは、単純なドキュメントではなくて、タグを付けられたメッセージであることに注意してください。メッセージからのドキュメントの抽出は、タグを指定してgetコマンドで行われます。

↓最初のコンソールでの実行内容
JXTA>msg = recv inpipe
recv has received a message
JXTA>data = get msg mytag
JXTA>cat data
<?xml version="1.0"?>


<ShellDoc>
<Item>
MembershipAuthenticator=NullAuthenticator
MembershipIdentity=somebody
InitialNetPeerGroupAppCode=net.jxta.impl.Shell.bin.Shell.Shell
InitialNetPeerGroupAppCodeURL=http://www.jxta.org/download/jxta.jar
#Default properties. Edit if you want.
</Item>
</ShellDoc>

 結構、クセのあるJXTAシェルですが、慣れましたでしょうか? 今回のJXTAシェルでのパイプを使った通信は、実は「Viva! JXTA 〜JXTAはネットワークを変える〜」で見たJXTAプログラムと深い関係にあります。それが次回のテーマです。

 次回は、JXTAシェルのコマンドのソースを読んで、それらが、JXTAのJava APIのどのようなクラスに対応しているのかを見ていきたいと思います。 それによって、JXTAシェルとJava API双方の理解が増すはずです。

 


Index
  連載のはじめに
  UNIXをグローバルなネットワーク上で実現するのがJXTA
JXTAのシェルがもつ役割
JXTA-Shellを理解するでのポイント
パイプを使った通信と告知


連載記事一覧




Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間