aqubi+shin1

Recent site activity

java‎ > ‎

TransformerFactory

XMLをXSLTするのに、Transformer クラスを使います。 これは TransformerFactoryクラスから 実装を取り出せます。 TransformerFactory.newInstance(); JDK1.4 では org.apache.xalan.processor.TransformerFactoryImpl JDK5.0 では com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl が返ってくるようです。JDK5.0になって com.sun パッケージの実装になってみたいですね。
・・・が、JDK5.0 でも xalan.jar をクラスパスに含めて実行すると、 org.apache.xalan.processor.TransformerFactoryImpl になります。 この理由は JDKのAPIDocにあります〜 APIドキュメントによると 探し出す手順は以下になります。
  1. javax.xml.transform.TransformerFactory システムプロパティを使用する 
  2. JRE ディレクトリ内のプロパティファイル lib/jaxp.properties を使用する。この構成ファイルは標準の java.util.Properties 形式であり、上記のように定義されたシステムプロパティであるキーを持つ実装クラスの完全指定の名前を含む
  3. 可能であれば、JAR 仕様で詳細に説明されているサービス API を使用して、クラス名を判定する。サービス API は、実行時に使用できる jar 内の META-INF/services/javax.xml.transform.TransformerFactory ファイルからクラス名を検索する
  4. プラットフォームのデフォルトの TransformerFactory インスタンス
xalan.jar の 中を見てみると・・・ ありますね、 META-INF/services/javax.xml.transform.TransformerFactory のファイルが。 この中身を見てみると org.apache.xalan.processor.TransformerFactoryImpl と記述されてます。
・・・これが有効になってたわけですね。 Factoryクラスによって、どの実装クラスを使うか? が指定できるのは便利な機能なんですが、それによって ハマることも。 たとえば、 tomcat5 上で 動かす Servlet にて Transformerをつかって XSLTしているプログラム。 JDK1.4でtomcatを動かすと、うまく動くのに、 JDK5.0でtomcatを動かすと、 Provider org.apache.xalan.processor.TransformerFactoryImpl not Found. ってエラーがでる。 ・・・・なーんて、悩んだ方いらっしゃるのでは? これまでの話で ピンっと来た人も多い? そぅ、この理由って tomcat自体が使っている TransformerFactoryの実装は org.apache.xalan.processor.TransformerFactoryImpl を使っていた からだと思います。 JDK1.4では、たまたま(?) 上記クラスが JDKの中に含まれていたので大丈夫でしたが、JDK5.0では 含まれていないので エラー になったんですね。 この場合の解決方法としては 大きく2種類。 一つ目は org.apache.xalan.processor.TransformerFactoryImpl がある xalan.jar とかを tomcat上のlibにいれちゃって、org.apacheパッケージを使うようにしちゃう。 二つ目は JDK5.0に含まれている com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl を使ってくれるような設定にしちゃう。 設定方法は JDKのAPIドキュメント通りなんですが、方法によりけりtomcatに影響があるかもしんない。 たとえば、システムプロパティに追加 System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"); って方法や JREのlib/jaxp.properties に追加する方法。 一応できるけど、システムプロパティに追加した時点で、tomcatを含むそのVM上の全てのプログラムに影響がいく? んじゃー無難な線として 作成したJARの META-INF/services/javax.xml.transform.TransformerFactory のファイルで com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl 指定しちゃう。 JDK1.4で動かされたときには アウト ですけどもね。。 JDK1.4、5.0両方で動作OKのものを作るためには・・・ ほんと妥協して Factoryクラスを使うんじゃなくて、使いたい Transformer クラスを自分でインスタンスしちゃう のが一番確実かもしんないなぁー