第8章
この章では、さまざまなソースからWebサービスを生成する「Webサービスウィザード」の使用について、基本手順と一般的なシナリオを説明します。トピックは次のとおりです。
プログラムからWebサービスにアクセスするためにウィザードを使用する手順とシナリオについては、を参照してください。
Novell exteNd Director 開発環境のWebサービスウィザードを使用すると、「Javaリモートオブジェクト」(RMIを使用)として実装される「標準の(SOAPベースの) Webサービス」を開発することができます。ウィザードでは、JAX-RPC (XMLベースRPCのJava API)およびNovell exteNd WebサービスSDK (Novell exteNdに含まれているJAX-RPX実装)に基づいて、Javaソースファイルを生成します。JAZ-RPCは、Webサービスサポートを提供するJ2EE仕様です。
生成されたファイルには、WebサービスへのアクセスおよびHTTP SOAP要求からのメソッドを処理する「サーブレット」が含まれています。生成されたファイルは、そのまま使用したり、必要に応じて変更したりできます。このJava指向の方法には、低レベルのSOAP APIをコーディングする代わりに、熟知しているRMIおよびJ2EEの技術を使用してWebサービスを処理できるという利点があります。
Webサービスの概念、標準、および技術の紹介については、を参照してください。
ウィザードに関する詳細なマニュアルについては、を参照してください。
完全な開発プロセスには、次の作業が含まれます。
Webサービスウィザードの使用を準備するには、次の操作を行います。
exteNd Director 開発環境で「WARプロジェクト」をセットアップします。
生成する各Webサービスに対して、ウィザードは、(HTTP SOAP要求から)そのWebサービスへのアクセスを処理する「サーブレット」を作成します。結果として、Webサービスが実行されるJ2EEサーバへの展開用にWebサービス(WARにつき1つまたは複数)をパッケージ化するために、WARが必要です。
その他の方法として、WARに「JARサブプロジェクト」をセットアップし、このJARを使用して、Webサービスに使用するサーブレットおよびその他のクラスを含めることもできます。 いずれの場合でも、「サーブレットマッピング」は、WARの展開記述子(web.xml)に含まれます。
WSDLファイルからWebサービスを生成する場合、JARサブオブジェクトを使用する方法は、Webサービスウィザードでは現在のところサポートされていません。この場合は、WARプロジェクトのみがサポートされています。
ファイル |
詳細 |
---|---|
Webサービスが生成される元のソースファイル、クラス、またはアーカイブ |
Webサービスは、次のいずれかから生成できます。 いずれを指定した場合でも、少なくとも、生成されたWebサービスで公開するメソッドが宣言されている必要があります。 Javaファイルのコンパイル Javaファイルを指定した場合は、Webサービスウィザードを開始する前に、プロジェクトでこれらのファイルをコンパイルする必要があります(ウィザードはコンパイルされたクラスから機能するため)。 WSDLバインドの編集 WSDLファイルを指定した場合は、サービス定義のSOAPアドレスによって正しいバインドURLが指定されるように、必要に応じてファイルを修正します。Webサービスウィザードでは、Webサービスに対して生成するファイルでこのURLを使用します。 オーバーロードしたメソッドがないこと オーバーロードしたメソッド名は、Webサービスインタフェースでは使用できません(WSDL 1.2の時点)。 次のとおりにします。 |
WebサービスSDKで必要な次のアーカイブ |
これらのJARは、Novell exteNdのtools\compilelibディレクトリにあります。J2EEサーバの設定に応じて、次のいずれかの操作を行います。
|
生成および編集の後でWebサービスクラスをコンパイルできるように、プロジェクトの「クラスパス」を編集します。 次のアーカイブを含める必要があります。
wssdk.jar およびStep 2にリストされているサポートJAR (必要な場合)
アプリケーション固有のエントリ(セッションBean Webサービスに対して指定したEJBクライアントJARファイルなど)
WARプロジェクトをセットアップしたら、Webサービスウィザードを使用する準備が整ったことになります。 ウィザードでは、一度に1つのWebサービスが作成されるため、複数のサービスを開発する場合は、ウィザードを複数回使用する必要があります。
ウィザードを起動するたびに、作成するWebサービスの種類を入力します。続いて、ウィザードによって、Webサービスを構成する1セットのソースファイルが生成されます。 次に、このプロセスの概要を示します。
[ファイル]>[新規作成]>[ファイル]の順に選択して[新規ファイル]ダイアログボックスを表示し、[Webサービス]タブに移動します。
次のいずれかの操作を実行して、Webサービスウィザードを起動します。
Webサービスの生成元 |
選択する項目 |
---|---|
次のいずれか |
新規Webサービス |
WSDLファイル |
既存のWebサービス 名前から分かるように、この項目は、主に、(WSDLファイルに基づいて)展開済みのWebサービスにアクセスする「Webサービスコンシューマ」を生成するために使用されます。ただし、WSDLファイルを青写真として読み込み、一致する「Webサービス」自体を生成するために使用することもできます。 |
ウィザードによって、「プロジェクトの場所」についての情報を入力するようメッセージが表示されたら、次の項目を指定します。
生成されたWebサービスファイルが含まれるようにセットアップした「WARプロジェクトまたはJARプロジェクト」(WSDLファイルから生成する場合は、ウィザードによってここでWARプロジェクトを指定するよう要求されます)。
このプロジェクトのターゲットの「ディレクトリおよびパッケージ」(Javaクラスから生成する場合、これらの設定の一部は入力する必要がありません。ウィザードによって自動的に処理されます)。
生成されたWebサービスファイルが含まれるようにJARプロジェクトを指定した場合、ウィザードによって、WebサービスのサーブレットをマップするWARプロジェクトも指定するようメッセージが表示されます。
ウィザードによってメッセージが表示されたら、Webサービスの生成元である「クラスまたはWSDLファイル」を選択します。
その後、選択した項目に基づいて追加の情報を入力するようメッセージが表示されます。
選択項目 |
ウィザードによって指定するよう求められる内容 |
---|---|
JavaBeanまたはその他のJavaクラス |
|
EJBセッションBeanのホームインタフェース |
|
EJBセッションBeanのリモートインタフェースまたはSessionBeanクラス自体 |
|
Javaリモートインタフェース |
|
WSDLファイル |
「クラス生成およびSOAPオプション」を入力するようメッセージが表示されたら、Webサービスに対して生成する1セットのソースファイルを選択して設定する必要があります。
最も重要な選択は、「スケルトン」を「結合ベース」になるように生成するかどうかです。この答えは、Webサービスの実装が従うアーキテクチャモデルによって異なります。実装モデルの選択を参照してください。
Webサービスをテストするための「スタブ」(単純なクライアントアプリケーションに付属)を生成することを選択できます。Javaクラスから生成する場合は、「WSDLファイル」(Webサービスをレジストリに発行するため)を要求したり、Webサービスの「サービスアドレス」(URL)を指定したりすることもできます。WSDLファイルから生成する場合は、「複合タイプ」がどのようにマップされるかを指定できます。
注記: jBrokerTM Web 1.xアプリケーションのサポートは、「旧製品との互換性」のオプションを使用して有効にできます。詳細については、jBroker Web 1.xとの互換性を選択した場合を参照してください。
ウィザードを終了すると、Webサービスに対して指定したものがすべて生成され、プロジェクトの他の部分は、サポートする変更内容で更新されます。
ファイル名を生成する場合、Webサービスウィザードは、JAX-RPCによって指定されている名前付けルールに従います。Javaクラスから開始した場合、結果として生成されるファイル名は、そのクラスの名前に基づいて付けられます。WSDLから開始した場合、結果として生成されるファイル名は、そのWSDLの定義に基づいて付けられます。
簡単にするため、このマニュアルでは、クラス名またはWSDL定義から派生して生成されたWebサービスのファイル名の一部を表すのにxxxを使用しています。
Webサービスウィザードは、Webサービスのファイル(前のリストを参照)を生成する際に、背後で「WebサービスSDKコンパイラ」を使用します。場合によっては、次のようなアプリケーションに固有の要件をサポートするために、これらのコンパイラによって追加コードやファイルが生成されることがあります。
詳細については、WebサービスSDKヘルプを参照してください。
WebサービスSDKの現在のバージョンには、以前のバージョンとの高度な後方互換性があります。ただし、JAX-RPC標準をサポートするために導入された特定の変更により、jBroker Web 1.xで作成されたアプリケーションをアップグレードする場合にコードの変更が必要になることがあります。このような変更には、次に対して使用される規則が含まれています。
ファイル名 JAX-RPCでは、特定のWebサービスファイルに名前を付ける場合の規則が指定されています。生成されるすべての名前の簡潔性と一貫性を保ちつつこれらの規則に従うために、新しい名前のパターンが採用されています(詳細については、次の「生成される1.x互換ファイル」を参照してください)。
クライアントコードでのスタブアクセス JAX-RPCでは、クライアントは、JNDI経由でスタブを直接検索するのではなく、サービスオブジェクトを使用してスタブのインスタンスを生成します。
現在のWebサービスSDKおよびJAX-RPCの規則にアップグレードすることをお勧めしますが、必須ではありません。WebサービスウィザードのjBroker Web 1.xの「互換性」オプションを使用することによって、ファイル名およびスタブアクセスに対する元のjBroker規則に従ってWebサービスファイルを生成できます。これにより、既存の1.xアプリケーションを変更することなく、WebサービスSDKの最新バージョンにおける他の改善点をすべて活用できるようになります。
生成される1.x互換ファイル 次の表は、jBroker Web 1.xの互換性オプションを使用した場合に生成されるファイルについて説明しています。
Webサービスウィザードによって生成されたファイルを編集する場合は、次のガイドラインに従います。
ガイドライン |
詳細 |
---|---|
編集が必要な場合があるファイル |
|
編集する必要のあるファイル |
|
編集してはいけないファイル |
生成された他のファイルは編集しても問題ありませんが、通常は編集する必要はありません。
場合によっては、Webサービスの実装を完了するために、手動でコード化されたファイルを1つまたは複数追加して、生成されたファイルとともに動作するようにする必要があります。追加ファイルの作成を参照してください。
生成されたxxxTie.javaファイルには、編集が必要な場合があるinit()メソッドが含まれています。
JavaBeanまたはJavaクラスから開始した場合、init()は、xxx_ServiceTieSkeletonのsetTarget()メソッドをコールし、(委任先の)xxxDelegateのインスタンスを渡すように生成されます。xxxDelegateによって空のコンストラクタが提供された場合、生成されたコードでは、そのコンストラクタを使用してインスタンスの生成を行います。
ただし、暗黙的または明示的な空のコンストラクタがない場合は、使用するコンストラクタを指定するようにコードを変更する必要があります。また、引数を期待するコンストラクタを使用するようにコードを変更することもできます。
ウィザードは、xxxDelegateの各パブリックコンストラクタに対して、setTarget()へのコールを自動的に生成します。 空のコンストラクタ(存在する場合)を使用する行以外の各行は、コメントアウトされます。必要なコンストラクタがある行のコメントを解除し、関連する変更を行います。
//super.setTarget( new MyObjectWSDelegate( java.lang.String arg0) ); //super.setTarget( new MyObjectWSDelegate( java.lang.String arg0, java.lang.String arg1) ); super.setTarget( new MyObjectWSDelegate( ) );
JavaリモートインタフェースまたはWSDLファイルから開始した場合、init()は、常にsetTarget()コールがコメントアウトされた状態で生成されます。この場合、インスタンスを生成して委任する独自のクラスを指定する必要があります。
//super.setTarget(new CONSTRUCT_YOUR_SERVICE_OBJECT_HERE);
EJBセッションBeanから開始した場合、生成されたinit()メソッドを編集する必要はありません。
xxxClientでWebサービスをテストする前に、生成されたxxxClient.javaファイルを、Webサービスの1つまたは複数のメソッドをコールするように編集する必要があります。 このファイルで「process()メソッド」を検索すると、使用できるメソッドコールがすべてリストされたコメントが見つかります。
// System.out.println("Test Result = " + remote.getString()); // System.out.println("Test Result = " + remote.setString(java.lang.String)); // System.out.println("Test Result = " + remote.sayHello());
テストするメソッドコールのコメントを解除し、必要に応じて適切な引数値を指定します。
// System.out.println("Test Result = " + remote.getString()); System.out.println("Test Result = " + remote.setString(args[0])); System.out.println("Test Result = " + remote.sayHello());
生成されたxxxClient.javaファイルに加えることができる追加の変更については、を参照してください。
多くの場合、ウィザードで生成が終了すると、Webサービスに必要なJavaソースファイルがすべて使用可能になります。ただし、手動で追加のクラスをコード化する必要が生じる場合もあります。
ウィザードによって生成されたWebサービスファイルを使用するには、次の操作を行います。
結合モデルを使用する場合、ウィザードによって、WARプロジェクトのweb.xmlファイルがWebサービスの適切なサーブレットマッピングで更新されます。ただし、スケルトンモデルの場合は、この情報を指定するようにweb.xmlを手動で編集する必要があります。
次の例では、MyServiceは、WebサービスMyRemoteに対して開発者がコード化したサーブレットクラスです。
<servlet> <servlet-name>MyService</servlet-name> <servlet-class>com.exsamp.rem.MyService</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyService</servlet-name> <url-pattern>MyRemote</url-pattern> </servlet-mapping>
web.xmlを編集するもう1つの理由は、Webサービスのブラウザベースのテスト環境を有効または無効にするためです。
詳細については、ブラウザからのWebサービスのテストを参照してください。
ウィザードが機能するにつれて、必要に応じて、プロジェクトのクラスパスおよびコンテンツに自動的にファイルが追加されます。ただし、コンパイルおよび実行するために必要なものがすべてプロジェクトに含まれていることを自分で確認する必要もあります。
たとえば、WebサービスでEJBセッションBeanにアクセスする場合、EJBクライアントJARファイルがプロジェクトのクラスパスに存在する必要があります。
プロジェクトに必要なクラスパスおよびコンテンツ(WebサービスSDKで必要なものを含む)のセットアップの詳細については、生成の準備を参照してください。
WARをJ2EEサーバに展開するために必要なサーバ固有の展開情報を準備します。 たとえば、Novell exteNd Application Serverに展開する場合は、exteNd展開計画ファイルを作成します。
exteNd Director 開発環境から展開する場合は、J2EEサーバのサーバプロファイルをセットアップする必要もあります。
この手順を完了すると、WARの各Webサービスは、公開されたメソッドの標準HTTP SOAP要求に応答できるサーブレットとしてアクセス可能になります。
WebサービスのxxxClientクラスを生成、編集、およびコンパイルした場合は、このクラスをメソッドコールの簡単なテスト用に使用できます。 exteNd Director 開発環境からxxxクライアントを実行するには、[ツール]>[ Webサービスクライアントクラスの実行]の順に選択します。Webサービスウィザードクライアントランナーが表示され、現在のプロジェクトから選択できるクライアントクラスのリストが提供されます。
xxxClientはコマンドラインから実行することもできます(システムクラスパスに適切なディレクトリおよびアーカイブを含めた場合)。
WebサービスSDKでは、WebブラウザからのWebサービスのテストを支援する機能が提供されます。Webサービスの開発および展開が終了したら、そのサービスのURLをブラウズして次の操作を実行できます。
このテスト機能をランタイム時に使用できるかどうかは、WARの展開記述子(web.xml)にあるwssdk.test.disableという名前の環境エントリによって制御されます。exteNd Director 開発環境で汎用WARプロジェクトを作成した場合は、新規プロジェクトウィザードによって自動的にweb.xmlにwssdk.test.disableが含められ、trueに設定されます。この機能を有効にするには、展開する前にwssdk.test.disableをfalseに設定しておく必要があります。
<env-entry> <env-entry-name>wssdk.test.disable</env-entry-name> <env-entry-value>false</env-entry-value> <env-entry-type>java.lang.Boolean</env-entry-type> </env-entry>
Webサービスウィザードを使用して開発する場合、選択できる基本的な実装モデルには、2種類あります。 この節では、生成するWebサービスに最も適した実装モデルを選択できるように、これらの実装モデルについて説明します。
次の表は、結合モデルの概要と、このモデルを使用する場合について説明しています。
Webサービスウィザードへの入力として指定するJavaリモートインタフェースまたはWSDLファイルしかない場合、この結合モデルを使用することは可能ですが、一般的ではありません。この場合、ウィザードの出力では、後で完了できるように、モデルの委任部分が残されます。 その後、実装クラスをコード化し、インスタンスを生成して委任するように、生成された結合クラスを編集する必要があります。
次の表は、スケルトンモデルの概要と、このモデルを使用する場合について説明しています。
このシナリオでは、公開するメソッドを実装する既存のJavaクラスに基づいてWebサービスを生成するために、Webサービスウィザードをどのように使用できるかがわかります。
実装モデル このシナリオでは、「結合」モデルの使用について説明しています。このアーキテクチャの概要については、実装モデルの選択を参照してください。
このシナリオのWARプロジェクトは、次のようにセットアップされます。
WebServiceSample.spf
このプロジェクトから生成される「アーカイブ」は次のとおりです。
WebServiceSample.war
WEB-INF lib wssdk.jar classes com exsamp obj MyObject.java web.xml
...\WEB-INF\lib\wssdk.jar ...\exteNdn\tools\compilelib\j2ee_api_1_n.jar
このシナリオでWebサービスウィザードに対して指定されている入力は、次のとおりです。
MyObjectは、Webサービスの生成元となる既存のJavaクラスです。このクラスは、公開するメソッドを実装します。MyObject.javaには、次のコードが含まれています(ウィザードを開始する前にコンパイルする必要があります)。
package com.exsamp.obj; public class MyObject { private String s; public MyObject() { } public MyObject(String xxx) { } public MyObject(String xxx, String yyy) { } public String getString() { return s; } public boolean setString(String s) { this.s = s; return true; } public String sayHello() { return "Hello there, I am on the server"; } }
このウィザードパネルには、次のように入力されています。
このウィザードパネルには、次のように入力されています。
このウィザードパネルには、次のように入力されています。
このウィザードパネルには、次のように入力されています。
このウィザードパネルには、次のように入力されています。
このシナリオで指定された入力に基づいて、Webサービスウィザードは、Webサービスを実装するために次のファイルを生成します。
MyObjectWS_ServiceSkeleton.javaは、Webサービスへのアクセスを処理する抽象サーブレットクラスです。
MyObjectWS_ServiceTieSkeleton.javaは、結合モデルをサポートするためにMyObjectWS_ServiceSkeletonを継承する抽象クラスです。
MyObjectWSTie.javaは、抽象サーブレットクラスを継承し、Webサービスのフロントエンドとして機能します。受信する要求(メソッドコール)を処理するために、このサーブレットは、MyObjectWSDelegateのインスタンスを生成して委任します。
MyObjectWSDelegate.javaは、実装クラス(MyObject)のインスタンスを生成し、要求されたメソッドコールをこのインスタンスに対して実行します。
新規Webサービス用に生成されたWSDLは、次のとおりです。
<?xml version="1.0" encoding="UTF-8"?> <definitions name="MyObjectWSService" targetNamespace="urn:com.exsamp.obj.MyObject" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:com.exsamp.obj.MyObject" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <types/> <message name="setStringRequest"> <part name="arg0" type="xsd:string"/> </message> <message name="setStringResponse"> <part name="result" type="xsd:boolean"/> </message> <message name="getStringRequest"/> <message name="getStringResponse"> <part name="result" type="xsd:string"/> </message> <message name="sayHelloRequest"/> <message name="sayHelloResponse"> <part name="result" type="xsd:string"/> </message> <portType name="MyObjectWS"> <operation name="setString" parameterOrder="arg0"> <input message="tns:setStringRequest"/> <output message="tns:setStringResponse"/> </operation> <operation name="getString"> <input message="tns:getStringRequest"/> <output message="tns:getStringResponse"/> </operation> <operation name="sayHello"> <input message="tns:sayHelloRequest"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="MyObjectWSBinding" type="tns:MyObjectWS"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="setString"> <soap:operation soapAction="urn:com.exsamp.obj.MyObject/setString"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </output> </operation> <operation name="getString"> <soap:operation soapAction="urn:com.exsamp.obj.MyObject/getString"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </output> </operation> <operation name="sayHello"> <soap:operation soapAction="urn:com.exsamp.obj.MyObject/sayHello"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:com.exsamp.obj.MyObject" use="encoded"/> </output> </operation> </binding> <service name="MyObjectWSService"> <port binding="tns:MyObjectWSBinding" name="MyObjectWSPort"> <soap:address location="http://localhost/WebServiceSampleDB/WebServiceSample/MyObject"/> </port> </service> </definitions>
このシナリオで指定されてた入力に基づいて、Webサービスウィザードは、展開されたWebサービスをテストできるように、次のファイルを生成します。
MyObjectWSService.javaは、JAX-RPCで使用されるサービスインタフェースで、Webサービスのスタブをクライアントで取得できるようにします。
MyObjectWSServiceImpl.javaは、スタブ(MyObjectWS_Stub)のインスタンスの生成を処理するサービス実装クラスです。
MyObjectWSBinding_Stub.javaは、Webサービスにアクセスするためのプロキシとしてクライアントで使用されます。このスタブクラスは、各メソッドコールのロジスティクスを処理するリモートインタフェース(MyObjectWS)を実装します。
MyObjectWSClient.javaは、次の方法でWebサービスにアクセスするシンプルなクライアントアプリケーションです。
MyObjectWSClient.javaファイルのprocess()メソッドを編集して、テストするWebサービスメソッドコールのコメントを解除する必要があります。 変更内容は次のとおりです。
// System.out.println("Test Result = " + remote.getString()); // System.out.println("Test Result = " + remote.setString(java.lang.String)); System.out.println("Test Result = " + remote.sayHello());
このシナリオでは結合モデルが使用されているため、Webサービスウィザードによってweb.xmlファイルが自動的に更新され、MyObject Webサービスの要求を処理するサーブレットクラスとしてMyObjectWSTieが宣言されます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servlet> <servlet-name>MyObject</servlet-name> <servlet-class>com.exsamp.obj.MyObjectWSTie</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyObject</servlet-name> <url-pattern>MyObject</url-pattern> </servlet-mapping> <env-entry> <env-entry-name>wssdk.test.disable</env-entry-name> <env-entry-value>true</env-entry-value> <env-entry-type>java.lang.Boolean</env-entry-type> </env-entry> </web-app>
この場合、開発者がWebサービス用のWebサービスSDKのブラウザベースのテスト環境を無効にするように選択した点にも注意してください。代わりに、Webサービスは、生成されたMyObjectWSClientアプリケーションを実行することによってテストされます。
ブラウザベースのテスト環境の詳細については、ブラウザからのWebサービスのテストを参照してください。
このプロジェクトを作成した後、WARファイルが作成されてJ2EEサーバに展開されると、MyObject Webサービスのテストを実行する準備が整ったことになります。 MyObjectWSClientアプリケーションを実行するためにexteNd Director 開発環境でクライアントランナーを使用した場合の結果は、次のとおりです。
Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved. more ...