2011-01-13 7 views
3

私はSpring-WSでOXMを行うためにJAXB2を使用しています。私が指定したXSDは、大きなXMLファイルをSOAPメッセージに添付する必要があります。そのため、MTOMを使用してファイルを転送し、JAXB2MarshallerでMTOMを有効にしています。JAXB2 BOMで壊れたMtom添付ファイル

期待されるmimeタイプのtext/xmlを持つMTOM添付ファイルを整列すると、JAXB2はその要素をjavax.xml.transform.Sourceオブジェクトとして配信します。いくつかの検索の後、私はそのSourceオブジェクトをどのようにファイルに送ることができるかを知ることができました。

final Source source = request.getSource(); 
StreamSource streamSource = (StreamSource) source; 
TransformerFactory factory = TransformerFactory.newInstance(); 
Transformer transformer = factory.newTransformer(); 
File file = new File ("/tempxmlfile.xml"); 
try{ 
    transformer.transform(streamSource, new StreamResult(file)); 
    LOG.info("File saved in "+file.getAbsolutePath()); 
    } 
catch(Exception ex){ 
     ex.getMessage(); 
    } 

私が午前問題は、私は添付ファイルとしてUTF-8でエンコードされたファイルを送信するとき、私は次のエラーを取得することです:

[Fatal Error] :1:1: Content is not allowed in prolog. 
ERROR: 'Content is not allowed in prolog.' 

これは前にバイトオーダーマークによって引き起こされていますこのBOMはUnicode標準で許可されているUTF-8エンコードファイルでは必要ありませんが、JavaはUTF-8エンコードストリームでBOMをサポートしていません。

この問題は、BOMのないファイルを送信することで解決できますが、BOMを挿入するほとんどのMicrosoft製品で問題が発生するため、これは実際には実現できません。

この問題をStreamsで修正することを拒否する回避策はたくさんありますが、Streamsにアクセスする必要があります.Source/Oracleが提供するSource ObjectにはReaderオブジェクトのみのInputStreamがありません。この問題を解決する方法はありますか?UTF-8エンコーディングでBOMを無視する方法を知っている読者にSources Readerオブジェクトをラップするか、またはJAXB2がソースに添付ファイルを読み込んで無視できるようにする方法を変更するUTF-8エンコーディングのBOM事前に

おかげで、 クレイグ

答えて

3

トリックは「マーク」リーダーです。

オプション#1 - BOMを確認し、私は私の元を信じてそれに

を取り除く:あなたの読者がマーキングをサポートしていない場合、あなたはありませんBufferedReaderの中でそれをラップすることができますコードがBOMを正しく書いていませんでした。あなたがマーク/リセット活用 '<を' ヒットするまで、そのPoint

読むに検索] < 'とアドバンスリーダー -

import java.io.*; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

    private static char[] UTF32BE = {0x00, 0x00, 0xFE, 0xFF}; 
    private static char[] UTF32LE = {0xFF, 0xFE, 0x00, 0x00}; 
    private static char[] UTF16BE = {0xFE, 0xFF}; 
    private static char[] UTF16LE = {0xFF, 0xFE}; 
    private static char[] UTF8 = {0xEF, 0xBB, 0xBF}; 

    public static void main(String[] args) throws Exception { 
     // Create an XML document with a BOM 
     FileOutputStream fos = new FileOutputStream("bom.xml"); 
     writeBOM(fos, UTF16LE); 

     OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8"); 
     oswUTF8.write("<root/>"); 
     oswUTF8.close(); 

     // Create a Source based on a Reader to simulate source.getRequest() 
     StreamSource attachment = new StreamSource(new FileReader(new File("bom.xml"))); 

     // Wrap reader in BufferedReader so it will support marking 
     Reader reader = new BufferedReader(attachment.getReader()); 

     // Remove the BOM 
     removeBOM(reader); 

     TransformerFactory tf = TransformerFactory.newInstance(); 
     Transformer t = tf.newTransformer(); 
     t.transform(new StreamSource(reader), new StreamResult(System.out)); 
    } 

    private static void writeBOM(OutputStream os, char[] bom) throws Exception { 
     for(int x=0; x<bom.length; x++) { 
      os.write((byte) bom[x]); 
     } 
    } 

    private static void removeBOM(Reader reader) throws Exception { 
     if(removeBOM(reader, UTF32BE)) { 
      return; 
     } 
     if(removeBOM(reader, UTF32LE)) { 
      return; 
     } 
     if(removeBOM(reader, UTF16BE)) { 
      return; 
     } 
     if(removeBOM(reader, UTF16LE)) { 
      return; 
     } 
     if(removeBOM(reader, UTF8)) { 
      return; 
     } 
    } 

    private static boolean removeBOM(Reader reader, char[] bom) throws Exception { 
     int bomLength = bom.length; 
     reader.mark(bomLength); 
     char[] possibleBOM = new char[bomLength]; 
     reader.read(possibleBOM); 
     for(int x=0; x<bomLength; x++) { 
      if(bom[x] != possibleBOM[x]) { 
       reader.reset(); 
       return false; 
      } 
     } 
     return true; 
    } 

} 

オプション#2:

を以下のソースコードは、より理にかなっています
import java.io.*; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 

public class Demo2 { 

    private static char[] UTF32BE = {0x00, 0x00, 0xFE, 0xFF}; 
    private static char[] UTF32LE = {0xFF, 0xFE, 0x00, 0x00}; 
    private static char[] UTF16BE = {0xFE, 0xFF}; 
    private static char[] UTF16LE = {0xFF, 0xFE}; 
    private static char[] UTF8 = {0xEF, 0xBB, 0xBF}; 

    public static void main(String[] args) throws Exception { 
     // Create an XML document with a BOM 
     FileOutputStream fos = new FileOutputStream("bom.xml"); 
     writeBOM(fos, UTF16BE); 

     OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8"); 
     oswUTF8.write("<root/>"); 
     oswUTF8.close(); 

     // Create a Source based on a Reader to simulate source.getRequest() 
     StreamSource attachment = new StreamSource(new FileReader(new File("bom.xml"))); 

     // Wrap reader in BufferedReader so it will support marking 
     Reader reader = new BufferedReader(attachment.getReader()); 

     // Remove the BOM 
     removeBOM(reader); 

     TransformerFactory tf = TransformerFactory.newInstance(); 
     Transformer t = tf.newTransformer(); 
     t.transform(new StreamSource(reader), new StreamResult(System.out)); 
    } 

    private static void writeBOM(OutputStream os, char[] bom) throws Exception { 
     for(int x=0; x<bom.length; x++) { 
      os.write((byte) bom[x]); 
     } 
    } 

    private static Reader removeBOM(Reader reader) throws Exception { 
     reader.mark(1); 
     char[] potentialStart = new char[1]; 
     reader.read(potentialStart); 
     if('<' == potentialStart[0]) { 
      reader.reset(); 
      return reader; 
     } else { 
      return removeBOM(reader); 
     } 
    } 

} 
+0

char定数に16進数の代わりに10進数を使用すると、* icky *です。 – dkarp

+0

試してみてくれてありがとうございました、残念ながら私はすでにこれを試してみましたが、うまくいきません。私のソースには読者がマークを実装していません。 –

+0

これは、BufferedReaderが再生する場所です。 ReaderをBufferedReaderでラップして、この機能を利用できます。http://download.oracle.com/javase/6/docs/api/java/io/BufferedReader.html#markSupported%28%29 –

関連する問題