Java から JavaScript への通信



このセクションでは、次のトピックについて説明します。

はじめに

Java Plug-in は、2 つの方法で DOM にアクセスできます。1 つは JSObject を、もう 1 つは共通 DOM API を介してアクセスを行う方法です。それぞれの方法およびセキュリティ上の考慮事項について、以下で説明します。

JSObject

Java アプレットは、Java から JavaScript への通信を行って Document Object Model (DOM) にアクセスするか、HTML ページ上で JavaScript 関数を呼び出す必要があります。ブラウザを使用すると、Java ラッパークラス netscape.javascript.JSObject を介した Java と JavaScript 間の通信が可能になります。詳細は、「Java Packages for LiveConnect」を参照してください。

ブラウザ間で DOM 実装が異なるため、Java Plug-in が提供する JSObject サポートは、Internet Explorer と Navigator で異なります。このドキュメントでは、異なるブラウザ環境で JSObject サポートがどのように機能するかを説明します。

JSObject の動作方法

JSObject を利用すると、HTML ページの DOM へのアクセスが容易になります。ただし、ブラウザが異なると DOM の実装方法も異なるため、Java アプレットで JSObject を使用すると、Java Plug-in の動作がブラウザによって異なる場合があります。特定のブラウザでの DOM 実装の詳細は、ブラウザの開発者ガイドを参照してください。

一般に、アプレットは次の方法で JSObject にアクセスします。

import netscape.javascript.*;
import java.applet.*;
import java.awt.*;
class MyApplet extends Applet {
     public void init() {
         JSObject win = JSObject.getWindow(this);
         JSObject doc = (JSObject) win.getMember("document");
         JSObject loc = (JSObject) doc.getMember("location");

         String s = (String) loc.getMember("href");  // document.location.href
         win.call("f", null);                      // Call f() in HTML page
     }
}

開始位置は、static メソッドです。

public static JSObject getWindow(Applet a) 

このメソッドにより、指定されたアプレットを含む Window を表す JSObject が返されます。このメソッドは、パラメータとして java.applet.Applet のみを取るため、アプレットから JSObject にアクセスできますが、Bean がアプレットでない限り、Bean からアクセスすることはできません。

Window オブジェクトの取得が完了したら、アプレットは次のメソッドを使用して HTML ページの DOM をナビゲートできます。

Java Plug-in では、getWindow()call()eval()setMember()、および getMember() だけを使用することをお勧めします。getSlot()setSlot()removeMember()、および toString() の実装はブラウザに依存するため、実行結果は、Java Plug-in が稼動しているブラウザのバージョンおよびプラットフォームにより異なります。

JSObject の使用方法の詳細は、「LiveConnect」ページの「Java to JavaScript Communication」セクションを参照してください。

Java コードをコンパイルして JSObject を利用するには、CLASSPATH 内に netscape.javascript パッケージを保持する必要があります。現在のところ、Java Plug-in 1.3 では、JAR ファイル JAWS.JAR 内に netscape.javascript が含まれています。JSObject を使用するアプレットをコンパイルするには、コンパイルする前に、CLASSPATHJAWS.JAR を追加する必要があります。

JSObject は、Java Plug-in ではサポートされますが、Java 2 プラットフォームの AppletViewer ではサポートされないことに留意してください。このため、JSObject を使用するアプレットは、AppletViewer では動作しないか、例外が発生します。

Java Plug-in での JSObject サポートの程度

Internet Explorer:

COM 経由で DOM にアクセスすることにより、Java Plug-in は IE での JSObject をフルサポートします。

Netscape Navigator:

Netscape の Plug-in API 経由で DOM にアクセスすることにより、Java Plug-in は、Navigator 4 での JSObject を限定的にサポートします。Navigator 4 では、JSObject を介して次の JavaScript オブジェクトにアクセスできます。

他の JavaScript オブジェクトは Netscape 4 ではサポートされておらず、JSObject を介してそういったオブジェクトにアクセスしようとすると、Java の例外が発生します。こうした制約は Netscape 6 には該当しないので、Netscape 6 では JSObject はフルサポートされます。

注: 異なるブラウザが同じ JavaScript オブジェクトをサポートするとしても、サポートされるオブジェクトのメソッドおよびプロパティが異なる場合があります。使用するブラウザの JavaScript 開発者ガイドを参照してください。

Java Plug-in での JSObject サポートの有効化

セキュリティ上の理由で、Java Plug-in の JSObject サポートは、デフォルトでは無効に設定されています。Java Plug-in の JSObject サポートを有効にするには、次に示すように、EMBED/OBJECT タグ内に新規属性 MAYSCRIPT が存在する必要があります。

元の APPLET タグ:

<APPLET code="XYZApp.class" codebase="html/" align="baseline"
     width="200" height="200" MAYSCRIPT>
<PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
     No JDK 1.3 support for APPLET!!
</APPLET>

新規 OBJECT タグ:

<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
     width="200" height="200" align="baseline"
     codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0">
     <PARAM NAME="code" VALUE="XYZApp.class">
     <PARAM NAME="codebase" VALUE="html/">
     <PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
     <PARAM NAME="MAYSCRIPT" VALUE="true">
     <PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
        No JDK 1.3 support for APPLET!!
</OBJECT>

新規 EMBED タグ:

<EMBED type="application/x-java-applet;version=1.3" width="200"
   height="200" align="baseline" code="XYZApp.class"
   codebase="html/" model="models/HyaluronicAcid.xyz" MAYSCRIPT=true
   pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html">
<NOEMBED>
   No JDK 1.3 support for APPLET!!
</NOEMBED>
</EMBED>

MAYSCRIPT が false に指定されているか、MAYSCRIPT が存在しない場合、JSObject は無効になります。EMBED/OBJECT タグ内の MAYSCRIPT 属性の詳細は、「Java Plug-in での OBJECTEMBED、および APPLET タグの使用」を参照してください。
          

共通 DOM API

概要

ここでは、Java Plug-in 1.4 の共通 DOM API について説明します。この API は、さまざまなプラットフォームで稼動する異なるブラウザベンダーのブラウザに対して、ブラウザ内の DOM にアクセスするための標準 API を提供します。

注:

Internet Explorer 6 と Netscape 6 ではフルサポートされていますが、ほかのブラウザでのサポートは制限されています。

この API は、Document Object Model (DOM) Level 2 勧告に基づいて構築されています (さまざまな w3c 勧告の詳細は、http://www.w3.org/DOM/ を参照してください)。Document Object Model (DOM) は、IDL (Interface Definition Language) を使用して定義されたインタフェースセットで、Java 言語バインディングが含まれます。

共通 DOM API には、w3c で定義された、次のインタフェースパッケージが含まれます。

DOMService

共通 DOM クラスを使用すると、org.w3c.dom および org.w3c.dom.html パッケージ内の API を介して、アプリケーションから基盤となるブラウザの DOM にアクセスできます。

各 DOM は、ブラウザ内の単一の XML/HTML ドキュメントの基盤表現を表します。各ブラウザは、ブラウザのフレーム/ウィンドウに複数の XML/HTML ドキュメントを表示できます。このため、アプリケーションが共通 DOM クラスを介して DOM へのアクセスを要求した場合、重要なのはアプリケーションに関連付けられた DOM を返すことです。アプリケーションに関連付けられた適切な DOM を取得するため、Java オブジェクトが DOMService.getService() に渡されます。DOMService は、オブジェクトに関連付けられた適切な DOMService 実装を返します。それ以外の場合、例外がスローされます。通常、Java オブジェクトは、アプレットまたは JavaBeans コンポーネントです。ただし、この仕様は、DOMServiceProvider が他の Java オブジェクトタイプを処理可能である場合、その使用を除外するものではありません。

DOM に対する操作を実行するには、DOMAction を実装するオブジェクトを DOMService.invokeAndWait() または DOMService.invokeLater() に渡す必要があります。次に、DOMAction.run() が、DOM アクセスをディスパッチするスレッド上で実行されます。

次に、Document オブジェクトのタイトルを取得する簡単な例を示します。

DOMService service = null;

try
{
    service = DOMService.getService(MyApplet);
    String title = (String) service.invokeAndWait(new DOMAction()
                            {
                                public Object run(DOMAccessor accessor)
                                {
                                     HTMLDocument doc = (HTMLDocument) accessor.getDocument(MyApplet);
                                     return doc.getTitle();
                                }
                            });
}
catch (DOMUnsupportedException e1)
{
}
catch (DOMAccessException e2)
{
}

DOMService Plugability

複数の DOMServiceProvider, が存在するため、DOMServiceProvider 実装の共通 DOM クラスへのプラグインをサードパーティに許可することは重要です。これを実現するため、新規 Java プロパティ com.sun.browser.dom.DOMServiceProvider が定義されています。

このプロパティを定義する場合、DOMServiceProvider 実装のクラス名のリストを含める必要があります。各クラス名は、「|」文字で区切ります。

DOMService.getService() の呼び出し時に、com.sun.browser.dom.DOMServiceProvider により指定された DOMServiceProvider 実装が 1 つずつ、プロパティで指定された順序に従って呼び出され、プロバイダがオブジェクトの DOM への関連付けを判別可能かどうかが確認されます。2 つの DOMServiceProvider が同一のオブジェクトを処理可能な場合、プロパティ内で最初に指定されたプロバイダが使用されます。

スレッドに対する安全性

各ブラウザの DOM は実装方法が異なるため、DOM アクセス時のスレッドの安全性は期待されていません。この仕様の DOM オブジェクト実装へのアクセスは、スレッドの安全性を確保するため、DOM アクセスをディスパッチするスレッドのみに制限する必要があります。これを実現するため、DOM オブジェクトにアクセスするコードのスコープを、DOMAction.run() ブロック内に限定する必要があります。操作を呼び出す場合、DOM アクセスをディスパッチするスレッドで DOMAction.run() が実行されるよう、DOMService.invokeAndWait() または DOMService.invokeLater() を使用する必要があります。

DOM オブジェクトの実装を DOMAction.run() ブロック外部で呼び出してはなりませんが、アプリケーションはこれらの DOM オブジェクトをクラスのインスタンスメンバとしてキャッシュしたり、スレッド間でこれらの DOM オブジェクトを渡す場合があります。ただし、DOM オブジェクトを任意のオブジェクトの static メンバとしてキャッシュすることは禁止されています。これは、static メンバが、基盤となる DOM オブジェクトのライフサイクル以上の期間存在する可能性があるためです。

任意のスレッドから呼び出し可能な共通 DOM クラス内の唯一のオブジェクトは、DOMService です。共通 DOM クラス内の他のオブジェクトへのアクセスは、DOMAction.run() ブロック内に制限されています。それ以外の操作を行うと、例外がスローされます。

セキュリティ

ブラウザ DOM は、ブラウザ内のすべてのサービスへのアクセスを提供します。このため、DOM への各呼び出し時に、セキュリティが適正にチェックされていることを確認するのは大切です。DOMService.invokeAndWait() または DOMService.invokeLater() が呼び出されると、呼び出し側のセキュリティコンテキストの捕捉が行われます。その後、対応する DOMAction.run() が DOM アクセスをディスパッチするスレッドで実行されると、DOM オブジェクト実装の呼び出し時に、呼び出し側のセキュリティコンテキストがブラウザ DOM に渡されます。元の呼び出し側が DOM へのアクセスに必要な権限を保持していない場合、DOMAccessException がスローされます。

DOM アクセスのセキュリティポリシーは、ブラウザにより異なります。このため、Java アプリケーションが署名され、完全に信頼されていても、ブラウザ内の DOM オブジェクトへのアクセスで DOMAccessException がスローされる場合があります。

DOM オブジェクトの寿命

DOM オブジェクトの実装は、ブラウザ DOM 内で実際の基盤をなすオブジェクトを表します。XML/HTML ドキュメントは瞬時に変化するため、Java の DOM オブジェクトが有効ではなくなっている可能性があります。無効な DOM オブジェクトへのアクセスが行われると、W3C DOM Level 2 仕様に従って、org.w3c.dom.DOMException がスローされます。DOMAction.run() 内の DOM オブジェクトにアクセスするコードを記述する開発者は、いつも DOM オブジェクトが有効であると見なすべきではありません。

適合性要件

この仕様を実装するサードパーティは、com.sun.browser.dom パッケージ内の共通 DOM クラスの実装を提供する必要があります。W3C DOM Level 2 API の実装は、W3C DOM Level 2 仕様にも適合している必要があります。ただし、ブラウザによって、実装している W3C DOM API のサブセットが異なる場合があるため、サードパーティは、すべての org.w3c.dom および org.w3c.dom.html クラスの実装を提供する必要はありません。

パッケージ com.sun.browser.dom

このセクションでは、com.sun.browser.dom パッケージの API を定義します。

public abstract class DOMService       

DOMService が定義するサービス API は、アプリケーションに対し、document オブジェクトへのアクセスを可能にします。この document オブジェクトは、アプリケーションを埋め込むブラウザ window の基盤となる DOM を表します。

public abstract class DOMService 
{
        /**
         * Returns new instance of a DOMService.The implementation
         * of the DOMService returns depending on the setting of the
         * javax.browser.dom.DOMServiceProvider property or, if the
         * property is not set, a platform-specific default.
         * 
         * Throws DOMUnsupportedException if the DOMService is not 
         * available to the obj.
         *
         * @param obj Object to leverage the DOMService
         */
        public static DOMService getService(Object obj) throws DOMUnsupportedException;

        /**
         * An empty constructor is provided.Implementations of this
         * abstract class must provide a protected no-argument constructor
         * in order for the static getService() method to work correctly.        
         * Application programmers should not be able to directly
         * construct implementation subclasses of this abstract subclass.
         */
        protected DOMService();

        /**
         * Causes action.run() to be executed synchronously on the 
         * DOM action dispatching thread.This call will block until all 
         * pending DOM actions have been processed and (then) 
         * action.run()
returns.This method should be used when an 
         * application thread needs to access the browser's DOM. 
         * It should not be called from the DOMActionDispatchThread
         * 
         * Note that if the DOMAction.run() method throws an uncaught 
         * exception (on the DOM action dispatching thread), it's caught 
         * and re-thrown as an DOMAccessException on the caller's thread.
         * 
         * @param action DOMAction.
         */    
        public abstract Object invokeAndWait(DOMAction action) throws DOMAccessException;

        /**
         * Causes action.run() to be executed asynchronously on the 
         * DOM action dispatching thread.This method should be used 
         * when an application thread needs to access the browser's 
         * DOM.It should not be called from the DOMActionDispatchThread
         *
         * Note that if theDOMAction.run() method throws an uncaught 
         * exception (on the DOM action dispatching thread),  it will not be
         * caught and re-thrown on the caller's thread.
         * 
         * @param action DOMAction.
         */    
        public abstract void invokeLater(DOMAction action);
}

上記の getService(Object obj) メソッド内の Object obj は、アプレットまたは Bean です。

public abstract class DOMServiceProvider

public abstract class DOMServiceProvider のインスタンスを実装すると、指定された Java オブジェクト用の基盤となるブラウザ DOM へのアクセスが可能になります。DOMServiceProvider のインスタンスを、アプリケーションから直接取得してはなりません。

public abstract class DOMServiceProvider
{
        /**
         * An empty constructor is provided.Implementations should 
         * provide a protected constructor so that the DOMService
         * can instantiate instances of the implementation class. 
         * Application programmers should not be able to directly
         * construct implementation subclasses of this abstract subclass.
         * The only way an application should be able to obtain a 
         * reference to a DOMServiceProvider implementation
         * instance is by using the appropriate methods of the
         * DOMService.
         */
        protected DOMServiceProvider();

        /**
         * Returns true if the DOMService can determine the association
         * between the obj and the underlying DOM in the browser.
         */
        public abstract boolean canHandle(Object obj);

        /**
         * Returns the Document object of the DOM.
         */
        public abstract org.w3c.dom.Document getDocument(Object obj) throws DOMUnsupportedException;

        /**
         * Returns the DOMImplemenation object of the DOM.
         */
        public abstract org.w3c.dom.DOMImplementation getDOMImplementation();
}

canHandle(Object obj) メソッドおよび getDocument(Object obj) メソッドの Object obj は、アプレットまたは Bean です。

public interface DOMAccessor

DOMAccessor は、ブラウザ DOM のエントリポイントにアクセスするために、DOMAction.run() 内で使用可能なインタフェースを表します。

public interface DOMAccessor
{
        /**
         * Returns the Document object of the DOM.
         */
        public org.w3c.dom.Document getDocument(Object obj) throws org.w3c.dom.DOMException;

        /**
         * Returns a DOMImplementation object.
         */
        public org.w3c.dom.DOMImplementation getDOMImplementation();

上記の getDocument(Object obj) メソッド内の Object obj は、アプレットまたは Bean です。

public interface DOMAction

DOMAction は、ブラウザの DOM で実行されるアプリケーション操作すべてをカプセル化します。

public interface DOMAction
{
        /**
         * When an object implementing interface DOMAction is passed
         * to DOMService.invokeAndWait() or DOMService.invokeLater(),
         * the run method is called in the DOM access dispatch thread.
         *
         * accessor is used for the DOMAction to access the entry point of 
         * the browser's DOM, if necessary.
         *
         * @param accessor DOMAccessor
         */
        public Object run(DOMAccessor accessor);
}

public class DOMUnsupportedException

この例外は、Java オブジェクトと DOM 間の関連性が見つからない場合、DOMService.getService() および DOMServiceProvider.getDocument() によりスローされます。

public class DOMUnsupportedException extends Exception
{    
        /**
         * Constructs a new DOMUnsupportedException with no detail message.
         */               
        public DOMUnsupportedException();

        /**
         * Constructs a new DOMUnsupportedException with the given detail message.
         *
         * @param msg Detail message.
         */               
        public DOMUnsupportedException(String msg);

        /**
         * Constructs a new DOMUnsupportedException with the given exception as a root clause.
         *
         * @param e Exception.
         */               
        public DOMUnsupportedException(Exception e);

        /**
         * Constructs a new DOMUnsupportedException with the given exception as a root clause and the given          * detail message.
         *
         * @param e Exception.
        * @param msg Detail message.
         */               
        public DOMUnsupportedException(Exception e, String msg);

        /**
         * Returns the detail message of the error or null if there is no detail message.
         */               
        public String getMessage();

        /**
         * Returns the root cause of the error or null if there is none.
         */               
        public Exception getException();   
}           

public class DOMAccessException

DOMAction.run() の内部でいずれかの DOM オブジェクトへのアクセスが行われた場合、その DOM オブジェクトが例外をスローすると、DOMService.accessAndWait() によりこの例外がスローされます。

public class DOMAccessException  extends Exception
{    
        /**
         * Constructs a new DOMAccessException with no detail message.
         */               
        public DOMAccessException();

        /**
         * Constructs a new DOMAccessException with the given detail message.
         *
         * @param msg Detail message.
         */               
        public DOMAccessException(String msg);

        /**
         * Constructs a new DOMAccessException with the given exception as a root clause.
         *
         * @param e Exception.
         */               
        public DOMAccessException(Exception e);

        /**
         * Constructs a new DOMAccessException with the given exception as a root clause and the given          * detail message.
         *
         * @param e Exception.
        * @param msg Detail message.
         */               
        public DOMAccessException(Exception e, String msg);

        /**
         * Returns the detail message of the error or null if there is no detail message.
         */               
        public String getMessage();

        /**
         * Returns the root cause of the error or null if there is none.
         */               
        public Exception getException();   
}