JnlpDownloadServlet
の使用JnlpDownloadServlet
の構築
JnlpDownloadServlet
は、Java Web Start アプリケーションを Web サーバーに配備するとともに拡張機能を提供するプロセスを簡素化するサーブレットです。JnlpDownloadServlet
は、コンパイル済み JAR ファイルおよびソースコードの両形式で、JDK の sample/jnlp/servlet
ディレクトリに用意されています。
もっとも単純な JNLP 配備の場合、アプリケーションファイルと JNLP ファイルを Web サーバー上に置きます。JNLP MIME タイプ用に Web サーバーを構成すると、基本的な JNLP 機能が使用可能になります。つまり、ユーザーがブラウザで JNLP ファイルのリンクをクリックすると、アプリケーションがダウンロードされて実行されます。
ただし、この方法にはいくつかの欠点があります。まず、アプリケーションのコードベースの URL を JNLP ファイルに明示的に指定する必要があります。したがって、アプリケーションを別の場所でホストすることにした場合や、ローカルのテストサーバーから公開の本稼働サーバーに移行する場合に、その変更が必要になります。次に、アプリケーションのタイムスタンプを報告するためにアプリケーションファイル上のファイルシステムタイムスタンプが使用されますが、これは望ましくない場合があります。最後に、HTTP を介して実装されるのは JNLP プロトコルのもっとも基本的な部分だけです。バージョン管理などのほかの機能はサポートされません。
JnlpDownloadServlet
は、アプリケーションファイルとクライアントとのパイプ役として機能します。これによって次の機能が提供されます。
JnlpDownloadServlet
によって提供されるアプリケーション配備の便利な機能について理解するには、JNLP と Java Web Start を使用してアプリケーションを配布するもっとも単純な方法をまず理解する必要があります。
app1
例 (JDK の sample/jnlp/servlet
ディレクトリ内) には、単純なアプリケーションと、有用性の高い Ant ビルドスクリプトが含まれています。Ant ビルドスクリプトは、アプリケーションを構築して Web サーバーでの配布用の WAR ファイルにバンドルします。
アプリケーション自体は単一のクラス Pie
とイメージファイル key-lime.jpg から成り、これらは pie.jar JAR ファイルにパッケージ化されています。
pie.jar アーカイブは Web アプリケーションファイル app1.war にパッケージ化されています。その内容は次のとおりです。
WEB-INF/web.xml index.html pie.jnlp pie.jar
JNLP ファイルは、アプリケーションが http://localhost:8080/
のサーバーに配備されると想定してアプリケーションを記述しており、ローカルにインストールされた Tomcat サーバーで機能します。
<?xml version="1.0" encoding="UTF-8"?> <jnlp spec="1.0+" codebase="http://localhost:8080/app1"> <information> <title>Pie</title> <vendor>Example Vendor</vendor> </information> <resources> <j2se version="1.2+"/> <jar href="pie.jar" main="true" /> </resources> <application-desc/> </jnlp>
クライアントとサーバーのやりとりは次のような対話と見なすことができます。
[ユーザーがブラウザでリンクをクリックします。]
クライアントブラウザ: pie.jnlp をください。
サーバー: はい、どうぞ。
クライアントブラウザ: MIME タイプは application/x-java-jnlp-file
なのですね。Java Web Start さん、私のために pie.jnlp を処理してください。
クライアント Java Web Start: このアプリケーションにはどのようなリソースが必要なのか調べてみます。サーバーさん、pie.jar をください。
サーバー: はい、どうぞ。
クライアント Java Web Start: それでは、JAR ファイルの Main-class
マニフェスト属性を使ってこのファイルを起動します。
[ユーザーの画面にアプリケーションが表示されます。]
app2
の例では、JnlpDownloadServlet
をアプリケーションとバンドルする方法と、それを使用して JNLP ファイルで単純な置換を実行する方法が示されています。
app3
の例は、バージョン管理されたリソース要求が JnlpDownloadServlet
でどのように処理されるかを示しています。
app2
と app3
はどちらも、以降のセクションで参照されています。
JnlpDownloadServlet
の使用
JnlpDownloadServlet
を利用するには、次の手順を実行します。
JnlpDownloadServlet
を Web アプリケーションの WAR ファイルにパッケージ化します。すべての機能を利用するには、2 つの JAR ファイル jnlp-servlet.jar
および jardiff.jar
を使用する必要があります。これら 2 つの JAR ファイルを WAR ファイルの WEB-INF/lib
ディレクトリに置きます。
*.jnlp
および *.jar
の要求を JnlpDownloadServlet
にマッピングします。このファイルには、JnlpDownloadServlet
を識別して JNLP ファイルと JAR ファイルのハンドラにする行が含まれている必要があります。完全な例を次に示します。
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>JnlpDownloadServlet</servlet-name> <servlet-class>jnlp.sample.servlet.JnlpDownloadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>JnlpDownloadServlet</servlet-name> <url-pattern>*.jnlp</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>JnlpDownloadServlet</servlet-name> <url-pattern>*.jar</url-pattern> </servlet-mapping> </web-app>
app2
の例と app3
の例では、JnlpDownloadServlet
を Web アプリケーションにパッケージ化する方法が示されています。詳細は、Ant ビルドスクリプト app2/build.xml
または app3/build.xml
を参照してください。
JnlpDownloadServlet
は JNLP ファイルで簡易置換を行います。クライアントが JNLP ファイルを要求すると、このサーブレットが元のファイルを読み取り、値を置換し、結果を返します。
JNLP ファイルの最初の行にタイムスタンプが含まれている場合、JnlpDownloadServlet
はその値をアプリケーションのタイムスタンプとして使用します。タイムスタンプが指定されていない場合、JnlpDownloadServlet
はファイルシステムの最終変更時間のタイムスタンプを使用します。
明示的なタイムスタンプを使用することは、負荷分散のために JNLP ファイルを複数のサーバーにコピーする場合に役立ちます。明示的なタイムスタンプにより、クライアントはどのサーバーを参照しても一貫した結果を得ることができます。
明示的なタイムスタンプを使用するには、JNLP ファイルの先頭に 1 行を追加します。この行は TS:
で始まります。この行の残り部分には、ISO 8601 形式のタイムスタンプを含める必要があります。その基本的な形式は次のとおりです。
YYYY-MM-DD hh:mm:ss
次に例を示します。
TS: 2010-08-07 21:19:05
タイムスタンプ文字列の詳細な説明については、「参照情報」セクションを参照してください。
JnlpDownloadServlet
は、2 つのドル記号で始まる文字列を置換します。たとえば、JNLP ファイルに次の行があるとします。
<jnlp spec="1.0+" codebase="$$codebase">
クライアントが JNLP ファイルを要求すると、配備されるたびに JnlpDownloadServlet
が $$codebase
を正しい値で置換します。この値を JNLP ファイルにハードコードする必要がなく、別のサーバーへの移行がより簡単になるため、これは便利です。
すべての置換のリストを次の表に示します。
名前 | 置換される値 |
---|---|
$$codebase |
JNLP ファイルの名前を除く、要求の URL |
$$name |
JNLP ファイルの名前 |
$$context |
Web アプリケーションのベース URL |
$$site |
Web サーバーのアドレス |
$$hostname |
サーバーの名前 |
たとえば、app2
の例が example.com
に配備されるとします。各置換の値は次のようになります。
名前 | 置換される値 |
---|---|
$$codebase |
http://example.com/app2/ |
$$name |
pie.jnlp |
$$context |
http://example.com/app2 |
$$site |
http://example.com |
$$hostname |
example.com |
app2/pie.jnlp
の例と app3/pie.jnlp
の例は $$codebase
のみを使用します。
JNLP 仕様では、明示的なバージョン番号を指定してアプリケーションリソースを要求することや、特定のロケール、オペレーティングシステム、システムアーキテクチャーのリソースを要求できます。つまり、オペレーティングシステムによってライブラリの異なるアプリケーションや、ロケールによってリソースファイルの異なるアプリケーションを配備できます。
JnlpDownloadServlet
は、特殊な要求を 2 つの異なるメカニズムでサポートします。1 つ目は、ロケールやオペレーティングシステムなどのパラメータをファイル名に埋め込む、リソースファイルの命名スキームです。2 つ目のメカニズムは、同じディレクトリ内のリソースファイルのパラメータを記述する XML ファイルを利用します。
JnlpDownloadServlet
では、ファイルに関する情報をファイル名に埋め込むことによって指定できます。ファイル名に 2 つ並んだ下線が含まれている場合、ファイル名は属性を含んでいると見なされます。接頭辞文字は、次のように属性の情報を指定します。
接頭辞 | 意味 |
---|---|
V |
バージョン番号 |
O |
オペレーティングシステム |
A |
アーキテクチャー |
L |
ロケール |
1 つのファイルにバージョンは 1 つだけ指定できますが、オペレーティングシステム、アーキテクチャー、またはロケール属性は複数関連付けることができます。たとえば、application__V1.2__Len_US__Len.jar は、リソース application.jar
のバージョンが 1.2
で、関連付けられたロケールが en_US
と en
であることを意味します。
たとえば、JNLP ファイルに次のリソース行があるとします。
<jar href="app-lib.jar" version="2.0" />
Java Web Start は、JNLP ファイルにこの行を見つけると、app-lib.jar
のバージョン 2.0 の要求をサーバーに送信します。Web アプリケーション内にファイル app-lib__V2.0.jar
が置かれている場合、JnlpDownloadServlet
はそれを app-lib.jar
のバージョン 2.0 としてクライアントに返します。Web アプリケーション内の実際のファイル名が再マッピングされ、app-lib.jar
としてクライアントに表示されることに注意してください。
ファイル命名規則は煩雑になることがあり、複数のリソースファイルが存在し、それぞれにオペレーティングシステム、アーキテクチャー、またはロケールが複数関連付けられている場合は特にそうなります。
JnlpDownloadServlet
は代替のメカニズムをサポートしており、そこではすべての属性が別の XML ファイルに記述されます。このサーブレットは、リソースと同じディレクトリで version.xml
ファイルを探します。version.xml
ファイルには、同じディレクトリ内のほかのファイルに関する情報が含まれています。
たとえば、次の version.xml
ファイルでは、クライアントには application.jar
として使用可能になるリソースが記述されています。実際のファイルは、同じディレクトリに application-1_2-us.jar
として格納されています。
<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>
app3
の例では、バージョン管理されたリソース要求に XML バージョンファイルを使用して応答する方法が示されています。特に、JNLP ファイルには次のリソース行があります。
<jar href="app-lib.jar" version="2.0" />
WAR ファイルには、ライブラリ、app-lib.jar
、およびライブラリを記述する次の XML バージョンファイル version.xml
が含まれています。
<jnlp-versions> <resource> <pattern> <name>app-lib.jar</name> <version-id>2.0</version-id> </pattern> <file>app-lib-2.0.jar</file> </resource> </jnlp-versions>
実際のファイル名 app-lib-2.0.jar
が再マッピングされ、クライアントに表示されるファイル名は app-lib.jar
となることに注意してください。
JnlpDownloadServlet
は、可能であれば JAR ファイルの増分更新を生成して返します。要求に current-version-id
パラメータが含まれている場合、このサーブレットが current-version-id
および要求されたバージョンの両方に一致するものを見つけることができ、かつ要求が JAR ファイルに対するものであれば、サーブレットによって JARDiff ファイルが生成されます。JARDiff ファイルは、そのサイズが要求されたバージョンのサイズよりも小さい場合に返されます。
生成された JARDiff ファイルは、Web コンテナに固有の一時ディレクトリに格納されます。サーブレットは、javax.servlet.context.tempdir
コンテキスト属性を使用して一時作業ディレクトリを見つけます。
Pack200 は、JAR ファイルの効率的な圧縮テクノロジです。アプリケーションのダウンロード時間とインストール時間は、ユーザーがアプリケーションをどのように感じるかを決定する重要な要因です。アプリケーションリソースをできるだけ小さくすると、ユーザーがアプリケーションのダウンロードを待たなければならない時間が短縮されます。
JnlpDownloadServlet
は、GZIP および Pack200 ダウンロードをサポートしているクライアント (Java Web Start など) にリソースを提供できます。*.jar.pack.gz
ファイルまたは *.jar.gz
ファイルを元の *.jar
ファイルとともにサーバー上に配置してください。たとえば、JnlpDownloadServlet
は、クライアントがサポートしているものに基づいて、次の中から最適なファイルを選択します。
pie.jar pie.jar.gz pie.jar.pack.gz
Pack200 ファイルは、Java Development Kit に含まれている pack200
ツールを使用して作成できます。app3
の例では、pie.jar
ファイルの Pack200 版が作成されます。Pack200 ファイルがどのように作成されるかを確認するには、build.xml
を調べてください。pie.jar
はシンプルなので Pack200 ファイルはごくわずかしか小さくなりませんが、より大きい JAR ファイルであれば、圧縮率ははるかに大きくなります。
JNLP の置換、Pack200 のサポート、およびファイル属性のサポートは、JnlpDownloadServlet
のもっとも有用な機能です。このサーブレットは、ロギングシステムおよび MIME タイプマッピングもサポートしています。
このサーブレットは、その動作を監視するためのログ機能を備えています。生成されるログメッセージは、次のカテゴリに分けられます。
FATAL
は、サーブレット内部で発生した機能不全エラーまたは内部エラーを示します。
WARNING
は、WAR ファイル内の情報の処理中または version.xml
ファイルの構文解析中に発生したエラーを示します。
INFORMATIONAL
は、すべての要求、応答、ディレクトリ走査などのログです。
DEBUG
は、要求がどのように処理されているかを示す詳細な内部情報を表示します。
ログ出力は、2 つのサーブレット初期化パラメータ logPath
と logLevel
によって制御されます。ログレベルは、NONE
、FATAL
、WARNING
、INFORMATIONAL
、DEBUG
のいずれかに設定できます。ログパスには、出力の書き込み先のファイルを指定します。パスを指定しない場合、ログはサーブレットの標準ログに書き込まれます (ServletContext.log()
を使用)。次はその例です。
<servlet> <servlet-name> JnlpDownloadServlet </servlet-name> <servlet-class> jnlp.sample.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>
サーブレットは、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 タイプが割り当てられます。
Extension | デフォルトの MIME タイプ |
---|---|
.jnlp |
application/x-java-jnlp-file |
.jar |
application/x-java-archive |
.jardiff |
application/x-java-archive-diff |
JnlpDownloadServlet
から返される MIME タイプを変更するには、web.xml
ファイルの <mime-type>
要素を使用します。次はその例です。
<web-app> ... <mime-mapping> <extension>jnlp</extension> <mime-type>text/ascii</mime-type> </mime-mapping> ... </web-app>
JnlpDownloadServlet
の構築
ほとんどの場合は JnlpDownloadServlet
をそのまま使用します。まれに、JnlpDownloadServlet
に機能を追加したい場合があります。完全なソースコードが提供されており、構築は比較的簡単です。
GNU make
と Java Development Kit (JDK) が必要で、環境変数を定義する必要があります。次は Linux システムでの例です。
$ export CLASS_PATH=/home/edmond/Applications/apache-tomcat-7.0.2/lib/servlet-api.jar $ export FILE_SEPARATOR=: $ export TMPDIR=/tmp $ export SDK_HOME=/home/edmond/jdk1.7.0 $ make . . .
構築によって出力されるのは lib/jnlp-servlet.jar
と lib/jardiff.jar
です。
一般的なタイムスタンプの形式は、次のとおりです。
YYYY-MM-DD hh:mm:ss
次に示すように、ダッシュ、コロン、および秒を付けずに記述することもできます。
YYYYMMDDhhmm
hh は 24 時間単位で表記します。デフォルトでは、ローカルタイムゾーンが使用されます。時間の最後に大文字の Z を追加することにより、UTC (世界標準時、GMT としても知られる) を指定することもできます。
23:59:59Z or 235959Z
文字列 +hh:mm
、+hhmm
、または +hh
を時間に追加することにより、ローカルタイムゾーンが UTC より hh
時間 mm
分進んでいることを指定できます。経度ゼロより西のタイムゾーン (UTC より遅れている) の場合は、代わりに -hh:mm
、-hhmm
、または -hh
という表記を使用します。たとえば、中央ヨーロッパ標準時 (CET) は +0100、米国およびカナダの東部標準時 (EST) は -0500 となります。次の文字列は、すべて同じ時間を指します。
12:00Z = 13:00+01:00 = 0700-0500
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)>