KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > runtime > impl > UTF8StreamWriter


1 /*
2 Copyright (c) 2004, Dennis M. Sosnoski.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.runtime.impl;
30
31 import java.io.IOException JavaDoc;
32
33 /**
34  * Handler for marshalling text document to a UTF-8 output stream.
35  *
36  * @author Dennis M. Sosnoski
37  * @version 1.0
38  */

39
40 public class UTF8StreamWriter extends StreamWriterBase
41 {
42     /** Conversion buffer for prefixes; */
43     private byte[] m_converts;
44     
45     /**
46      * Constructor.
47      *
48      * @param uris ordered array of URIs for namespaces used in document (must
49      * be constant; the value in position 0 must always be the empty string "",
50      * and the value in position 1 must always be the XML namespace
51      * "http://www.w3.org/XML/1998/namespace")
52      */

53     
54     public UTF8StreamWriter(String JavaDoc[] uris) {
55         super("UTF-8", uris);
56         m_prefixBytes = new byte[uris.length][];
57         defineNamespace(0, "");
58         defineNamespace(1, "xml");
59     }
60     
61     /**
62      * Write markup text to output. Markup text can be written directly to the
63      * output without the need for any escaping, but still needs to be properly
64      * encoded.
65      *
66      * @param text markup text to be written
67      * @throws IOException if error writing to document
68      */

69     
70     protected void writeMarkup(String JavaDoc text) throws IOException JavaDoc {
71         int length = text.length();
72         makeSpace(length * 3);
73         int fill = m_fillOffset;
74         for (int i = 0; i < length; i++) {
75             char chr = text.charAt(i);
76             if (chr > 0x7F) {
77                 if (chr > 0x7FF) {
78                     m_buffer[fill++] = (byte)(0xE0 + (chr >> 12));
79                     m_buffer[fill++] = (byte)(0x80 + ((chr >> 6) & 0x3F));
80                     m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
81                 } else {
82                     m_buffer[fill++] = (byte)(0xC0 + (chr >> 6));
83                     m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
84                 }
85             } else {
86                 m_buffer[fill++] = (byte)chr;
87             }
88         }
89         m_fillOffset = fill;
90     }
91     
92     /**
93      * Write markup character to output. Markup text can be written directly to
94      * the output without the need for any escaping, but still needs to be
95      * properly encoded.
96      *
97      * @param chr markup character to be written
98      * @throws IOException if error writing to document
99      */

100     
101     protected void writeMarkup(char chr) throws IOException JavaDoc {
102         makeSpace(3);
103         if (chr > 0x7F) {
104             if (chr > 0x7FF) {
105                 m_buffer[m_fillOffset++] = (byte)(0xE0 + (chr >> 12));
106                 m_buffer[m_fillOffset++] = (byte)(0x80 + ((chr >> 6) & 0x3F));
107                 m_buffer[m_fillOffset++] = (byte)(0x80 + (chr & 0x3F));
108             } else {
109                 m_buffer[m_fillOffset++] = (byte)(0xC0 + (chr >> 6));
110                 m_buffer[m_fillOffset++] = (byte)(0x80 + (chr & 0x3F));
111             }
112         } else {
113             m_buffer[m_fillOffset++] = (byte)chr;
114         }
115     }
116     
117     /**
118      * Report that namespace has been defined.
119      *
120      * @param index namespace URI index number
121      * @param prefix prefix used for namespace
122      */

123     
124     protected void defineNamespace(int index, String JavaDoc prefix) {
125         int limit = prefix.length() * 3;
126         if (m_converts == null) {
127             m_converts = new byte[limit];
128         } else if (limit > m_converts.length) {
129             m_converts = new byte[limit];
130         }
131         int fill = 0;
132         for (int i = 0; i < prefix.length(); i++) {
133             char chr = prefix.charAt(i);
134             if (chr > 0x7F) {
135                 if (chr > 0x7FF) {
136                     m_converts[fill++] = (byte)(0xE0 + (chr >> 12));
137                     m_converts[fill++] = (byte)(0x80 + ((chr >> 6) & 0x3F));
138                     m_converts[fill++] = (byte)(0x80 + (chr & 0x3F));
139                 } else {
140                     m_converts[fill++] = (byte)(0xC0 + (chr >> 6));
141                     m_converts[fill++] = (byte)(0x80 + (chr & 0x3F));
142                 }
143             } else {
144                 m_converts[fill++] = (byte)chr;
145             }
146         }
147         byte[] trim;
148         if (fill > 0) {
149             trim = new byte[fill+1];
150             System.arraycopy(m_converts, 0, trim, 0, fill);
151             trim[fill] = ':';
152         } else {
153             trim = new byte[0];
154         }
155         if (index < m_prefixBytes.length) {
156             m_prefixBytes[index] = trim;
157         } else if (m_extensionBytes != null) {
158             index -= m_prefixBytes.length;
159             for (int i = 0; i < m_extensionBytes.length; i++) {
160                 int length = m_extensionBytes[i].length;
161                 if (index < length) {
162                     m_extensionBytes[i][index] = trim;
163                 } else {
164                     index -= length;
165                 }
166             }
167         } else {
168             throw new IllegalArgumentException JavaDoc("Index out of range");
169         }
170     }
171     
172     /**
173      * Write attribute text to output. This needs to write the text with any
174      * appropriate escaping.
175      *
176      * @param text attribute value text to be written
177      * @throws IOException if error writing to document
178      */

179     
180     protected void writeAttributeText(String JavaDoc text) throws IOException JavaDoc {
181         int length = text.length();
182         makeSpace(length * 6);
183         int fill = m_fillOffset;
184         for (int i = 0; i < length; i++) {
185             char chr = text.charAt(i);
186             if (chr == '"') {
187                 fill = writeEntity(QUOT_ENTITY, fill);
188             } else if (chr == '&') {
189                 fill = writeEntity(AMP_ENTITY, fill);
190             } else if (chr == '<') {
191                 fill = writeEntity(LT_ENTITY, fill);
192             } else if (chr == '>' && i > 2 && text.charAt(i-1) == ']' &&
193                 text.charAt(i-2) == ']') {
194                 m_buffer[fill++] = (byte)']';
195                 m_buffer[fill++] = (byte)']';
196                 fill = writeEntity(GT_ENTITY, fill);
197             } else if (chr < 0x20) {
198                 if (chr != 0x9 && chr != 0xA && chr != 0xD) {
199                     throw new IOException JavaDoc("Illegal character code 0x" +
200                         Integer.toHexString(chr) + " in attribute value text");
201                 } else {
202                     m_buffer[fill++] = (byte)chr;
203                 }
204             } else {
205                 if (chr > 0x7F) {
206                     if (chr > 0x7FF) {
207                         if (chr > 0xD7FF && (chr < 0xE000 || chr == 0xFFFE ||
208                             chr == 0xFFFF || chr > 0x10FFFF)) {
209                             throw new IOException JavaDoc("Illegal character code 0x" +
210                                 Integer.toHexString(chr) +
211                                 " in attribute value text");
212                         } else {
213                             m_buffer[fill++] = (byte)(0xE0 + (chr >> 12));
214                             m_buffer[fill++] =
215                                 (byte)(0x80 + ((chr >> 6) & 0x3F));
216                             m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
217                         }
218                     } else {
219                         m_buffer[fill++] = (byte)(0xC0 + (chr >> 6));
220                         m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
221                     }
222                 } else {
223                     m_buffer[fill++] = (byte)chr;
224                 }
225             }
226         }
227         m_fillOffset = fill;
228     }
229     
230     /**
231      * Write ordinary character data text content to document.
232      *
233      * @param text content value text
234      * @throws IOException on error writing to document
235      */

236
237     public void writeTextContent(String JavaDoc text) throws IOException JavaDoc {
238         int length = text.length();
239         makeSpace(length * 5);
240         int fill = m_fillOffset;
241         for (int i = 0; i < length; i++) {
242             char chr = text.charAt(i);
243             if (chr == '&') {
244                 fill = writeEntity(AMP_ENTITY, fill);
245             } else if (chr == '<') {
246                 fill = writeEntity(LT_ENTITY, fill);
247             } else if (chr == '>' && i > 2 && text.charAt(i-1) == ']' &&
248                 text.charAt(i-2) == ']') {
249                 m_buffer[fill++] = (byte)']';
250                 m_buffer[fill++] = (byte)']';
251                 fill = writeEntity(GT_ENTITY, fill);
252             } else if (chr < 0x20) {
253                 if (chr != 0x9 && chr != 0xA && chr != 0xD) {
254                     throw new IOException JavaDoc("Illegal character code 0x" +
255                         Integer.toHexString(chr) + " in content text");
256                 } else {
257                     m_buffer[fill++] = (byte)chr;
258                 }
259             } else {
260                 if (chr > 0x7F) {
261                     if (chr > 0x7FF) {
262                         if (chr > 0xD7FF && (chr < 0xE000 || chr == 0xFFFE ||
263                             chr == 0xFFFF || chr > 0x10FFFF)) {
264                             throw new IOException JavaDoc("Illegal character code 0x" +
265                                 Integer.toHexString(chr) + " in content text");
266                         } else {
267                             m_buffer[fill++] = (byte)(0xE0 + (chr >> 12));
268                             m_buffer[fill++] =
269                                 (byte)(0x80 + ((chr >> 6) & 0x3F));
270                             m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
271                         }
272                     } else {
273                         m_buffer[fill++] = (byte)(0xC0 + (chr >> 6));
274                         m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
275                     }
276                 } else {
277                     m_buffer[fill++] = (byte)chr;
278                 }
279             }
280         }
281         m_fillOffset = fill;
282         m_textSeen = m_contentSeen = true;
283     }
284     
285     /**
286      * Write CDATA text to document.
287      *
288      * @param text content value text
289      * @throws IOException on error writing to document
290      */

291
292     public void writeCData(String JavaDoc text) throws IOException JavaDoc {
293         int length = text.length();
294         makeSpace(length * 3 + 12);
295         int fill = m_fillOffset;
296         fill = writeEntity(LT_CDATASTART, fill);
297         for (int i = 0; i < length; i++) {
298             char chr = text.charAt(i);
299             if (chr == '>' && i > 2 && text.charAt(i-1) == ']' &&
300                 text.charAt(i-2) == ']') {
301                 throw new IOException JavaDoc("Sequence \"]]>\" is not allowed " +
302                     "within CDATA section text");
303             } else if (chr < 0x20) {
304                 if (chr != 0x9 && chr != 0xA && chr != 0xD) {
305                     throw new IOException JavaDoc("Illegal character code 0x" +
306                         Integer.toHexString(chr) + " in content text");
307                 } else {
308                     m_buffer[fill++] = (byte)chr;
309                 }
310             } else {
311                 if (chr > 0x7F) {
312                     if (chr > 0x7FF) {
313                         if (chr > 0xD7FF && (chr < 0xE000 || chr == 0xFFFE ||
314                             chr == 0xFFFF || chr > 0x10FFFF)) {
315                             throw new IOException JavaDoc("Illegal character code 0x" +
316                                 Integer.toHexString(chr) +
317                                 " in CDATA section text");
318                         } else {
319                             m_buffer[fill++] = (byte)(0xE0 + (chr >> 12));
320                             m_buffer[fill++] =
321                                 (byte)(0x80 + ((chr >> 6) & 0x3F));
322                             m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
323                         }
324                     } else {
325                         m_buffer[fill++] = (byte)(0xC0 + (chr >> 6));
326                         m_buffer[fill++] = (byte)(0x80 + (chr & 0x3F));
327                     }
328                 } else {
329                     m_buffer[fill++] = (byte)chr;
330                 }
331             }
332         }
333         m_fillOffset = writeEntity(LT_CDATAEND, fill);
334         m_textSeen = m_contentSeen = true;
335     }
336 }
Popular Tags