001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.stream.writers;
027:
028: import java.io.FileWriter;
029: import java.io.IOException;
030: import java.io.OutputStreamWriter;
031: import java.io.Writer;
032: import java.nio.charset.Charset;
033: import java.nio.charset.CharsetEncoder;
034: import com.sun.org.apache.xerces.internal.util.XMLChar;
035:
036: /**
037: * Implements common xml writer functions.
038: *
039: * @author Neeraj Bajaj,K.Venugopal Sun Microsystems.
040: */
041:
042: public class WriterUtility {
043:
044: public static final String START_COMMENT = "<!--";
045: public static final String END_COMMENT = "-->";
046: public static final String DEFAULT_ENCODING = " encoding=\"utf-8\"";
047: public static final String DEFAULT_XMLDECL = "<?xml version=\"1.0\" ?>";
048: public static final String DEFAULT_XML_VERSION = "1.0";
049: public static final char CLOSE_START_TAG = '>';
050: public static final char OPEN_START_TAG = '<';
051: public static final String OPEN_END_TAG = "</";
052: public static final char CLOSE_END_TAG = '>';
053: public static final String START_CDATA = "<![CDATA[";
054: public static final String END_CDATA = "]]>";
055: public static final String CLOSE_EMPTY_ELEMENT = "/>";
056: public static final String SPACE = " ";
057: public static final String UTF_8 = "utf-8";
058:
059: static final boolean DEBUG_XML_CONTENT = false;
060:
061: /**XXX: This feature is only used when writing element content values.
062: * default value is 'true' however, if the feature is set to false
063: * characters wont be escaped.
064: * This feature has no effect when writing Attribute values, character would still be escaped.
065: * I can't think of any reason why this would be useful when writing attribute values.
066: * However, this can be reconsidered if there is any usecase.
067: */
068: boolean fEscapeCharacters = true;
069:
070: /** Writer object*/
071: Writer fWriter = null;
072:
073: //CharsetEncoder
074: CharsetEncoder fEncoder;
075:
076: public WriterUtility() {
077: fEncoder = getDefaultEncoder();
078: }
079:
080: /** Creates a new instance of WriterUtility */
081: public WriterUtility(Writer writer) {
082: fWriter = writer;
083: if (writer instanceof OutputStreamWriter) {
084: String charset = ((OutputStreamWriter) writer)
085: .getEncoding();
086: if (charset != null) {
087: fEncoder = Charset.forName(charset).newEncoder();
088: }
089: } else if (writer instanceof FileWriter) {
090: String charset = ((FileWriter) writer).getEncoding();
091: if (charset != null) {
092: fEncoder = Charset.forName(charset).newEncoder();
093: }
094: } else {
095: //attempt to retreive default fEncoderoder
096: fEncoder = getDefaultEncoder();
097: }
098: }
099:
100: /**
101: * sets the writer object
102: * @param writer file to write into
103: */
104: public void setWriter(Writer writer) {
105: fWriter = writer;
106: }
107:
108: public void setEscapeCharacters(boolean escape) {
109: fEscapeCharacters = escape;
110: }
111:
112: public boolean getEscapeCharacters() {
113: return fEscapeCharacters;
114: }
115:
116: /**
117: * writes xml content (characters and element content
118: * @param content
119: */
120: public void writeXMLContent(char[] content, int start, int length)
121: throws IOException {
122: writeXMLContent(content, start, length, getEscapeCharacters());
123: }
124:
125: /**
126: * writes xml content (characters and element content
127: * @param content
128: */
129: private void writeXMLContent(char[] content, int start, int length,
130: boolean escapeCharacter) throws IOException {
131: if (DEBUG_XML_CONTENT) {
132: System.out.println("content to write is "
133: + new String(content, start, length));
134: }
135: int index;
136: char ch;
137: int sc;
138: final int end = start + length;
139: //define startWritePos to track the position from where the character array data needs to be written
140: //initialize this variable to start pos. indicating that no data has been written
141: int startWritePos = start;
142:
143: for (index = start; index < end; index++) {
144: ch = content[index];
145:
146: if (fEncoder != null && !fEncoder.canEncode(ch)) {
147: //- write the data to the point we get this character
148: fWriter.write(content, startWritePos, index
149: - startWritePos);
150:
151: //escape this character
152: fWriter.write("&#x");
153: fWriter.write(Integer.toHexString(ch));
154: fWriter.write(';');
155: //increase the startWritePos by 1 indicating that next write should start from
156: //one position ahead
157: startWritePos = index + 1;
158:
159: }
160: if (DEBUG_XML_CONTENT) {
161: System.out.println("startWritePos = " + startWritePos);
162: System.out.println("index = " + index);
163: System.out.println("start = " + start);
164: System.out.println("end = " + end);
165: }
166:
167: switch (ch) {
168: case '<': {
169: if (escapeCharacter) {
170: //this character needs to be escaped, write the data from the last write pos
171: fWriter.write(content, startWritePos, index
172: - startWritePos);
173: fWriter.write("<");
174: if (DEBUG_XML_CONTENT) {
175: System.out.print(new String(content,
176: startWritePos, index - startWritePos));
177: System.out.println("<");
178: }
179: //increase the startWritePos by 1 indicating that next write should start from
180: //one position ahead
181: startWritePos = index + 1;
182: }
183: break;
184: }
185: case '&': {
186: if (escapeCharacter) {
187: //this character needs to be escaped, write the data from the last write pos
188: fWriter.write(content, startWritePos, index
189: - startWritePos);
190: fWriter.write("&");
191: if (DEBUG_XML_CONTENT) {
192: System.out.print(new String(content,
193: startWritePos, index - startWritePos));
194: System.out.println("&");
195: }
196: //increase the startWritePos by 1 indicating that next write should start from
197: //one position ahead
198: startWritePos = index + 1;
199: }
200: break;
201: }
202:
203: case '>': {
204: if (escapeCharacter) {
205: //this character needs to be escaped, write the data from the last write pos
206: fWriter.write(content, startWritePos, index
207: - startWritePos);
208: fWriter.write(">");
209: if (DEBUG_XML_CONTENT) {
210: System.out.print(new String(content,
211: startWritePos, index - startWritePos));
212: System.out.println(">");
213: }
214: //increase the startWritePos by 1 indicating that next write should start from
215: //one position ahead
216: startWritePos = index + 1;
217: }
218: break;
219: }
220: }
221: }
222: if (DEBUG_XML_CONTENT) {
223: System.out.println("out of the loop, writing "
224: + new String(content, startWritePos, end
225: - startWritePos));
226: }
227: //write any pending data
228: fWriter.write(content, startWritePos, end - startWritePos);
229: }
230:
231: /**
232: * writes xml content (characters and element content
233: * @param content
234: */
235: public void writeXMLContent(String content) throws IOException {
236: if (content == null || content.length() == 0)
237: return;
238: writeXMLContent(content.toCharArray(), 0, content.length());
239: }
240:
241: /**
242: * Write Attribute value to the underlying stream.
243: *
244: * @param value
245: */
246:
247: public void writeXMLAttributeValue(String value) throws IOException {
248: writeXMLContent(value.toCharArray(), 0, value.length(), true);
249: }
250:
251: private CharsetEncoder getDefaultEncoder() {
252: try {
253: String encoding = System.getProperty("file.encoding");
254: if (encoding != null) {
255: return Charset.forName(encoding).newEncoder();
256: }
257: } catch (Exception ex) {
258: //for any exception thrown , catch and continue
259: }
260: return null;
261: }
262: }
|