< 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 >