< prev index next >

jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -24,19 +24,20 @@
  */
 
 package com.sun.xml.internal.bind.v2.runtime.output;
 
 import java.io.IOException;
+import java.io.Writer;
 import java.lang.reflect.Constructor;
 
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
+import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
 
-import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
 import org.xml.sax.SAXException;
 
 /**
  * {@link XmlOutput} that writes to StAX {@link XMLStreamWriter}.
  * <p>

@@ -51,11 +52,11 @@
 
     /**
      * Creates a new {@link XmlOutput} from a {@link XMLStreamWriter}.
      * This method recognizes an FI StAX writer.
      */
-    public static XmlOutput create(XMLStreamWriter out, JAXBContextImpl context) {
+    public static XmlOutput create(XMLStreamWriter out, JAXBContextImpl context, CharacterEscapeHandler escapeHandler) {
         // try optimized path
         final Class writerClass = out.getClass();
         if (writerClass==FI_STAX_WRITER_CLASS) {
             try {
                 return FI_OUTPUT_CTOR.newInstance(out, context);

@@ -67,21 +68,30 @@
                 return STAXEX_OUTPUT_CTOR.newInstance(out);
             } catch (Exception e) {
             }
         }
 
+        CharacterEscapeHandler xmlStreamEscapeHandler = escapeHandler != null ?
+                escapeHandler : NewLineEscapeHandler.theInstance;
+
         // otherwise the normal writer.
-        return new XMLStreamWriterOutput(out);
+        return new XMLStreamWriterOutput(out, xmlStreamEscapeHandler);
     }
 
 
     private final XMLStreamWriter out;
 
+    private final CharacterEscapeHandler escapeHandler;
+
+    private final XmlStreamOutWriterAdapter writerWrapper;
+
     protected final char[] buf = new char[256];
 
-    protected XMLStreamWriterOutput(XMLStreamWriter out) {
+    protected XMLStreamWriterOutput(XMLStreamWriter out, CharacterEscapeHandler escapeHandler) {
         this.out = out;
+        this.escapeHandler = escapeHandler;
+        this.writerWrapper = new XmlStreamOutWriterAdapter(out);
     }
 
     // not called if we are generating fragments
     @Override
     public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {

@@ -135,11 +145,11 @@
     }
 
     public void text(String value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
         if(needsSeparatingWhitespace)
             out.writeCharacters(" ");
-        out.writeCharacters(value);
+        escapeHandler.escape(value.toCharArray(), 0, value.length(), false, writerWrapper);
     }
 
     public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
         if(needsSeparatingWhitespace)
             out.writeCharacters(" ");

@@ -205,6 +215,83 @@
         } catch (Throwable e) {
             return null;
         }
     }
 
+    /**
+     * Performs character escaping only for new lines.
+     */
+    private static class NewLineEscapeHandler implements CharacterEscapeHandler {
+
+        public static final NewLineEscapeHandler theInstance = new NewLineEscapeHandler();
+
+        @Override
+        public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
+            int limit = start+length;
+            int lastEscaped = start;
+            for (int i = start; i < limit; i++) {
+                char c = ch[i];
+                if (c == '\r' || c == '\n') {
+                    if (i != lastEscaped) {
+                        out.write(ch, lastEscaped, i - lastEscaped);
+                    }
+                    lastEscaped = i + 1;
+                    if (out instanceof XmlStreamOutWriterAdapter) {
+                        try {
+                            ((XmlStreamOutWriterAdapter)out).writeEntityRef("#x" + Integer.toHexString(c));
+                        } catch (XMLStreamException e) {
+                            throw new IOException("Error writing xml stream", e);
+                        }
+                    } else {
+                        out.write("&#x");
+                        out.write(Integer.toHexString(c));
+                        out.write(';');
+                    }
+                }
+            }
+
+            if (lastEscaped != limit) {
+                out.write(ch, lastEscaped, length - lastEscaped);
+            }
+        }
+    }
+
+    private static final class XmlStreamOutWriterAdapter extends Writer {
+
+        private final XMLStreamWriter writer;
+
+        private XmlStreamOutWriterAdapter(XMLStreamWriter writer) {
+            this.writer = writer;
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            try {
+                writer.writeCharacters(cbuf, off, len);
+            } catch (XMLStreamException e) {
+                throw new IOException("Error writing XML stream", e);
+            }
+        }
+
+        public void writeEntityRef(String entityReference) throws XMLStreamException {
+            writer.writeEntityRef(entityReference);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            try {
+                writer.flush();
+            } catch (XMLStreamException e) {
+                throw new IOException("Error flushing XML stream", e);
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            try {
+                writer.close();
+            } catch (XMLStreamException e) {
+                throw new IOException("Error closing XML stream", e);
+            }
+        }
+    }
 }
< prev index next >