JMishelle 設計書
JMichelle system design
Copyright(C) 2000 Yoshinori WATANABE
1.要件定義
2.システム設計
2-1.概要
2-2.コマンド解析、実行
1.要件定義
図.1 ユースケース図
Fig.1 Usecase Diagram
ミッシェルはおよそ上記の機能を持っています。
青い箇所(太線)はすでに完成している機能、黄色い箇所(細線)は開発中の
機能、灰色の箇所(点線)はまだ開発に未着手のところです。
通常のシェルの機能をサポートしていますが、(あるいは将来サポートしますが、)
それ以外の機能、例えばURI統合など、独自の機能もサポートしていきます。
このあと、個々の機能についての説明が続く・・・。
でも、書かなくてもわかるかな。
2.システム設計
2-1.概要
図.2 クラス図(概要)
Fig.2 Class Diagram(over view)
JMichelleの主なクラスについてクラス図を示します。
JMichelleがエントリとなるクラスです。
init()のあとにprocess()を行い、最後にexit()を行う簡単な構造です。
process()の中で、MdShellEngineを生成し、initで生成したMdShellEnvを渡して
MdShellEngineのprocess()を呼んでいます。
このprocess()の中で、プロンプトを表示し、キーボードからの入力を行い、
コマンドを実行し、これらの一連の動作を繰り返しています。
ここがシェルのメインの処理を行っているところといえるでしょう。
1つのコマンドを処理しているのが、processCommand()で、この中で、
dirやcd、pwdなどの内部コマンドや、ネイティブの外部コマンドを
実行しています。
それらのコマンドを管理しているのが、MdShellCmdListで、これは、
MdShellCommandInterfaceインターフェースを持つクラスの集合を管理
しています。
つまり、すべてのコマンドはこのMdShellCommandInterfaceインターフェース
を持つことになります。
MdShellCommandInterfaceには以下のメソッドが定義されています。
public interface MdShellCommandInterface {
public String getCommand();
public String getHelpString();
public void registerImplementedCommand(Vector vecList);
public boolean isThisCommand(MdShellEnv shellenv,String strCommand);
public void processCommand(MdShellEnv shellenv);
public boolean isHiddenCommand();
}
getCommand()はコマンド名を返します。
dirコマンドの場合、"dir"にあたります。
getHelpString()はHelpコマンド時に表示される文字列です。
dirコマンドの場合、"dir : ディレクトリ一覧
, lsはエイリアス"にあたります。
processCommand()が実際にコマンドを実行するメソッドです。
ここで、目的の処理を行えばよいのです。
引数にMdShellEnvが渡されますが、それからgetOut()で取得できる標準出力に対して出力すれば
画面に処理の結果を表示させることができます。
また必要ならば、ユーザーに問い合わせて標準入力から取り入れることができます。
registerImplementedCommand()はMdShellCmdListに自分自身のコマンドを登録します。
・・・
うーん、registerImplementedCommand(Vector vecList)と、
isThisCommand(MdShellEnv shellenv,String strCommand)について、
チョット考えさせて下さい。
dirのlsや、helpの?など、aliasは個々のコマンドで定義すべきでは
ないと思うのです。
aliasを組み込めば、この2つは変わってくると思うのですが・・・。
あれれっ、でも、MdShellCmdAlias というクラスもありますね。
むむむ、混乱。
それと、isHiddenCommand()は最近追加したメソッドのようですが、
どういうのを目的に作られたのでしょうか?
2-2.コマンド解析、実行
図.3 コマンドの解析、実行
Fig.3 parsing command, and execute
入力されたコマンドは上記の手順で実行されます。この処理は、MdShellEngineクラス内で
処理されます。
まず、入力されたコマンドは、ShellParserクラスに渡されます。
そこで、コマンドヒストリ「!!」「!10」やエイリアスの置き換えが行われます。
また、補完機能もあります。
正常に置換された場合は新たにヒストリの中に組み込まれます。
エイリアスとヒストリの順番や関係が良くわかっていません。
多分、別のクラスに分けたほうがよいと思いますが、どっちを先に処理するのでしょう?
次に、置換されたコマンドはRedirectParserクラスに渡されます。
そこで、「<」「>」「|」や「>&」などのトークンを元に、複数のコマンドと
入出力ファイルに分解されます。また、出力ファイルを追加書き込みするか、
新規書き込みにするかの指定も解析されます。
この構文もシェルにより若干ことなるようです。
その場合は、このクラスを書き換えることになります。
また、他のシェルには上記コマンド以外に順次処理「;」や「<<」もあるようです。
分割されたコマンドはコマンドの数だけ、環境が用意されます。
環境には標準ストリームのin,out,errがありますが、個々のコマンドに応じ、
入力ファイルや出力ファイル、パイプなどで適切なストリームに置き換えます。
そして同時にコマンドを実行させます。
内部コマンドかネイティブコマンドかの判断などは、ProcessCommanderクラス以下で
行われます。
2000-10-12現在、上記の設計を元に開発していますが、まだ完成していません。
リダイレクトのうち、out,errは成功しているが、inは成功していない。(Ctrl+Z?)
パイプが動かない。
コマンド解析部の変更が不十分。
まず、MdShellCommandInterfaceを変更し、String[] argsの引数を追加。
そして、それから継承しているすべてのコマンドをそれに合わせる。
内部コマンド、ネィティブコマンドを呼んでいるところで、引数を分割して
呼ぶ。最後に、Envの中の不要になる関数を破棄。
ヒストリの機能はまだ別クラスになっていない。
エイリアスの仕組みがまだない。MdShellCmdAliasは偽者。
unixユーザにとって、上記のクラス名が妥当なのかどうなのか不安。
図.4 コマンドと環境と入出力ファイル
Fig.4 commands, enveronments and input/output file
コマンドと環境、入出力ファイルについて、もう少し複雑な入力コマンドを使って、詳しく説明します。
Engineは実行モジュールであるgrepとsortのスレッドを作成します。
その際、Engineが保持しているEnvを複製し、inとoutにそれぞれ適切なリダイレクト元/先とパイプをつなげます。
準備ができたらすべてのスレッドを実行させます。ファイルの入力から処理が始まり、次々と処理が始まります。
入力が終わると順にスレッドが終了し、最後のスレッドが終了すれば、全体の処理は完了です。