2011-01-13 5 views
3

저는 Spring-WS에서 OXM을 수행하기 위해 JAXB2를 사용하고 있습니다. 내가 지정한 XSD는 비누 메시지에 큰 XML 파일을 첨부해야하므로 MTOM을 사용하여 파일을 전송하고 JAXB2Marshaller에서 MTOM을 활성화했습니다.BOM에 의해 JAXB2 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은 유니 코드 표준에서 허용하는 UTF-8 인코딩 파일에 필요하지 않지만 Java는 UTF-8 인코딩 된 스트림의 BOM을 지원하지 않습니다.

BOM없이 파일을 보내이 문제를 해결할 수 있지만 BOM을 삽입하는 대부분의 Microsoft 제품에서 문제가 발생할 수 있으므로 실제로는 가능하지 않습니다.

Sun/Oracle이 스트림에서이 문제를 해결하지 못하게하는 많은 해결 방법이 있지만 스트림에 대한 액세스 권한이 필요합니다. JAXB2에서 제공하는 소스 객체에는 Reader 객체 만있는 InputStream이 없습니다. . UTF-8 인코딩으로 BOM을 무시하는 방법을 알고 있거나 무시할 수 있도록 JAXB2가 소스로 첨부 파일을 읽는 방법을 변경하는 방법을 알고있는 판독기로 Source Reader 객체를 래핑하여이 문제를 해결할 수있는 방법이 있습니까? UTF-8 인코딩의 BOM 사전에

감사합니다, 크레이그

답변

3

는 트릭을 "마크"리더입니다.

옵션 # 1 - BOM를 확인하고 내 원본을 믿고 그것을

를 제거 : 당신의 독자가 표시 지원하지 않는 경우에는 않는 BufferedReader로 그것을 포장 할 수 있습니다 코드가 BOM을 잘못 작성했습니다. 소스 코드는 아래에 더 의미가 있습니다 :

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

시도해 주셔서 감사합니다. Unfortunatly 이미 시도했지만 작동하지 않습니다. 내 소스에 들어있는 독자가 마크를 구현하지 않습니다. –

+0

BufferedReader가 재생되는 곳입니다. 이 기능을 사용하려면 Reader를 BufferedReader로 래핑 할 수 있습니다. http://download.oracle.com/javase/6/docs/api/java/io/BufferedReader.html#markSupported%28%29 –