第1回 JXTA ShellからJXTAを知る


UNIXをグローバルなネットワーク上で実現するのがJXTA

 筆者はUNIXで育った世代です。それは、いまでは、もう若くはないということの告白でしかないかもしれません。もう20年近く前の話になるのですが、入出力デバイスを含めて、すべてのリソースをファイルとして管理しようという思想、入出力の標準化とリダイレクトによって複数のプロセスを結合するアイデア、さまざまなプロセスを呼び出し結合するユーザーインターフェイスとしてのシェルの提供など、いまではあまり新しいものには感じられないかもしれませんが、まだ、大型機のTSSやラインプリンタが一般的な時代、筆者はそのスマートさに熱狂しました。

「ファイル・システム」は、例えていえば、自然環境での「森林」のようなものさ。「プロセス」は、その森に住む「生き物」だと思えばいい。僕らは、ハーメルンの笛吹きさながら、この生き物たちを、自由に、協調させることができるんだ。

 JXTAのプロジェクトの話を聞き、また、そのソースを読んで、筆者はこうした興奮をあらためて思い出しました。二十数年前に、UNIXが単一のマシンのリソースの内部で行おうとしたことを、JXTAはグローバルなネットワークの上で実現しようとしているのだと筆者は考えています。

 ファイルの森は、地球を覆い尽くすネットワークの森に変わりました。森の生き物は単なる「プロセス」から、ネットワークを構成するノード、「ピア」に変わっています。しかし、この広大なリソース空間で共有可能なものは共有しうるシステムへの、また、このグローバルなものに拡大した世界で、ピア相互のコミュニケーションを容易に保証しうるシステムへの志向が高まるのは当然のことに思われます。

JXTAのシェルがもつ役割

 JXTAにはシェル「JXTA-Shell」が提供されています。今回は、JXTAの特徴の1つでもある、このシェルを取り上げてみたいと思います。

 JXTAのシェルはJXTAアプリケーションの1つです。決して、JXTAのシステムの中枢部を占めているわけではありません。その意味では、無数にありうるJXTAアプリケーションの中の1つにすぎないのですが、ちょっと特別の意味を持っているアプリケーションです。

 このあたりは、UNIXのカーネルとUNIXシェルの関係とよく似ています。UNIXのカーネルは「ファイル・システム」「プロセス」「プロセスの入出力」など、さまざまなリソースを管理しています。UNIXのシェルは、こうしたリソースにユーザーが自由にアクセスするのを助けることを目的とする特別のアプリケーションです。シェルは、カーネル管理下のリソースとユーザーの間にインタラクティブなインターフェイスを提供します。先の例えでいえば「ハーメルンの笛吹き男」の「魔法の笛」にあたる便利な道具がシェルです。

 JXTAのシェルも、JXTAがネットワーク上で管理している「ピア」「ピアグループ」「パイプ」といったJXTAのリソースに対する、インタラクティブなインターフェイスを提供します。

 ピアとピアの相互のコミュニケーションを保証するために、グローバルなネットワーク上にまで拡大された「パイプ」という考えは、とても面白いものです。また、セキュリティを保証しながら広大なリソースの共有をどのように図るかという課題はとても挑戦的なものです。こうした仕事をコントロールするための、使いやすいインターフェイスとしてのシェルをどう構築するのかというのも、とても大事な取り組みです。

JXTA-Shellを理解するうえでのポイント

 とはいうものの、実際に提供されているJXTA-Shellは、まだまだ機能が限られていて成熟していません。現実のそれは、理想的に動いてくれているわけではありません。僕は、多少辛い評価をしています。もちろん、それは現在進行形の日々姿を変えていくプロジェクトの産物ですので、あまり、固定的な決めつけは良くないでしょう。また、UNIXにもB-Shell、C-Shell、K-Shell……とたくさんのシェルがあるように、JXTAにも、複数のシェルが提供されるようになるのだと思います。

 まずは、JXTA-Shellが機能として持っているものを正確に理解することから始めたいと思います。それには、JXTA-Shellの次のような項目の理解が必要です。

  1. 変数への値のアサイン
  2. パイプを使った通信と告知
  3. shareとsearch ――告知の公開と獲得
  4. ピアグループの生成と告知
  5. ピアグループへの参加と移動・離脱

 このリストを見ても、筆者の記事「Viva! JXTA 〜JXTAはネットワークを変える」で紹介した「告知(Advertisement)」の役割の理解が重要なことが分かってもらえると思います。今回は、「2.パイプを使った通信と告知」まで説明します。

 「3.shareとsearch――告知の公開と獲得」からはJXTA-Shellのコマンドの使い方を学ぶだけでなく、JXTA-ShellコマンドとJXTA APIとの密接な関係を示しながら説明を進めていきます。

変数への値のアサイン

 JXTA-Shellには、かなりクセがあります。JXTA-Shellを使うには、このクセをよく知っておく必要があります。UNIXのシェルと大体同じ働きのパイプやリダイレクトの説明は後にして、JXTA-Shellの特徴的な変数への値のアサインを見ておくことにしましょう。

 ここでは、次のことについて説明します。

(1)イコールの左側と右側の扱い
(2)setenvの使い方
(3)importfileとexportfile
(4)自動的に生成される変数たち


(1)イコールの左側と右側の扱い

 シェル変数への値のアサインは、UNIXのB-Shell(name=value)、C-Shell(set name=value)でもシンタックスが異なっていますね。JXTA-Shellの代入文は、そのどれとも異なっています。次のサンプルのpipeadv = mkadv -pを見てください。イコールの左側は、もちろんシェル変数の名前ですが、右側が少し変わっています。右側は、実はmkadv -p というコマンドなのです。この代入文は、右側のコマンドを実行してその結果を左の変数に代入するという働きをします。UNIXのシェルでいえばpipeadv = `mkadv -p`のように、バッククオートを使う場合と同じですね。でも、JXTA-Shellでは、イコールの右側の文字列は自動的にコマンド文字列として解釈され、実行されることになります。

 代入されたシェル変数の値は、catコマンドで表示することができます。これも、UNIXのシェルでしたら、変数の値の表示には、echoを使うところですね。このサンプルでは、mkadv -pコマンドは「告知(advertisement)」と呼ばれるXML文字列を生成することを示しています。

JXTA>pipeadv = mkadv -p
JXTA>cat pipeadv
<?xml version="1.0"?>
<!DOCTYPE jxta:PipeAdvertisement>

<jxta:PipeAdvertisement>
<id>
jxta://59616261646162614A757874614D5047EC183B29B689448E82CC9C296C33
DFE5000000000000000000000000000000000000000000000000000000000000401
</id>
</jxta:PipeAdvertisement>


(2)setenvの使い方

 JXTA-Shellでは、変数への値の設定にはsetenvコマンドを使うこともできます。しかし、このコマンドもUNIXのシェルとはちょっと違っています。UNIXでは、setenv a bは環境変数aに値bを直接設定するのですが、JXTA-Shellでは、bは変数の名前として解釈され、その値の評価が行われ、その結果がaに代入されます。ですからsetenvの2番目の引数は、1番目の引数に先立って存在しなければなりません。その意味では、すでにある変数bの内容を、新しく変数aにコピーする、コピー・コマンドの一種と考えてもいいかもしれません。ただし、コピー・コマンドとは変数の並び方が逆になっていますので注意してください。

JXTA>setenv a b
setenv: cannot access b ← bという変数が存在しないので値にアクセスできない。

JXTA>setenv a pipeadv ← 先に代入した変数pipeadvの値を、変数aに設定する。
JXTA>cat a  ← catでaの値を確認してみる。pipeadvと同じことが分かる。
<?xml version="1.0"?>


<!DOCTYPE jxta:PipeAdvertisement>


<jxta:PipeAdvertisement>
<id>
jxta://59616261646162614A757874614D5047EC183B29B689448E82CC9C296C
33DFE500000000000000000000000000000000000000000000000000000000000
00401
</id>
</jxta:PipeAdvertisement>


(3)importfileとexportfile

 JXTA-Shellでは、を使った代入文でもsetenvでも、シェル変数にコマンドラインから好きな文字列を設定できるわけではないことが分かります。ただ、次のようにimportfileコマンドを利用すると、JXTA-Shellの外部のファイルから指定した名前の変数にそのファイルの中身を設定することができます。次のサンプルは、カレント・ディレクトリのjxtaConfigファイルの中身を変数mydataに設定しています。正確にいえば、変数に設定されている文字列は、ファイルの中身そのものではなく、いくつかのタグが付けられていることがcat mydataを実行して内容を見れば分かります。こうした構造はStructuredDocumentと呼ばれています。

 こうしてJXTA-Shellの内部に読み込まれたStructuredDocumentは、exportfileコマンドを使ってJXTA-Shellの外部にファイルとして書き出すことができます。ここでは、先に内部に取り込んで変数mydataに設定した内容をファイルc:\backup\jxtaConfig.txtに書き出しています。

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>

JXTA>exportfile -f c:\backup\jxtaConfig.txt mydata


(4)自動的に生成される変数たち

 シェル変数への値の設定で興味深いのは、JXTA-Shellでは、あるコマンドの実行によって自動的にシェル変数が生成され、値が設定されることです。envコマンドで現在のシェル変数を知ることができます。次のサンプルでは、JXTA-Shellを立ち上げた時点で、envでどのような変数が定義されているのかを見ています。いくつかのコマンドを実行した後で、どのような変数が生成されたかを確認してください。

 この例では、コマンドmkmsg、mkadv -p、mkmsgで、変数env1、env2、env3が生成され、コマンドpeersの実行でpeer0とpeer1の2つの変数が生成されたことが分かると思います。ここでは例を示しませんが、コマンドgroupsでは、変数group0、group1、goups2……が、shareコマンドでは、変数adv0、adv1、adv2……が生成されます。このように、自動的に生成される変数たちには、名前の後ろに出現順に数字が付け加えられています。

JXTA>env ↓JXTA-Shellのシェル変数の初期状態

stdout = Default OutputPipe (class net.jxta.impl.Shell.ShellOutputPipe)
SHELL = Root Shell (class net.jxta.impl.Shell.bin.Shell.Shell)
consout = Default Console OutputPipe (class net.jxta.impl.Shell.ShellOutputPipe)
History = History (class net.jxta.impl.Shell.bin.history.HistoryQueue)
stdgroup = Default Group (class net.jxta.impl.peergroup.StdPeerGroup)
stdin = Default InputPipe (class net.jxta.impl.Shell.ShellInputPipe)
consin = Default Console InputPipe (class net.jxta.impl.Shell.ShellInputPipe)
Shell = Root Shell (class net.jxta.impl.Shell.bin.Shell.Shell)

↓いくつかのコマンドを実行してみる
JXTA>mkmsg
JXTA>mkadv -p
JXTA>mkmsg
JXTA>peers
peer0: name = pcg-c1
peer1: name = Fujio

JXTA>env ↓上記のコマンドの実行によって新しい変数が追加されている peer0,peer1,env0,env1,env2....


peer1 = stored local peer advertisement (class net.jxta.impl.protocol.PeerGroupAdv)
peer0 = stored local peer advertisement (class net.jxta.impl.protocol.PeerGroupAdv)
stdin = Default InputPipe (class net.jxta.impl.Shell.ShellInputPipe)
SHELL = Root Shell (class net.jxta.impl.Shell.bin.Shell.Shell)
env3 = Message (class net.jxta.impl.endpoint.MessageImpl)
History = History (class net.jxta.impl.Shell.bin.history.HistoryQueue)
env2 = PipeService Advertisement (class net.jxta.impl.protocol.PipeAdv)
Shell = Root Shell (class net.jxta.impl.Shell.bin.Shell.Shell)
env1 = Message (class net.jxta.impl.endpoint.MessageImpl)
stdout = Default OutputPipe (class net.jxta.impl.Shell.ShellOutputPipe)
consout = Default Console OutputPipe (class net.jxta.impl.Shell.ShellOutputPipe)
consin = Default Console InputPipe (class net.jxta.impl.Shell.ShellInputPipe)
stdgroup = Default Group (class net.jxta.impl.peergroup.StdPeerGroup)


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


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


連載記事一覧




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

注目のテーマ

Java Agile 記事ランキング

本日 月間