PR

前回,JavaからHTMLドキュメントに埋めこんだJavaScriptにアクセスし,HTMLドキュメントのDOMを操作する方法を紹介しました。しかし,DOM操作を行うにはJavaScriptで記述しなければなりません。

そこで,J2SE 1.4で導入されたのが,HTMLドキュメントのDOMを直接Javaから扱うことができるCommon DOM APIです。次世代Java Plug-inではCommon DOM APIも改善されています。ここでは,Common DOM APIの改善点だけでなく,Common DOM API全体について紹介します。

Common DOM API

Common DOM APIはJAXPで扱うDOM APIにHTML特有のインタフェースなどを加えたAPIです。

たとえば,HTMLドキュメントの全体を表すためにorg.w3c.dom.Documentインタフェースのサブインタフェースであるorg.w3c.dom.html.HTMLDocumentインタフェースなどが導入されています。

Documentオブジェクトの取得

DOMでXMLドキュメントを扱う場合,ドキュメントに対応するDocumentオブジェクトを取得する必要があります。

JAXPではDocumentオブジェクトの取得にjavax.xml.parsers.DocumentBuilder【http://java.sun.com/javase/ja/6/docs/ja/api/javax/xml/parsers/DocumentBuilder.html】クラスを使用します。しかし,アプレットが埋めこまれたHTMLドキュメントにはDocumentBuilderクラスは適用できません。

既存のCommon DOM APIでは,com.sun.java.browser.dom.DOOMServiceクラスを使用してきました。

たとえば,HTMLドキュメントのタイトルを取得するには次のように記述する必要がありました。

import javax.swing.JApplet;
import org.w3c.dom.html.HTMLDocument;
import com.sun.java.browser.dom.DOMAccessor;
import com.sun.java.browser.dom.DOMAction;
import com.sun.java.browser.dom.DOMService;
import com.sun.java.browser.dom.DOMUnsupportedException;
 
public class OldCommonDOMSample extends JApplet {
    @Override
    public void init() {
        try {
            // DOMServiceオブジェクトの取得
            DOMService service = DOMService.getService(this);
            
            service.invokeLater(new DOMAction() {
                public Object run(DOMAccessor accessor) {
                    // Document オブジェクトの取得
                    // 引数はアプレットオブジェクト
                    HTMLDocument doc 
                        = (HTMLDocument)accessor.getDocument(
                                        OldCommonDOMSample.this);
                                        
                    // タイトルを出力
                    System.out.println("Title: " + doc.getTitle());
 
                    return null;
                }
            });
        } catch (DOMUnsupportedException ex) {
            // 例外処理
        }
    }
}

このコードを見ただけで,ちょっと面倒だなということがわかります。

注目していただきたいのが,赤字で示したinvokeLaterメソッドです。他にinvokeLaterメソッドというメソッドを定義しているクラスにはjavax.swing.SwingUtilitiesクラスがあります。

Swingはイベントディスパッチスレッドだけで動作し,SwingUtilitiesクラスのinvokeLaterメソッドは他のスレッドからイベントディスパッチスレッドにアクセスするために使用するメソッドです。

つまり,ここでも同じことがいえるわけです。

HTMLドキュメントのDOMにアクセスするには特定のスレッドに限定されており,他のスレッドからDOMにアクセスするにはDOMServiceクラスのinvokeLaterメソッドもしくはinvokeAndWaitメソッドを使用する必要があるのです。

ところが,次世代Java Plug-inでは,同じ処理を次のように記述することができます。

import javax.swing.JApplet;
import org.w3c.dom.DOMException;
import org.w3c.dom.html.HTMLDocument;
 
import com.sun.java.browser.plugin2.DOM;
 
public class NewCommonDOMSample extends JApplet {
    @Override
    public void init() {
        try {
            // Document オブジェクトの取得
            HTMLDocument doc = (HTMLDocument)DOM.getDocument(this);
 
            // タイトルを出力
            System.out.println("Title: " + doc.getTitle());
        } catch (DOMException ex) {
            // 例外処理
        }
    }
}

大幅に簡略されたことがわかります。

Documentオブジェクトを取得するには,赤字で示したようにcom.sun.java.browser.plugin2.DOMクラスのgetDocumentメソッドを使用します。引数はアプレットオブジェクトです。

しかも,Documentオブジェクトの取得はアプレットのスレッドで行っています。つまり,以前のCommon DOM APIのようにDOMにアクセするスレッドが限定されずに,どのスレッドからでもDOMにアクセスできるようになったことを示しています。

なお,DOMクラスのgetDocumentメソッドの戻り値の型はDocumentインタフェースですが,実際にはHTMLドキュメント表すHTMLDocumentインタフェースが使用されます。

前述したように,HTMLDocumentインタフェースはDocumentインタフェースのサブインタフェースなので,getDocumentメソッドの戻り値をキャストします。