001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/DOMWriter.java,v 1.2 2001/07/22 20:25:13 pier Exp $
003: * $Revision: 1.2 $
004: * $Date: 2001/07/22 20:25:13 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.catalina.util;
065:
066: import java.io.*;
067: import org.w3c.dom.Attr;
068: import org.w3c.dom.Document;
069: import org.w3c.dom.NamedNodeMap;
070: import org.w3c.dom.Node;
071: import org.w3c.dom.NodeList;
072: import org.xml.sax.InputSource;
073:
074: /**
075: * A sample DOM writer. This sample program illustrates how to
076: * traverse a DOM tree in order to print a document that is parsed.
077: */
078: public class DOMWriter {
079:
080: //
081: // Data
082: //
083:
084: /** Default Encoding */
085: private static String PRINTWRITER_ENCODING = "UTF8";
086:
087: private static String MIME2JAVA_ENCODINGS[] = { "Default", "UTF-8",
088: "US-ASCII", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3",
089: "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7",
090: "ISO-8859-8", "ISO-8859-9", "ISO-2022-JP", "SHIFT_JIS",
091: "EUC-JP", "GB2312", "BIG5", "EUC-KR", "ISO-2022-KR",
092: "KOI8-R", "EBCDIC-CP-US", "EBCDIC-CP-CA", "EBCDIC-CP-NL",
093: "EBCDIC-CP-DK", "EBCDIC-CP-NO", "EBCDIC-CP-FI",
094: "EBCDIC-CP-SE", "EBCDIC-CP-IT", "EBCDIC-CP-ES",
095: "EBCDIC-CP-GB", "EBCDIC-CP-FR", "EBCDIC-CP-AR1",
096: "EBCDIC-CP-HE", "EBCDIC-CP-CH", "EBCDIC-CP-ROECE",
097: "EBCDIC-CP-YU", "EBCDIC-CP-IS", "EBCDIC-CP-AR2", "UTF-16" };
098:
099: /** Print writer. */
100: protected PrintWriter out;
101:
102: /** Canonical output. */
103: protected boolean canonical;
104:
105: public DOMWriter(String encoding, boolean canonical)
106: throws UnsupportedEncodingException {
107: out = new PrintWriter(new OutputStreamWriter(System.out,
108: encoding));
109: this .canonical = canonical;
110: } // <init>(String,boolean)
111:
112: //
113: // Constructors
114: //
115:
116: /** Default constructor. */
117: public DOMWriter(boolean canonical)
118: throws UnsupportedEncodingException {
119: this (getWriterEncoding(), canonical);
120: }
121:
122: public DOMWriter(Writer writer, boolean canonical) {
123: out = new PrintWriter(writer);
124: this .canonical = canonical;
125: }
126:
127: public static String getWriterEncoding() {
128: return (PRINTWRITER_ENCODING);
129: }// getWriterEncoding
130:
131: public static void setWriterEncoding(String encoding) {
132: if (encoding.equalsIgnoreCase("DEFAULT"))
133: PRINTWRITER_ENCODING = "UTF8";
134: else if (encoding.equalsIgnoreCase("UTF-16"))
135: PRINTWRITER_ENCODING = "Unicode";
136: else
137: PRINTWRITER_ENCODING = MIME2Java.convert(encoding);
138: }// setWriterEncoding
139:
140: public static boolean isValidJavaEncoding(String encoding) {
141: for (int i = 0; i < MIME2JAVA_ENCODINGS.length; i++)
142: if (encoding.equals(MIME2JAVA_ENCODINGS[i]))
143: return (true);
144:
145: return (false);
146: }// isValidJavaEncoding
147:
148: /** Prints the specified node, recursively. */
149: public void print(Node node) {
150:
151: // is there anything to do?
152: if (node == null) {
153: return;
154: }
155:
156: int type = node.getNodeType();
157: switch (type) {
158: // print document
159: case Node.DOCUMENT_NODE: {
160: if (!canonical) {
161: String Encoding = this .getWriterEncoding();
162: if (Encoding.equalsIgnoreCase("DEFAULT"))
163: Encoding = "UTF-8";
164: else if (Encoding.equalsIgnoreCase("Unicode"))
165: Encoding = "UTF-16";
166: else
167: Encoding = MIME2Java.reverse(Encoding);
168:
169: out.println("<?xml version=\"1.0\" encoding=\""
170: + Encoding + "\"?>");
171: }
172: print(((Document) node).getDocumentElement());
173: out.flush();
174: break;
175: }
176:
177: // print element with attributes
178: case Node.ELEMENT_NODE: {
179: out.print('<');
180: out.print(node.getNodeName());
181: Attr attrs[] = sortAttributes(node.getAttributes());
182: for (int i = 0; i < attrs.length; i++) {
183: Attr attr = attrs[i];
184: out.print(' ');
185: out.print(attr.getNodeName());
186: out.print("=\"");
187: out.print(normalize(attr.getNodeValue()));
188: out.print('"');
189: }
190: out.print('>');
191: NodeList children = node.getChildNodes();
192: if (children != null) {
193: int len = children.getLength();
194: for (int i = 0; i < len; i++) {
195: print(children.item(i));
196: }
197: }
198: break;
199: }
200:
201: // handle entity reference nodes
202: case Node.ENTITY_REFERENCE_NODE: {
203: if (canonical) {
204: NodeList children = node.getChildNodes();
205: if (children != null) {
206: int len = children.getLength();
207: for (int i = 0; i < len; i++) {
208: print(children.item(i));
209: }
210: }
211: } else {
212: out.print('&');
213: out.print(node.getNodeName());
214: out.print(';');
215: }
216: break;
217: }
218:
219: // print cdata sections
220: case Node.CDATA_SECTION_NODE: {
221: if (canonical) {
222: out.print(normalize(node.getNodeValue()));
223: } else {
224: out.print("<![CDATA[");
225: out.print(node.getNodeValue());
226: out.print("]]>");
227: }
228: break;
229: }
230:
231: // print text
232: case Node.TEXT_NODE: {
233: out.print(normalize(node.getNodeValue()));
234: break;
235: }
236:
237: // print processing instruction
238: case Node.PROCESSING_INSTRUCTION_NODE: {
239: out.print("<?");
240: out.print(node.getNodeName());
241: String data = node.getNodeValue();
242: if (data != null && data.length() > 0) {
243: out.print(' ');
244: out.print(data);
245: }
246: out.print("?>");
247: break;
248: }
249: }
250:
251: if (type == Node.ELEMENT_NODE) {
252: out.print("</");
253: out.print(node.getNodeName());
254: out.print('>');
255: }
256:
257: out.flush();
258:
259: } // print(Node)
260:
261: /** Returns a sorted list of attributes. */
262: protected Attr[] sortAttributes(NamedNodeMap attrs) {
263:
264: int len = (attrs != null) ? attrs.getLength() : 0;
265: Attr array[] = new Attr[len];
266: for (int i = 0; i < len; i++) {
267: array[i] = (Attr) attrs.item(i);
268: }
269: for (int i = 0; i < len - 1; i++) {
270: String name = array[i].getNodeName();
271: int index = i;
272: for (int j = i + 1; j < len; j++) {
273: String curName = array[j].getNodeName();
274: if (curName.compareTo(name) < 0) {
275: name = curName;
276: index = j;
277: }
278: }
279: if (index != i) {
280: Attr temp = array[i];
281: array[i] = array[index];
282: array[index] = temp;
283: }
284: }
285:
286: return (array);
287:
288: } // sortAttributes(NamedNodeMap):Attr[]
289:
290: /** Normalizes the given string. */
291: protected String normalize(String s) {
292: StringBuffer str = new StringBuffer();
293:
294: int len = (s != null) ? s.length() : 0;
295: for (int i = 0; i < len; i++) {
296: char ch = s.charAt(i);
297: switch (ch) {
298: case '<': {
299: str.append("<");
300: break;
301: }
302: case '>': {
303: str.append(">");
304: break;
305: }
306: case '&': {
307: str.append("&");
308: break;
309: }
310: case '"': {
311: str.append(""");
312: break;
313: }
314: case '\r':
315: case '\n': {
316: if (canonical) {
317: str.append("&#");
318: str.append(Integer.toString(ch));
319: str.append(';');
320: break;
321: }
322: // else, default append char
323: }
324: default: {
325: str.append(ch);
326: }
327: }
328: }
329:
330: return (str.toString());
331:
332: } // normalize(String):String
333:
334: private static void printValidJavaEncoding() {
335: System.err.println(" ENCODINGS:");
336: System.err.print(" ");
337: for (int i = 0; i < MIME2JAVA_ENCODINGS.length; i++) {
338: System.err.print(MIME2JAVA_ENCODINGS[i] + " ");
339: if ((i % 7) == 0) {
340: System.err.println();
341: System.err.print(" ");
342: }
343: }
344:
345: } // printJavaEncoding()
346:
347: }
|