Java

JNLP アプリケーションの WAR 形式でのパッケージ化

Java TM Web Start

Version 1.2

 コメントおよびフィードバックの送付先 : javawebstart-feedback@sun.com

目次

はじめに

サーブレットの構成
リソースの指定
リソースへのマッピング要求
JNLP ファイルの処理

はじめに

Java Web Start の開発者向けパックには、JNLP ファイルおよび関連するリソースを Web アーカイブ (.war) ファイルにパッケージ化するために使用されるサーブレットが含まれています。このサーブレットの目的は、JNLP アプリケーション用の簡単で利便性の高いパッケージング形式を提供することによって、Tomcat や J2EE 準拠のアプリケーションサーバなどの Web コンテナに JNLP アプリケーションを容易に配備できるようにすることです。

ダウンロードサーブレットは、次の機能をサポートします。

パッケージ化をサポートしているのは、JnlpDownloadServlet という 1 つのサーブレットです。このサーブレットは、jnlp-servlet.jar ファイルにパッケージ化されています。

以下に、サーブレットの使用方法を示す 2 つの例、およびサーブレットの機能の詳細を説明します。

1 つ目の例では、バージョンベースのダウンロードを使用せずに、アプリケーションを WAR ファイルにパッケージ化する方法を示します。JnlpDownloadServlet を使って、要求時に正確な URL (URL 絶対パス) を JNLP ファイルに挿入します。2 つ目の例では、バージョンベースのダウンロードをサポートする方法を示します。

バージョンダウンロードプロトコルを使用しない WAR ファイル

example1.war には、以下が含まれています。
   /index.html
   /app/launch.jnlp
   /app/application.jar
   /app/images/icon.gif
   /WEB-INF/web.xml
   /WEB-INF/lib/jnlp-servlet.jar
   /WEB-INF/lib/jaxp.jar
   /WEB-INF/lib/parser.jar
アプリケーションの JNLP ファイルは、次のようになります。
   TS: 2002-04-23 19:21:05
   <?xml version="1.0" encoding="UTF-8"?>
   <jnlp codebase="$$codebase">
     <information>
         <title>Example 1</title>
         <vendor>Myself</vendor>
         <description>just an example</description>
         <icon href="images/icon.gif"/>
     </information>
     <resources>
       <j2se version="1.2+"/>
       <jar href="application.jar"/>
     </resources>
     <application-desc/>
   </jnlp>
TS タグの付いた最初の行には、サーブレットが返す JNLP ファイルのタイムスタンプが含まれています。タイムスタンプは、ISO 8601 形式で記述されます。この行が省略されると、WAR ファイル内のファイルのタイムスタンプが使用されます。文字列 $$codebase は、JnlpDownloadServlet によって、要求を行う実際の URL に置き換えられます。

web.xml ファイルは、JNLP ファイルへのすべての要求に対して JNLPDownloadServlet を呼び出すように、Web コンテナに指示します。

  <web-app>
     <servlet>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
     </servlet>
     <servlet-mapping>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <url-pattern>*.jnlp</url-pattern>
     </servlet-mapping>
  </web-app>
JnlpDownloadServlet が動作するためには、XML パーサが必要です。WEB-INF/lib ディレクトリ内の jaxp.jar および parser.jar で XML パーサが実装されています。パーサのリファレンス実装は、
http://java.sun.com/xml からダウンロードできます。

バージョンダウンロードプロトコルを使用する WAR ファイル

example2.war には、以下が含まれています。
   /index.html
   /app/version.xml
   /app/launch.jnlp
   /app/application.jar
   /app/lib__V2.1.jar
   /app/images/icon.gif
   /WEB-INF/web.xml
   /WEB-INF/lib/jnlp-servlet.jar
   /WEB-INF/lib/jaxp.jar
   /WEB-INF/lib/parser.jar
/app ディレクトリには、2 つの JAR リソース、application.jar および lib.jar が含まれます。lib.jar は命名規約を使用して、バージョン ID 2.1 を関連付けます (つまり、バージョン情報はファイルごとに関連付けられます)。application.jar ファイルのバージョンは、version.xml ファイルに記述されます (つまり、バージョン情報はディレクトリごとに記述されます)。versions.xml ファイルは、次のようになります。
   <jnlp-versions>
      <resource>
         <pattern>
           <name>application.jar</name>
            <version-id>1.1</version-id>
         </pattern>
         <file>application.jar</file>
      </resource>
   </jnlp-versions>
アプリケーションの JNLP ファイルは、次のようになります。
   TS: 2002-04-23 19:21:05
   <?xml version="1.0" encoding="UTF-8"?>
   <jnlp codebase="$$codebase" href="$$name">
     <information>
         <title>Example 2</title>
         <vendor>Myself</vendor>
         <description>just an example</description>
         <icon href="images/icon.gif"/>
     </information>
     <resources>
       <j2se version="1.2+"/>
       <jar href="application.jar" version="1.1"/>
       <jar href="lib.jar" version="2.1"/>
     </resources>
     <application-desc/>
   </jnlp>
最後に、/app ディレクトリへのすべての要求に対して JnlpDownloadServlet が呼び出されるように、web.xml ファイルを構成します。
  <web-app>
     <servlet>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
     </servlet>
     <servlet-mapping>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <url-pattern>/app/*</url-pattern>
     </servlet-mapping>
  </web-app>

サーブレットの構成

このセクションでは、JnlpDownloadServlet を含めて WAR ファイルを構成する方法、およびサーブレットの構成方法を説明します。

WAR アーカイブへのサーブレットの追加

まず、必要なサーブレットコードを、サーブレットのコンテナが利用できるようにする必要があります。これは、WEB-INF/lib ディレクトリを生成することにより行われます。WEB-INF/lib/ ディレクトリに jnlp-servlet.jar ファイルを追加することによって、WAR アーカイブにサーブレットが追加されます。サーブレットは XML パーサにアクセスする必要があるため、Java XML パーサを実装する JAR ファイルも追加する必要があります。これらのファイルは、
http://java.sun.com/xml からダウンロードできます。

サーブレットのコードが利用可能になったら、適切な JNLP ファイルおよび JAR ファイルのセットまたは指定されたサブディレクトリに対してサーブレットを呼び出すように、Web コンテナに指示する必要があります。これはすべて、WEB-INF/web.xml ファイルの <web-app> タグで指定します。

   <web-app>
      ...
   </web-app>
最初に、サーブレットの呼び出し方法を Web コンテナに指示します。これには、<servlet> タグを使用します。
   <servlet>
      <servlet-name>JnlpDownloadServlet</servlet-name>
      <servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
   </servlet>
次に、サーブレットをいつ呼び出すかを Web コンテナに指示します。これには、いくつかの方法があります。1 つの方法として、特定のディレクトリ、または特定の拡張子を持つファイルが指定された場合に呼び出すことができます。たとえば、JNLP ファイルに対してサーブレットを呼び出す場合は、web.xml ファイルに以下を追加します。
   <servlet-mapping>
     <servlet-name>JnlpDownloadServlet</servlet-name>
     <url-pattern>*.jnlp</url-pattern>
   </servlet-mapping>
特定のサブディレクトリに対してサーブレットを呼び出す場合は、以下を追加します。
   <servlet-mapping>
     <servlet-name>JnlpDownloadServlet</servlet-name>
     <url-pattern>/app/*</url-pattern>
   </servlet-mapping>

サーブレットの構成方法の例については、example1 および example2 も参照してください。

ログ

サーブレットには、その動作を監視するためのログ機能が組み込まれています。生成されるログメッセージは、次の 4 つのカテゴリに分けられます。
FATAL (致命的)
サーブレット内部で発生した機能不全エラーまたは内部エラー
WARNING (警告)
WAR ファイル内の情報の処理中 (version.xml ファイルの構文解析など) に発生したエラー
INFORMATIONAL (情報)
すべての要求、応答、ディレクトリの再走査などのログ
DEBUG (デバッグ)
要求がどどのように処理されているかを示す詳細な内部情報
ログ出力は、logLevel および logPath という 2 つのサーブレット初期化パラメータによって制御されます。ログレベルは、NONE、FATAL、WARNING、INFORMATIONAL、DEBUG のいずれかに設定することができます。ログパスには、出力の書き込み先のファイルを指定します。パスを指定しない場合は、ログはサーブレットの標準ログに書き込まれます (ServletContext.log メソッドを使用)。次に例を示します。
 <servlet>
    <servlet-name>
      JnlpDownloadServlet
    </servlet-name>
    <servlet-class>
      com.sun.javaws.servlet.JnlpDownloadServlet
    </servlet-class>

    <init-param>
      <param-name>
        logLevel
      </param-name>

      <param-value>
        DEBUG
      </param-value>
    </init-param>

    <init-param>
      <param-name>
        logPath
      </param-name>

      <param-value>
        /logs/jnlpdownloadservlet.log
      </param-value>
    </init-param>

  </servlet>

ファイル拡張子および MIME タイプの構成

サーブレットは、JNLP ファイルおよび JAR ファイルを特別に扱います。後述の節で説明するように、JNLP ファイルはマクロによって展開されます。JAR ファイルに対するバージョンベースの要求によって、増分更新が生成されることがあります。サーブレットは、拡張子を利用して、ファイルが JNLP または JAR のどちらであるかを特定します。JNLP ファイルのデフォルトの拡張子は .jnlp、JAR ファイルのデフォルトの拡張子は .jar です。これらのデフォルト拡張子は、初期化パラメータ jnlp-extension および jar-extension を使って変更できます。次に例を示します。
    <init-param>
      <param-name>
        jnlp-extension
      </param-name>

      <param-value>
        .xjnlp
      </param-value>
    </init-param>
返される MIME タイプも、ファイルの拡張子に基づいて決定されます。MIME タイプは、Web コンテナおよび WAR ファイルの構成ファイルで確認されます。マッピングが指定されていない場合、デフォルトの MIME タイプは次のようになります。
       拡張子       デフォルト MIME タイプ
     -------------------------------------------
       .jnlp        application/x-java-jnlp-file
       .jar         application/x-java-archive
       .jardiff     application/x-java-archive-diff
マッピングは、web.xml ファイルの <mime-type> 要素を使って変更できます。次に例を示します。
  <web-app>
     ...
     <mime-mapping>
        <extension>jnlp</extension>
        <mime-type>text/ascii</mime-type>
     </mime-mapping>
     ...
  </web-app>

リソースの指定

イメージ、JAR ファイル、JNLP ファイルなどのアプリケーションリソースは、WAR ファイルに格納されます。WAR ファイル自体は階層ディレクトリ構造になっており、WAR ファイル中のリソースの配置により、検索に使用される URL が決まります。

WAR ファイル (またはサーブレット) が、http://www.mytool.com/tool/ で始まるすべての URL 要求を処理するように構成されている場合を考えてみましょう。このとき、http://www.mytool.com/tool/app/launch.jnlp が要求されたとします。この場合、JnlpDownloadServlet は、WAR ファイル中の app/ ディレクトリ内で launch.jnlp リソースを検索します。

バージョン情報を保持しない場合

関連付けられたバージョン情報を持たないリソース (アプリケーションの JNLP ファイルなど) は、単に WAR ファイルに追加されるだけです。たとえば、上の例では、WAR ファイルには次のファイルが含まれます。
    /app/launch.jnlp
通常、返されるタイムスタンプは、ファイルが WAR ファイル内で保持する最終更新タイムスタンプです。唯一の例外は JNLP ファイルで、タイムスタンプは JNLP ファイル内で明示的に指定されます (
後述の説明を参照)。

バージョン情報その他

JNLP 仕様に準拠したバージョンベースおよび拡張子ベースのダウンロードプロトコルでは、バージョン ID、オペレーティングシステム、システムアーキテクチャ、およびロケールに基づいて、リソースを検索できます。JnlpDownloadServlet は、この情報をリソースに関連付ける 2 つの機構を提供します。一方は命名規約を使用してファイルごとに関連付けを行い、もう一方は構成ファイルを使用してディレクトリごとに関連付けを行います。同一のディレクトリに両方の機構を適用することも可能です。

次の情報を、リソースに関連付けることができます。

パスは、WAR アーカイブ内のリソースの位置によって指定されます。残りの情報は、命名規約を使用することによって指定されるか、または version.xml ファイル内で指定されます。

リソースの命名

二重下線 (__) のマーカーがファイル名に含まれる場合、ファイルの命名規約が使用されます。ファイル名は、次に示す BNF 表記法に従って構文解析されます。
	file    ::= name __ options . ext
	options ::= option ( __ options ) *
	option  ::= V version-id |
        	    O os |
            	    A arch |
            	    L locale
バージョン ID は、ファイルごとに 1 つだけ指定できます。ただし、os フィールド、arch フィールド、および locale フィールドは、複数指定することができます。次に例を示します。
	application__V1.2__Len_US__Len.jar
この例では、リソース application.jar には、バージョン ID 1.2 とロケール en_US および en が関連付けられています。

version.xml ファイル

各ディレクトリに version.xml ファイルを配置することにより、特定のディレクトリ内のファイルの追加情報 (バージョン ID など) を記述できます。このファイルは、ファイル命名規約の代わりに使用することができます。

たとえば、ディレクトリ内にファイル application-1_2-us.jar および version.xml を配置し、version.xml の内容を次のようにします。

       <jnlp-versions>
          <resource>
             <pattern>
                <name>application.jar</name>
                <version-id>1.2</version-id>
                <locale>en_US</locale>
                <locale>en</locale>
             </pattern>
             <file>application-1_2-us.jar</file>
         </resource>
       </jnlp-versions>
これは、application__V1.2__Len_US__Len.jar という名前のファイルをディレクトリ内に配置するのと同じになります。

version.xml 中でプラットフォームバージョン ID を設定することにより、リソースを指定することもできます。この場合、リソースは、JRE 用の特定のプラットフォーム要求を満たすために使用されます。プラットフォームバージョン ID 付きのリソースは、<platform> 要素を使って指定されます。次に例を示します。

	  <platform>
             <pattern>
                <name>J2RE</name>
                <version-id>1.3</version-id>
                <locale>en_US</locale>
                <locale>en</locale>
             </pattern>
             <file>j2re-1_3.0-us.jnlp</file>
             <product-version-id>1.3.0</product-version-id>
         </platform>
通常、現在ローカルシステムにインストールされていない Java 2 プラットフォームのバージョンをアプリケーションが要求すると、Java Web Start はプラットフォームバージョン要求を内部で生成します。

version.xml のすべての文書型定義 (DTD) を次に示します。

   <!ELEMENT jnlp-versions <resource*, platform*)>
   <!ELEMENT resource (pattern, file)>
   <!ELEMENT platform (pattern, file, product-version-id)>
   <!ELEMENT pattern (name, version-id, os*, arch*, locale*)>
   <!ELEMENT name (#PCDATA)>
   <!ELEMENT version-id (#PCDATA)>
   <!ELEMENT os (#PCDATA)>
   <!ELEMENT arch (#PCDATA)>
   <!ELEMENT locale (#PCDATA)>
   <!ELEMENT file (#PCDATA)>
   <!ELEMENT product-version-id (#PCDATA)>

リソースへのマッピング要求

JNLP 仕様には、4 種類の異なるダウンロード要求が定義されています。Java Web Start (より一般的には、JNLP クライアント) は、リソースの要求時に、サーバに対してこれらのダウンロード要求を実行できます。

要求は、最初に JNLPDownloadServlet によって処理され、次の情報が抽出されます。

example2 の事例で、それが http://www.mytool.com/tool2/ によりホストされる場合を考えてみましょう。http://www.mytool.com/tool2/app/lib.jar&version-id=2.1 が実行されるとします。この場合、リソースのパスは app/ に、名前は lib.jar に、バージョン文字列は 2.1 に、OS、アーキテクチャ、およびロケールのリストは空になります。

ディレクトリへの要求 (http://www.mytool.com/tool2/app/ など) にはデフォルトのファイル名 launch.jnlp が追加されます。このため、この要求は http://www.mytool.com/tool2/app/launch.jnlp と同じになります。

基本ダウンロード要求の処理

バージョン ID が指定されていない要求 (要求に version-id パラメータも platform-version-id パラメータも指定されていない) は、基本ダウンロード要求として処理されます。

最初に、要求に二重下線 (__) が含まれるかどうか、または version.xml ファイルへの要求かどうかが検査されます。いずれかに該当する場合、要求は拒否され、HTTP 404 エラーコードが返されます。

次に、JnlpDownloadServlet は、指定されたパスおよび名前のリソースを WAR ファイル内で検索し、見つかった場合、それを返します。見つからなかった場合は、その要求に対して HTTP 404 エラーコードが返されます。

見つかったファイルが JNLP ファイルの場合、後述の方法で前処理されてから返されます。

バージョンベースのダウンロード要求の処理

バージョン ID が指定されたリソースの検索方法は、バージョンベースのダウンロードプロトコル、拡張ダウンロードプロトコル、およびプラットフォームバージョンダウンロード要求において、同一です。

まず JnlpDownloadServlet は、URL 要求が (要求中のパスに基づいて) アクセスする WAR ファイルディレクトリ内にあるすべてのリソースのデータベースを構築します。version.xml ファイル (存在する場合)、および前述の命名規約を使用するディレクトリ内のファイルリストを走査することによって、データベースが構築されます。サーブレットは、情報を内部にキャッシュします。version.xml ファイルのタイムスタンプが最後に走査したものよりも新しい場合にのみ、再走査が実行されます。このため、命名規約を利用してファイルを追加する場合、version.xml ファイルのタイムスタンプを更新して、サーブレットにより再走査が確実に実行されるようにしてください。

次に、サーブレットはデータベース内のエントリを走査して、指定された要求に一致するものを検索します (一致規則については後述します)。プラットフォームに関係しない要求の場合、最初に version.xml ファイル内の resource エントリが指定された順序で走査され、次に命名規約を使って指定されたエントリが走査されます。プラットフォームバージョン要求の場合、version.xml ファイル内の platform エントリが、指定された順序で走査されます。要求を満たすエントリが複数存在する場合、バージョン ID の値がもっとも大きいエントリが返されます。要求を満たすエントリが複数存在し、かつバージョン ID の値が等しい場合、指定された最初のエントリが返されます。

一致規則は、次のとおりです。

  1. リソースの名前が、要求に一致する必要がある。
  2. リソースのバージョン ID が、要求内のバージョン文字列に一致する必要がある。
  3. オペレーティングシステム、アーキテクチャ、およびロケールリストに対して、次の規則が適用される。
    1. リソースに対し空のリストが指定された場合、一致と見なされる。
    2. リソースに対し空でないリストが指定された場合、リソースで指定された 1 つ以上の値が、要求内で指定された 1 つ以上の値の前置と等しいなら、一致と見なされる。
応答として返された x-java-jnlp-version-id は、対応するリソースのバージョン ID になります。ただし、プラットフォーム要求は例外で、version.xml ファイルの <product-version-id> フィールドから取得されます。

一致したファイルが JNLP ファイルの場合、後述の方法で前処理されてから返されます。

JARDiff の自動生成

サーブレットは、可能な場合には増分更新を自動的に生成して、JAR ファイルに返します。current-version-id パラメータが要求に含まれており、サーブレットが current-version-id の一致と要求されたバージョンの両方を (上述の一致規則で) 検索することができ、かつ要求が JAR ファイルに対するものである (ターゲットのリソースが拡張子が .jar) 場合、JARDiff ファイルがサーブレットにより生成されます。JARDiff ファイルは、そのサイズが要求されたバージョンのサイズよりも小さいものである限り返されます。

生成された JARDiff ファイルは、指定された Web コンテナに固有の一時ディレクトリに格納されます。サーブレットは、javax.servlet.context.tempdir コンテキスト属性を使って、一時作業ディレクトリを検索します。

JNLP ファイルの処理

JnlpDownloadServlet は、JNLP ファイル内の特定のテンプレートの値をマクロにより自動的に展開し、現行の要求に固有な URL で置き換えます。これにより、ハードコードされた URL を含めずに、JNLP ファイルを記述および配備することができます。

マクロ展開

サーブレットは、JNLP ファイル内の特定の固定キー (接頭辞 $$ の付いたもの) を、現行の要求に基づく URL で置き換えます。位置に依存しない WAR ファイルを作成して Web コンテナ内に配備することができるように、キーが設計されています。

サーブレットが検索および置換を行う 3 つのキーを、次の表に示します。

         パターン      値
         ----------------------------------------------------------------
         $$codebase    要求の完全な URL (JNLP ファイルの名前を除く)
	 $$name        JNLP ファイルの名前
         $$context     Web Archive のベース URL
例:
example1 の WAR ファイルを考えましょう。この WAR ファイルが、http://www.mytool.com/tool に配備されているとします。この場合、http://www.mytool.com/tool/app/launch.jnlp への要求により、JNLP ファイルが返されます。マクロにより展開されたキーの値は、次のようになります。
      $$codebase = http://www.mytool.com/tool/app/
      $$name     = launch.jnlp
      $$context  = http://www.mytool.com/tool/

サーブレットは、JNLP ファイルの形式や、XML が正しく形成されているかどうかを検証することはありません。値の置き換えは、単ににテキスト上で行われます。

明示的なタイムスタンプ

明示的なタイムスタンプを JNLP ファイルに含めることにより、Web サーバが返すタイムスタンプを一定にできます。JNLP ファイルが、ラウンドロビン方式または負荷均衡方式で同一の URL のサーバとして稼動する複数の Web サーバ上で複製される場合、特に有用です。同様の手法は、JAR ファイルには適用されないことに注意してください。JAR ファイルの場合、バージョンベースのダウンロードプロトコルを代わりに使用する必要があります。

最初の行が TS: で始まる場合、明示的なタイムスタンプが JNLP に含まれます。この場合、タイムスタンプは ISO 8601 形式に基づいて構文解析されます (次の節を参照)。最初の行は、コンテンツからも削除されます。

TS: 要素を使用したサンプル JNLP ファイルの例については、前述の example1 および example2 を参照してください。

ISO 8601 形式

一般的なタイムスタンプの形式は、次のとおりです。
   YYYY-MM-DD hh:mm:ss
次に示すように、ダッシュ、コロン、および秒を付けずに記述することもできます。
   YYYYMMDDhhmm
hh は 24 時間単位で表記します。デフォルトでは、ローカルタイムゾーンが使用されます。次に示すように、時刻の最後に大文字の Z を追加することにより、UTC (世界標準時、GMT としても知られる) を指定することもできます。
     23:59:59Z または 235959Z
次の文字列を時刻に追加することにより、使用するローカルタイムゾーンが、UTC に hh 時間 mm 分を追加したものであることを指定できます。
     +hh:mm、+hhmm、または +hh
経度ゼロより西のタイムゾーン (UTC よりも前の時間になる) の場合は、次のように表記します。
     -hh:mm, -hhmm, or -hh
たとえば、中央ヨーロッパ標準時 (CET) は +0100、米国およびカナダの東部標準時 (EST) は -0500 となります。次の文字列は、すべて同じ時刻を指します。
     12:00Z = 13:00+01:00 = 0700-0500


Copyright © 2002 Sun Microsystems, Inc. All Rights Reserved.

Sun