20 * |
20 * |
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
23 * have any questions. |
23 * have any questions. |
24 */ |
24 */ |
25 |
|
26 package com.sun.xml.internal.bind.v2.runtime.output; |
25 package com.sun.xml.internal.bind.v2.runtime.output; |
27 |
26 |
28 import java.io.IOException; |
27 import java.io.IOException; |
29 import java.io.OutputStream; |
28 import java.io.OutputStream; |
30 |
29 |
31 import javax.xml.stream.XMLStreamException; |
30 import javax.xml.stream.XMLStreamException; |
32 |
31 |
33 import com.sun.xml.internal.bind.DatatypeConverterImpl; |
32 import com.sun.xml.internal.bind.DatatypeConverterImpl; |
34 import com.sun.xml.internal.bind.v2.runtime.Name; |
33 import com.sun.xml.internal.bind.v2.runtime.Name; |
35 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; |
34 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; |
|
35 import com.sun.xml.internal.bind.v2.runtime.MarshallerImpl; |
36 |
36 |
37 import org.xml.sax.SAXException; |
37 import org.xml.sax.SAXException; |
38 |
38 |
39 /** |
39 /** |
40 * {@link XmlOutput} implementation specialized for UTF-8. |
40 * {@link XmlOutput} implementation specialized for UTF-8. |
80 * allows us to write "/>" for empty elements. |
80 * allows us to write "/>" for empty elements. |
81 */ |
81 */ |
82 protected boolean closeStartTagPending = false; |
82 protected boolean closeStartTagPending = false; |
83 |
83 |
84 /** |
84 /** |
|
85 * @see MarshallerImpl#header |
|
86 */ |
|
87 private String header; |
|
88 |
|
89 /** |
85 * |
90 * |
86 * @param localNames |
91 * @param localNames |
87 * local names encoded in UTF-8. |
92 * local names encoded in UTF-8. |
88 */ |
93 */ |
89 public UTF8XmlOutput(OutputStream out, Encoded[] localNames) { |
94 public UTF8XmlOutput(OutputStream out, Encoded[] localNames) { |
91 this.localNames = localNames; |
96 this.localNames = localNames; |
92 for( int i=0; i<prefixes.length; i++ ) |
97 for( int i=0; i<prefixes.length; i++ ) |
93 prefixes[i] = new Encoded(); |
98 prefixes[i] = new Encoded(); |
94 } |
99 } |
95 |
100 |
|
101 public void setHeader(String header) { |
|
102 this.header = header; |
|
103 } |
|
104 |
96 @Override |
105 @Override |
97 public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException { |
106 public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException { |
98 super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext); |
107 super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext); |
99 |
108 |
100 octetBufferIndex = 0; |
109 octetBufferIndex = 0; |
101 if(!fragment) { |
110 if(!fragment) { |
102 write(XML_DECL); |
111 write(XML_DECL); |
|
112 } |
|
113 if(header!=null) { |
|
114 textBuffer.set(header); |
|
115 textBuffer.write(this); |
103 } |
116 } |
104 } |
117 } |
105 |
118 |
106 public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException { |
119 public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException { |
107 flushBuffer(); |
120 flushBuffer(); |
375 protected final void flushBuffer() throws IOException { |
388 protected final void flushBuffer() throws IOException { |
376 out.write(octetBuffer, 0, octetBufferIndex); |
389 out.write(octetBuffer, 0, octetBufferIndex); |
377 octetBufferIndex = 0; |
390 octetBufferIndex = 0; |
378 } |
391 } |
379 |
392 |
380 public void flush() throws IOException { |
|
381 flushBuffer(); |
|
382 out.flush(); |
|
383 } |
|
384 |
|
385 |
|
386 |
|
387 static byte[] toBytes(String s) { |
393 static byte[] toBytes(String s) { |
388 byte[] buf = new byte[s.length()]; |
394 byte[] buf = new byte[s.length()]; |
389 for( int i=s.length()-1; i>=0; i-- ) |
395 for( int i=s.length()-1; i>=0; i-- ) |
390 buf[i] = (byte)s.charAt(i); |
396 buf[i] = (byte)s.charAt(i); |
391 return buf; |
397 return buf; |
392 } |
398 } |
393 |
399 |
394 private static final byte[] XMLNS_EQUALS = toBytes(" xmlns=\""); |
400 // per instance copy to prevent an attack where malicious OutputStream |
395 private static final byte[] XMLNS_COLON = toBytes(" xmlns:"); |
401 // rewrites the byte array. |
396 private static final byte[] EQUALS = toBytes("=\""); |
402 private final byte[] XMLNS_EQUALS = _XMLNS_EQUALS.clone(); |
397 private static final byte[] CLOSE_TAG = toBytes("</"); |
403 private final byte[] XMLNS_COLON = _XMLNS_COLON.clone(); |
398 private static final byte[] EMPTY_TAG = toBytes("/>"); |
404 private final byte[] EQUALS = _EQUALS.clone(); |
|
405 private final byte[] CLOSE_TAG = _CLOSE_TAG.clone(); |
|
406 private final byte[] EMPTY_TAG = _EMPTY_TAG.clone(); |
|
407 private final byte[] XML_DECL = _XML_DECL.clone(); |
|
408 |
|
409 // masters |
|
410 private static final byte[] _XMLNS_EQUALS = toBytes(" xmlns=\""); |
|
411 private static final byte[] _XMLNS_COLON = toBytes(" xmlns:"); |
|
412 private static final byte[] _EQUALS = toBytes("=\""); |
|
413 private static final byte[] _CLOSE_TAG = toBytes("</"); |
|
414 private static final byte[] _EMPTY_TAG = toBytes("/>"); |
|
415 private static final byte[] _XML_DECL = toBytes("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); |
|
416 |
|
417 // no need to copy |
399 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; |
418 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; |
400 private static final byte[] XML_DECL = toBytes("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); |
|
401 } |
419 } |