Sun, 18 Jun 2017 23:18:45 +0100
8172297: In java 8, the marshalling with JAX-WS does not escape carriage return
Reviewed-by: lancea
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/NoEscapeHandler.java Sun Jun 18 23:18:45 2017 +0100 1.3 @@ -0,0 +1,45 @@ 1.4 +/* 1.5 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.bind.marshaller; 1.30 + 1.31 +import java.io.IOException; 1.32 +import java.io.Writer; 1.33 + 1.34 +/** 1.35 + * Performs no character escaping. 1.36 + * 1.37 + * @author 1.38 + * Roman Grigoriadi (roman.grigoriadi@oracle.com) 1.39 + */ 1.40 +public class NoEscapeHandler implements CharacterEscapeHandler { 1.41 + 1.42 + public static final NoEscapeHandler theInstance = new NoEscapeHandler(); 1.43 + 1.44 + @Override 1.45 + public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { 1.46 + out.write(ch, start, length); 1.47 + } 1.48 +}
2.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BridgeImpl.java Tue May 16 13:28:58 2017 -0700 2.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BridgeImpl.java Sun Jun 18 23:18:45 2017 +0100 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -76,7 +76,7 @@ 2.11 2.12 public void marshal(Marshaller _m, T t, XMLStreamWriter output) throws JAXBException { 2.13 MarshallerImpl m = (MarshallerImpl)_m; 2.14 - m.write(tagName,bi,t,XMLStreamWriterOutput.create(output,context),new StAXPostInitAction(output,m.serializer)); 2.15 + m.write(tagName,bi,t,XMLStreamWriterOutput.create(output,context, m.getEscapeHandler()),new StAXPostInitAction(output,m.serializer)); 2.16 } 2.17 2.18 public void marshal(Marshaller _m, T t, OutputStream output, NamespaceContext nsContext) throws JAXBException {
3.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/MarshallerImpl.java Tue May 16 13:28:58 2017 -0700 3.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/MarshallerImpl.java Sun Jun 18 23:18:45 2017 +0100 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -160,7 +160,7 @@ 3.11 3.12 @Override 3.13 public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException { 3.14 - write(obj, XMLStreamWriterOutput.create(writer,context), new StAXPostInitAction(writer,serializer)); 3.15 + write(obj, XMLStreamWriterOutput.create(writer,context, escapeHandler), new StAXPostInitAction(writer,serializer)); 3.16 } 3.17 3.18 @Override 3.19 @@ -364,6 +364,15 @@ 3.20 } 3.21 3.22 3.23 + /** 3.24 + * Returns escape handler provided with JAXB context parameters. 3.25 + * 3.26 + * @return escape handler 3.27 + */ 3.28 + CharacterEscapeHandler getEscapeHandler() { 3.29 + return escapeHandler; 3.30 + } 3.31 + 3.32 // 3.33 // 3.34 // create XMLWriter by specifing various type of output.
4.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/FastInfosetStreamWriterOutput.java Tue May 16 13:28:58 2017 -0700 4.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/FastInfosetStreamWriterOutput.java Sun Jun 18 23:18:45 2017 +0100 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -25,6 +25,7 @@ 4.11 4.12 package com.sun.xml.internal.bind.v2.runtime.output; 4.13 4.14 +import com.sun.xml.internal.bind.marshaller.NoEscapeHandler; 4.15 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl; 4.16 import com.sun.xml.internal.bind.v2.runtime.Name; 4.17 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; 4.18 @@ -220,7 +221,7 @@ 4.19 4.20 public FastInfosetStreamWriterOutput(StAXDocumentSerializer out, 4.21 JAXBContextImpl context) { 4.22 - super(out); 4.23 + super(out, NoEscapeHandler.theInstance); 4.24 4.25 this.fiout = out; 4.26 this.localNames = context.getUTF8NameTable();
5.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/StAXExStreamWriterOutput.java Tue May 16 13:28:58 2017 -0700 5.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/StAXExStreamWriterOutput.java Sun Jun 18 23:18:45 2017 +0100 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -27,6 +27,7 @@ 5.11 5.12 import javax.xml.stream.XMLStreamException; 5.13 5.14 +import com.sun.xml.internal.bind.marshaller.NoEscapeHandler; 5.15 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data; 5.16 5.17 import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx; 5.18 @@ -40,7 +41,7 @@ 5.19 private final XMLStreamWriterEx out; 5.20 5.21 public StAXExStreamWriterOutput(XMLStreamWriterEx out) { 5.22 - super(out); 5.23 + super(out, NoEscapeHandler.theInstance); 5.24 this.out = out; 5.25 } 5.26
6.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java Tue May 16 13:28:58 2017 -0700 6.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java Sun Jun 18 23:18:45 2017 +0100 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -26,15 +26,16 @@ 6.11 package com.sun.xml.internal.bind.v2.runtime.output; 6.12 6.13 import java.io.IOException; 6.14 +import java.io.Writer; 6.15 import java.lang.reflect.Constructor; 6.16 6.17 import javax.xml.stream.XMLStreamException; 6.18 import javax.xml.stream.XMLStreamWriter; 6.19 6.20 +import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler; 6.21 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl; 6.22 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; 6.23 6.24 -import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl; 6.25 import org.xml.sax.SAXException; 6.26 6.27 /** 6.28 @@ -53,7 +54,7 @@ 6.29 * Creates a new {@link XmlOutput} from a {@link XMLStreamWriter}. 6.30 * This method recognizes an FI StAX writer. 6.31 */ 6.32 - public static XmlOutput create(XMLStreamWriter out, JAXBContextImpl context) { 6.33 + public static XmlOutput create(XMLStreamWriter out, JAXBContextImpl context, CharacterEscapeHandler escapeHandler) { 6.34 // try optimized path 6.35 final Class writerClass = out.getClass(); 6.36 if (writerClass==FI_STAX_WRITER_CLASS) { 6.37 @@ -69,17 +70,26 @@ 6.38 } 6.39 } 6.40 6.41 + CharacterEscapeHandler xmlStreamEscapeHandler = escapeHandler != null ? 6.42 + escapeHandler : NewLineEscapeHandler.theInstance; 6.43 + 6.44 // otherwise the normal writer. 6.45 - return new XMLStreamWriterOutput(out); 6.46 + return new XMLStreamWriterOutput(out, xmlStreamEscapeHandler); 6.47 } 6.48 6.49 6.50 private final XMLStreamWriter out; 6.51 6.52 + private final CharacterEscapeHandler escapeHandler; 6.53 + 6.54 + private final XmlStreamOutWriterAdapter writerWrapper; 6.55 + 6.56 protected final char[] buf = new char[256]; 6.57 6.58 - protected XMLStreamWriterOutput(XMLStreamWriter out) { 6.59 + protected XMLStreamWriterOutput(XMLStreamWriter out, CharacterEscapeHandler escapeHandler) { 6.60 this.out = out; 6.61 + this.escapeHandler = escapeHandler; 6.62 + this.writerWrapper = new XmlStreamOutWriterAdapter(out); 6.63 } 6.64 6.65 // not called if we are generating fragments 6.66 @@ -137,7 +147,7 @@ 6.67 public void text(String value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException { 6.68 if(needsSeparatingWhitespace) 6.69 out.writeCharacters(" "); 6.70 - out.writeCharacters(value); 6.71 + escapeHandler.escape(value.toCharArray(), 0, value.length(), false, writerWrapper); 6.72 } 6.73 6.74 public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException { 6.75 @@ -207,4 +217,82 @@ 6.76 } 6.77 } 6.78 6.79 + 6.80 + /** 6.81 + * Performs character escaping only for new lines. 6.82 + */ 6.83 + private static class NewLineEscapeHandler implements CharacterEscapeHandler { 6.84 + 6.85 + public static final NewLineEscapeHandler theInstance = new NewLineEscapeHandler(); 6.86 + 6.87 + @Override 6.88 + public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { 6.89 + int limit = start+length; 6.90 + int lastEscaped = start; 6.91 + 6.92 + for (int i = start; i < limit; i++) { 6.93 + char c = ch[i]; 6.94 + if (c == '\r' || c == '\n') { 6.95 + if (i != lastEscaped) { 6.96 + out.write(ch, lastEscaped, i - lastEscaped); 6.97 + } 6.98 + lastEscaped = i + 1; 6.99 + if (out instanceof XmlStreamOutWriterAdapter) { 6.100 + try { 6.101 + ((XmlStreamOutWriterAdapter)out).writeEntityRef("#x" + Integer.toHexString(c)); 6.102 + } catch (XMLStreamException e) { 6.103 + throw new IOException("Error writing xml stream", e); 6.104 + } 6.105 + } else { 6.106 + out.write("&#x"); 6.107 + out.write(Integer.toHexString(c)); 6.108 + out.write(';'); 6.109 + } 6.110 + } 6.111 + } 6.112 + if (lastEscaped != limit) { 6.113 + out.write(ch, lastEscaped, length - lastEscaped); 6.114 + } 6.115 + } 6.116 + } 6.117 + 6.118 + private static final class XmlStreamOutWriterAdapter extends Writer { 6.119 + 6.120 + private final XMLStreamWriter writer; 6.121 + 6.122 + private XmlStreamOutWriterAdapter(XMLStreamWriter writer) { 6.123 + this.writer = writer; 6.124 + } 6.125 + 6.126 + @Override 6.127 + public void write(char[] cbuf, int off, int len) throws IOException { 6.128 + try { 6.129 + writer.writeCharacters(cbuf, off, len); 6.130 + } catch (XMLStreamException e) { 6.131 + throw new IOException("Error writing XML stream", e); 6.132 + } 6.133 + } 6.134 + 6.135 + public void writeEntityRef(String entityReference) throws XMLStreamException { 6.136 + writer.writeEntityRef(entityReference); 6.137 + } 6.138 + 6.139 + @Override 6.140 + public void flush() throws IOException { 6.141 + try { 6.142 + writer.flush(); 6.143 + } catch (XMLStreamException e) { 6.144 + throw new IOException("Error flushing XML stream", e); 6.145 + } 6.146 + } 6.147 + 6.148 + @Override 6.149 + public void close() throws IOException { 6.150 + try { 6.151 + writer.close(); 6.152 + } catch (XMLStreamException e) { 6.153 + throw new IOException("Error closing XML stream", e); 6.154 + } 6.155 + } 6.156 + } 6.157 }