先週から次世代Java Plug-inのJNLPサポートについて紹介してきました。先週はJNLPを用いたアプレットのデプロイメントと実行について紹介しましたので,今週からJNLP APIについて紹介していきます。

実際にJNLP APIを紹介する前に,なぜJNLP APIが必要なのか考えてみましょう。

アプレットにはいろいろと制限があることは,よく知られています。例えば,次のアプレットをブラウザ上で実行してみましょう。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFileChooser;
 
// このアプレットは署名しないと
// アクセスコントロール例外が発生します
public class IllegalApplet extends JApplet {
    @Override
    public void init() {
        JButton button = new JButton("Open File...");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                // ファイルチューザを用いたファイルの選択
                JFileChooser chooser = new JFileChooser();
                int returnVal 
                    = chooser.showOpenDialog(IllegalApplet.this);
 
                if(returnVal == JFileChooser.APPROVE_OPTION) {
                    // ファイルを選択したら表示する
                    System.out.println(chooser.getSelectedFile());
                }
            }
        });
        add(button);
    }
}

このアプレットは本来ならボタンをクリックするとファイルチューザーダイアログを表示し,ファイルを選択できます。しかし,実際にボタンをクリックすると,以下のような例外が発生します。

Exception in thread "AWT-EventQueue-2" java.security.AccessControlException:
access denied (java.io.FilePermission C:\Users\sakuraba\Documents read)
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkRead(Unknown Source)
    at java.io.File.exists(Unknown Source)
    at java.io.Win32FileSystem.canonicalize(Unknown Source)
    at java.io.File.getCanonicalPath(Unknown Source)
    at sun.awt.shell.Win32ShellFolderManager2.createShellFolder(Unknown Source)
    at sun.awt.shell.Win32ShellFolderManager2.getPersonal(Unknown Source)
    at sun.awt.shell.Win32ShellFolderManager2.get(Unknown Source)
    at sun.awt.shell.ShellFolder.get(Unknown Source)
    at javax.swing.filechooser.FileSystemView.getDefaultDirectory(Unknown Source)
    at javax.swing.JFileChooser.setCurrentDirectory(Unknown Source)
    at javax.swing.JFileChooser.(Unknown Source)
            <<以下,省略>>

これはファイルチューザがローカルのファイルにアクセスするために発生した例外です。

アプレットはサンドボックスと呼ばれる制限された環境の中で動作するため,このような例外が発生します。サンドボックスで制限される機能には,ローカルリソースへのアクセスなどがあります。

このような制限を解除するには,VeriSignなどの認証局から証明書を取得し,その証明書を使用してJARファイルを署名することが必要です。しかし,証明書の取得は無料ではありませんし,それなりに手間のかかることです。

そこで,JNLPでは,ユーザーに注意を喚起し,了解をえたうえで,特定の制限を部分的に緩めるAPIが定義されました。それが,JNLP APIです。

JNLP API自体はこれまでJava Web Startで使用されてきました。しかし,Java Web Startが使われている例は少なく,JNLP APIの解説もあまりありません。そこで,新しいAPIではないのですが,本連載で紹介することにしました。

JNLP APIが提供している機能はサービスと呼び,表1にあげる10種類が提供されています。

表1●JNLP APIが提供するサービス
インタフェース名 説明
BasicService コードベースの取得などを行うサービス
FileOpenService ファイルチューザを使用したファイルのオープンを行うサービス
FileSaveService ファイルチューザを使用したファイルの保存を行うサービス
ExtendedService 指定されたファイルをオープンするサービス
ClipboardService システムクリップボードにアクセスするサービス
PrintService 印刷機能にアクセスするサービス
PersistenceService アプリケーション固有データへのアクセスを行うサービス
SingleInstanceService アプレットをシングルトンとして登録するサービス
DownloadService JARファイルなどのリソースを制御するサービス
ExtensionInstallerService 拡張インストーラが使用するサービス

これらのサービスはすべてインタフェースとして定義され,いずれもjavax.jnlpパッケージに含まれています。また,これらのクラスは標準のクラスライブラリとは分けられており,JREがインストールされたディレクトリの直下のlibディレクトリにあるjavaws.jarファイルに含まれています。このため,JNLP APIを使用したアプレットをコンパイルする時には,クラスパスにjavaws.jarファイルを含める必要があります。

最後のExtensionInstallerServiceクラスは,プラットフォームに依存するネイティブライブラリーなどをインストールする時に使用する拡張インストーラで使用するため,アプレットで使用することはありません。また,拡張インストーラを使用することは稀であることから,本連載では解説を省略させていただきます。