この章では、プロバイダの作成方法について説明します。内容は次のとおりです。
プロバイダ API の詳細は、Javadoc リファレンスページを参照してください。
プロバイダは、データにアクセスするために管理対象オブジェクトと通信するクラスです。プロバイダは、統合と解釈を行うために情報を CIM Object Manager に送ります。CIM Object Manager Repository に存在しないデータの要求を管理アプリケーションから受け取る場合、CIM Object Manager はその要求をプロバイダに送ります。
オブジェクトプロバイダは、CIM Object Manager と同じマシンにインストールされている必要があります。CIM Object Manager は、オブジェクトプロバイダ API を使用して、ローカルマシンにインストールされているプロバイダと通信します。
アプリケーションが CIM Object Manager に動的データを要求した場合、CIM Object Manager はプロバイダインタフェースを使用してその要求をプロバイダに渡します。
プロバイダは、CIM Object Manager からの要求に応答して次の機能を実行します。
プロバイダは扱えるサービスの要求タイプにより分類されます。Sun WBEM SDK では、次の 3 種類のプロバイダをサポートしています。
インスタンス - 指定されたクラス (Solaris パッケージなど) の動的インスタンスを提供します。インスタンスプロバイダは、次に示す操作の 1 つ以上をサポートします。
インスタンス検出
列挙
変更
削除
メソッド - 1 つ以上のクラスのメソッドを提供します。メソッドは、クラスの動作を表現する関数です。メソッドは、プロバイダによって実装される必要があります。
プロバイダ 1 つでメソッドとインスタンスの両方を提供できるため便利です。
ほとんどのプロバイダは、プルプロバイダです。つまり、必要に応じてデータを動的に生成することによりそれ自体のデータを管理します。プルプロバイダは、CIM Object Manager および CIM Repository と最小限の対話しか行いません。プルプロバイダによって管理されるデータは、通常、頻繁に変化します。そのため、プロバイダはアプリケーションから要求が出るたびにデータを動的に生成するか、あるいはローカルキャッシュからデータを取り出す必要があります。
プロバイダは、単体でインスタンスプロバイダ、プロパティプロバイダ、およびメソッドプロバイダの役割を同時に果たすことができます。このためには、関連するすべてのメソッドを適切に登録、実装する必要があります。
プロバイダは、それらの役割に固有のサービスをサポートするプロバイダインタフェースを実装します。インタフェースを実装するには、プロバイダクラスは初めに implements 節でそのインタフェースを宣言し、続いてそのインタフェースのすべての抽象メソッドに対して実装 (本体) を提供する必要があります。次の表では、プロバイダインタフェースについて説明しています。メソッドプロバイダ、インスタンスプロバイダ、およびプロパティプロバイダは、単一の Java クラスファイルに含めることも、あるいは個々のファイルに格納することもできます。
プロバイダは、initialize メソッドを使用して CIM Object Manager と通信できます。initialize メソッドには、CIM Object Manager に対する参照である、 CIMOMhandle 型の引数を指定できます。CIMOMhandle クラスには、プロバイダが CIM Object Manager との間でデータ転送に使用できるメソッドが含まれます。
表 7-1 プロバイダインタフェース
インタフェース |
説明 |
---|---|
CIMProvider |
すべてのプロバイダが実装する基本インタフェース |
InstanceProvider |
インスタンスプロバイダが実装する基本インタフェース。インスタンスプロバイダは、クラスの動的インスタンスを提供する |
MethodProvider |
メソッドプロバイダが実装するインタフェース。メソッドプロバイダは、CIM クラスのすべてのメソッドの実装を提供する |
PropertyProvider |
プロパティプロバイダが実装するインタフェース。プロパティプロバイダは、動的プロパティの検出と更新のために使用される。動的データは、CIM Object Manager Repository には格納されない |
次の表は、Provider パッケージ (com.sun.wbem.provider) に含まれるインスタンスプロバイダインタフェースのメソッドについて説明しています。
これらの各メソッドは引数 op を取ります。op は、指定された CIM クラスまたは CIM インスタンスの CIM オブジェクトパスです。オブジェクトパスには、ネームスペース、クラス名、およびキー (オブジェクトがインスタンスの場合) が含まれます。ネームスペースは、ほかのネームスペース、クラス、インスタンス、および修飾子のデータ型を格納できるディレクトリです。キーは、クラスインスタンスを個別に識別するプロパティです。キープロパティには、キー修飾子が含まれます
たとえば、次のオブジェクトパスは 2 つの部分から構成されます。
¥¥myserver¥root¥cimv2¥Solaris_ComputerSystem:Name=mycomputer: CreationClassName=Solaris_ComputerSystem
¥¥myserver¥root¥cimv2
これは、ホスト myserver 上のデフォルトの CIM ネームスペースです。
Solaris_ComputerSystem:Name=mycomputer: CreationClassName=Solaris_ComputerSystem
これは、ホスト myserver 上のデフォルトネームスペースに存在する特定の Solaris Computer System オブジェクトです。この Solaris コンピュータシステムは、(プロパティ=値) という書式で示される 2 つのキー修飾子値によって個別に識別されます。
Name=mycomputer
CreationClassName=Solaris_ComputerSystem
メソッド |
説明 |
---|---|
enumInstances |
オブジェクトパスに指定されたクラスのすべてのインスタンスを列挙する。ディープ (deep) または シャロー (shallow) 列挙が可能だが、現在 CIM Object Manager はシャロー列挙だけを要求する |
getInstance |
オブジェクトパス (op) に指定されたインスタンスを返す |
setInstance |
オブジェクトパス (op) に指定されたインスタンスを設定する。そのインスタンスが存在しない場合は、追加する必要がある |
deleteInstance |
オブジェクトパス (op) に指定されたインスタンスを削除する |
例 7-1 のコードセグメントは、CIM Object Manager からのインスタンスデータ要求を 1 つ以上の特化されたプロバイダに送る Solaris インスタンスプロバイダクラスを作成します。これらの特化されたプロバイダは、特定の Solaris オブジェクトの動的データの要求に対するサービスを提供します。たとえば、Solaris_Package プロバイダは、Solaris_Package クラスのインスタンスの要求に対応します。
インスタンスプロバイダは、InstanceProvider インタフェースのすべてのメソッドを実装する必要があります。例 7-1 のコードセグメントは、次の 2 つのメソッドだけを示しています。
enumInstances - Solaris パッケージとパッチを列挙する適切なプロバイダを呼び出す。このメソッドは、クラスおよびそのサブクラスのすべてのインスタンスを返すディープ列挙を行う
getInstances - Solaris パッケージとパッチのインスタンスを取得する適切なプロバイダを呼び出す
public class Solaris implements InstanceProvider { /** * 最上位レベルのプロバイダクラスが、CIM Object Manager * からの要求を適切なプロバイダに送る。 */ public void initialize(CIMONHandle, ch) throws CIMException { } public void cleanup() throws CIMException { } /* このクラスは、指定されたクラス内の指定されたオブジェクトの 列挙済みインスタンスが入ったベクトルを返す。オブジェクトが Solaris パッケージの場合、このクラスは Solaris_Package プロバイダを呼び 出し、システム上の Solaris パッケージのリストを返す。 オブジェクトが Solaris パッチの場合、Solaris_Patch プロバイダを 呼び出し、システム上の Solaris パッチのリストを返す。*/ public Vector enumInstances(CIMObjectPath op, CIMClient.DEEP, CIMClass cc) throws CIMException { if (op.getObjectName().equalsIgnoreCase("solaris_package")) { Solaris_Package sp = new Solaris_Package(); return sp.enumerateInstances(op); } if (op.getObjectName().equalsIgnoreCase("solaris_patch")) { Solaris_Patch sp = new Solaris_Patch(); return sp.enumerateInstances(op); } return new Vector(); } /* このクラスは、指定されたクラス内の指定されたオブジェクトの インスタンスを返す。オブジェクトが Solaris パッケージの場合、 このクラスは Solaris_Package プロバイダを呼び出し、指定された Solaris パッケージのデータを返す。オブジェクトが Solaris パッチの場合、Solaris_Patch プロバイダを呼び出し、指定された Solaris パッチのデータを返す。*/ public CIMInstance getInstance(CIMObjectPath op, CIMClass cc) throws CIMException { if (op.getObjectName().equalsIgnoreCase("solaris_package")) { Solaris_Package sp = new Solaris_Package(); return sp.getInstance(op,cc); } if (op.getObjectName().equalsIgnoreCase("solaris_patch")) { Solaris_Patch sp = new Solaris_Patch(); return sp.getInstance(op,cc); } } |
特化された Solaris インスタンスプロバイダは、API を使用してオブジェクトインスタンスの取得と設定を行います。これらのプロバイダは、C 関数を呼び出して Solaris 固有の値 (ホスト名、シリアル番号、リリース、マシン、アーキテクチャ、メーカーなど) を取得するネイティブメソッドの宣言も行います。
例 7-2 のコードセグメントは、例 7-1 で呼び出される solaris_package クラスを示します。このコードセグメントは、getInstance メソッドを実装します。このメソッドは、指定されたクラスの新しいインスタンスを作成し、ネイティブ C 関数 (GetPkgArchitecture() など) が返すプロパティをそれらのインスタンスに割り当てます。
public class Solaris_Package { public CIMInstance getInstance(CIMObjectPath op, CIMClass cc) { String pkgName = ""; for (Enumeration e = op.getKeys().elements(); e.hasMoreElements();) { CIMProperty cp = (CIMProperty)e.nextElement(); if (cp.getName().equalsIgnoreCase("name")) { pkgName = (String) ((CIMValue)(cp.getValue())).getValue(); } } CIMInstance ci = cc.newInstance(); ci.setProperty("Name", new CIMValue(pkgName)); ci.setProperty("TargetOperatingSystem", new CIMValue(new UnsignedInt16(29))); ci.setProperty("Status", new CIMValue(GetPkgStatus(pkgName))); ci.setProperty("Architecture", new CIMValue(GetPkgArchitecture(pkgName))); ci.setProperty("Description", new CIMValue(GetPkgDescription(pkgName))); ci.setProperty("Caption", new CIMValue(GetPkgDescription(pkgName))); ci.setProperty("Manufacturer", new CIMValue(GetPkgVendor(pkgName))); ci.setProperty("Category", new CIMValue(GetPkgCategory(pkgName))); ci.setProperty("Basedir", new CIMValue(GetPkgBasedir(pkgName))); return ci; } native String GetPkgDescription(String pkgName); native String GetPkgArchitecture(String pkgName); native String GetPkgVersion(String pkgName); native String GetPkgVendor(String pkgName); native String GetPkgBasedir(String pkgName); native String GetPkgCategory(String pkgName); native String GetPkgStatus(String pkgName); static { System.loadLibrary("NativeUnix"); } } |
次の表は、プロパティプロバイダインタフェースのメソッドについて説明しています。
表 7-3 PropertyProvider インタフェースメソッド
メソッド |
説明 |
---|---|
getPropertyValue |
指定されたインスタンスのプロパティの値を返す |
setPropertyValue |
指定されたインスタンスのプロパティの値を設定する |
例 7-3 のコードセグメントは、例 7-5 で登録されるプロパティプロバイダ (fruit_prop_provider) クラスを作成します。fruit_prop_provider は、PropertyProvider インタフェースを実装します。
このサンプルプロパティプロバイダは、指定されたクラスのプロパティ値、親クラス、およびプロパティ名を返す getPropertyValue メソッドを示しています。CIM プロパティは、その名前と親クラスによって定義されます。複数のプロパティで同じ名前を使用できますが、親クラスはプロパティを個別に識別します。
fruit_prop_provider implements PropertyProvider { public CIMValue getPropertyValue(CIMObjectpath op, string originclass, string PropertyName){ if (PropertyName.euqals("a") return new CIMValue("fooa") else return new CIMValue("foob"); } ... } |
MethodProvider メソッドには、次の引数を指定できます。
op - メソッドが呼び出されるインスタンスのオブジェクトパス
originClass - クラス階層内でこのメソッドの定義が初めに行われたクラスの名前。CIM プロパティは、親クラスから継承される CIM クラスの属性です。CIM プロパティは、ネームスペース内でその名前と親クラスによって個別に識別されます。たとえば、speed という 2 つのプロパティが存在する場合、それらはそれぞれの親クラス DiskDrive と CPU で区別されます。
inParams - メソッドの入力パラメータである CIMValues のベクトル
CIMValue - メソッドの戻り値。メソッドに戻り値がない場合、メソッドは NULL を返す必要があります。CIM Value は、CIM のデータ型と CIM プロパティの値を格納します。CIM のデータ型 (CIM Specification で定義されている) は、組み込まれているデータ型に限定されます。次の表は、CIM の各データ型に対応する WBEM のデータ型の名前を示しています。
表 7-4 Sun WBEM SDK と CIM のデータ型名
CIM のデータ型 |
WBEM のデータ型 |
説明 |
---|---|---|
uint8 |
UnsignedInt8 |
符号なし 8 ビット整数 |
sint8 |
Byte |
符号付き 8 ビット整数 |
uint16 |
UnsignedInt16 |
符号なし 16 ビット整数 |
sint16 |
Short |
符号付き 16 ビット整数 |
uint32 |
UnsignedInt32 |
符号なし 32 ビット整数 |
sint32 |
Integer |
符号付き 32 ビット整数 |
uint64 |
UnsignedInt64 |
符号なし 64 ビット整数 |
sint64 |
Long |
符号付き 64 ビット整数 |
string |
String |
UCS-2 文字列 |
boolean |
Boolean |
ブール型 |
real32 |
Float |
IEEE 4 バイト浮動小数点 |
real64 |
Double |
IEEE 8 バイト浮動小数点 |
datetime |
CIMDateTime |
日時を含む文字列 |
classname ref |
CIMObjectPath |
厳密に型定義された参照 |
char16 |
Character |
16 ビット UCS-2 文字 |
次の表では、MethodProvider インタフェースのメソッドについて説明します。
表 7-5 MethodProvider インタフェースメソッド
メソッド |
説明 |
---|---|
invokeMethod |
CIM Object Manager は、指定されたメソッドが呼び出される場合にこのメソッドを呼び出す |
例 7-4 のコードセグメントは、CIM Object Manager からのメソッド実行要求を 1 つ以上の特化されたプロバイダに送る Solaris プロバイダクラスを作成します。これらの特化されたプロバイダは、特定の Solaris オブジェクトの動的データの要求に対するサービスを行います。たとえば、Solaris_Package プロバイダは、Solaris_Package クラスのメソッドを実行する要求に対応します。
この例のメソッドプロバイダは、適切なプロバイダを呼び出して次に示す処理の 1 つを実行する単一のメソッド invokeMethod を実装します。
Solaris システムをリブートする
Solaris システムをリブートまたは停止する
Solaris シリアルポートを削除する
public class Solaris implements MethodProvider { public void initialize(CIMONHandle, ch) throws CIMException { } public void cleanup() throws CIMException { } public CIMValue invokeMethod(CIMObjectPath op, String methodName, Vector inParams, Vector outParams) throws CIMException { if (op.getObjectName().equalsIgnoreCase("solaris_computersystem")) { Solaris_ComputerSystem sp = new Solaris_ComputerSystem(); if (methodName.equalsIgnoreCase("reboot")) { return new CIMValue (sp.Reboot()); } } if (op.getObjectName().equalsIgnoreCase("solaris_operatingsystem")) { Solaris_OperatingSystem sos = new Solaris_OperatingSystem(); if (methodName.equalsIgnoreCase("reboot")) { return new CIMValue (sos.Reboot()); } if (methodName.equalsIgnoreCase("shutdown")) { return new CIMValue (sos.Shutdown()); } } if (op.getObjectName().equalsIgnoreCase("solaris_serialport")) { Solaris_SerialPort ser = new Solaris_SerialPort(); if (methodName.equalsIgnoreCase("disableportservice")) { return new CIMValue (ser.DeletePort(op)); } } return null; } } |
プロバイダは、管理対象デバイスに関する情報の取得と設定を行います。ネイティブプロバイダは、管理対象デバイスで動作するように作成されるマシン固有のプログラムです。たとえば、Solaris システム上のデータにアクセスするプロバイダは、通常、C 関数を組み込んで Solaris システムの照会を行います。ネイティブプロバイダは、一般に次のような理由で作成されます。
効率 - 速度が重視されるコードの一部を低レベルのプログラミング言語 (アセンブラなど) で実装し、その後 Java アプリケーションでそれらの機能を呼び出すと便利な場合がある
プラットフォーム固有の機能にアクセスする必要がある - 標準の Java クラスライブラリが、アプリケーションに必要なプラットフォームに固有の機能をサポートしていない場合がある
従来のコード - Java 以外のプログラミング言語で作成された従来のコードを Java プロバイダと共に継続して使用したい場合がある
JDK の一部である Java Native Interface (JNI) は、Java のネイティブプログラミングインタフェースです。JNI を使用してプログラムを作成すると、ほとんどのプラットフォームで完全に移植可能です。Java Virtual Machine (VM) で動作する Java コードで JNI を使用すると、そのコードは C、C++、アセンブラのようなほかの言語で作成されたアプリケーションおよびライブラリで実行できます。
Java プログラムの作成、および Java プログラムとネイティブメソッドの統合についての詳細は、 Java Web サイト http://www.javasoft.com/docs/books/tutorial/native1.1/index.html を参照してください。
プロバイダを作成したあと、プロバイダクラスファイルと共有ライブラリファイルの場所を指定する必要があります。
次に示す方法の 1 つを使用して、共有ライブラリファイルの場所を指定します。
LD_LIBRARY_PATH 環境変数を、共有ライブラリファイルのある場所に設定します。C シェルを使用している場合の入力例を次に示します。
% setenv LD_LIBRARY_PATH /wbem/provider/ |
Borne シェルを使用している場合の入力例を次に示します。
$ LD_LIBRARY_PATH=/wbem/provider/ $ export LD_LIBRARY_PATH |
共有ライブラリファイルを、LD_LIBRARY_PATH 環境変数によって指定されているディレクトリにコピーします。WBEM のインストールを行うと、この環境変数は /install_dir/opt/SUNWconn/wbem/lib に設定されます。次に入力例を示します。
% cp libnative.so /install_dir/opt/SUNWconn/wbem/lib % cp native.c /install_dir/opt/SUNWconn/wbem/lib |
プロバイダクラスファイルを、/install_dir/opt/SUNWconn/wbem/lib に移動します。
CLASSPATH 変数を、プロバイダクラスファイルが入っているディレクトリに設定します。
/install_dir/opt/SUNWconn/wbem/bin/com/mycomp/wbem/provider/
に置く場合は、C シェルでは CLASSPATH 変数を次のように設定します。
% setenv CLASSPATH /install_dir/opt/SUNWconn/wbem/bin/com/mycomp/wbem/provider/ |
Borne シェルでは次の構文を使用します。
$ CLASSPATH=/install_dir/opt/SUNWconn/wbem/bin/com/mycomp/wbem/provider/ $ export CLASSPATH |
CIM Object Manager が動作していることを確認します。
インストールを行うと CIM Object Manager は自動的に起動します。CIM Object Manager が動作していない場合は、「CIM Object Manager の再起動」を参照してください。
サポートするデータと処理、およびそれらの物理的な実装についての情報を公開するため、CIM Object Manager にプロバイダを登録します。CIM Object Manager は、この情報を使用してプロバイダのロードと初期化、および特定のクライアント要求に適切なプロバイダを決定します。プロバイダはすべて同じ方法で登録します。登録時に CIM Object Manager、プロバイダとも動作している必要はありません。
CIM クラスを定義する MOF ファイルを作成します。
そのクラスに、provider 修飾子を割り当てます。provider 修飾子には、プロバイダ名を割り当てます。
プロバイダ名により、そのクラスのプロバイダとしての役目をする Java クラスが識別されます。クラス名は、完全に指定する必要があります。次に例を示します。
プロバイダについては、プロバイダ名が固有になるように、Java クラスおよびパッケージ命名規則に従うことを推奨します。固有のパッケージ名の接頭辞は小文字の ASCII 文字で、トップレベルのドメイン名にする必要があります。現在は、com、edu、gov、mil、net、org、または、ISO 標準 3166、1981 で指定されている国名を識別する 2 文字コードなどです。
パッケージ名のあとの名前は、組織内部の命名規則によって異なります。たとえば、あるディレクトリ名のコンポーネントは、部名、課名、プロジェクト名、マシン名、あるいはログイン名などになります (例 : com.mycompany.wbem.myprovider)。
[Provider("com.kailee.wbem.providers.provider_name")] Class_name { ... };
MOF ファイルをコンパイルします。次に例を示します。
mofcomp class_name
例 7-5 のサンプル MOF ファイルは、インスタンスプロバイダ (fruit_class_provider)、プロパティプロバイダ (fruit_prop_provider)、およびメソッドプロバイダ (fruit_method_provider) を登録する Fruit というクラスを作成します。
// fruit_class_provider を Fruit クラスのプロバイダとして登録 [Provider("com.food.fruitprovider.fruit_class_provider")] Fruit { // fruit_prop_provider は、プロパティ a のプロバイダである。 [Provider("com.food.fruitprovider.fruit_class_provider")] - string a; // fruit_prop_provider は、プロパティ b のプロバイダでもある。 [Provider("com.food.fruitprovider.fruit_class_provider")] string b; // fruit_method_provider は、メソッド b のプロバイダである。 [Provider("com.food.fruitprovider.fruit_class_provider")] int b(); }; |
プロバイダクラスは、CIM Object Manager とプロバイダの動作中に変更できます。しかし、加えた変更を有効にするためには、CIM Object Manager を停止して再起動する必要があります。
プロバイダソースファイルを編集します。
プロバイダソースファイルをコンパイルします。次に例を示します。
% javac MyProvider.java |
システムプロンプトで次のコマンドを入力し、システム上でスーパーユーザーになります。
% su |
プロンプトに対し、スーパーユーザーのパスワードを入力します。
次のコマンドを入力して、init.wbem コマンドがある位置にディレクトリを変更します。
# cd /etc/init.d/ |
次のコマンドを入力して、CIM Object Manager を停止します。
# ./init.wbem stop |
次のコマンドを入力して、CIM Object Manager を再起動します。
# ./init.wbem start |
第 8 章「Sun WBEM SDK サンプルの使用」で、プロバイダの例の設定と実行方法について説明しています。