1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package com.sun.star.script.framework.container;
29 
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.io.IOException;
33 import java.lang.reflect.Method;
34 
35 import javax.xml.parsers.*;
36 import org.w3c.dom.Document;
37 import org.xml.sax.InputSource;
38 import org.xml.sax.SAXException;
39 import org.xml.sax.SAXParseException;
40 
41 public class XMLParserFactory {
42 
43     private static XMLParser parser = null;
44     private static String officedtdurl = null;
45 
46     private XMLParserFactory() {}
47 
48     public static XMLParser getParser() {
49         if (parser == null) {
50             synchronized (XMLParserFactory.class) {
51                 if (parser == null)
52                     parser = new DefaultParser();
53             }
54         }
55         return parser;
56     }
57 
58     public static void setParser(XMLParser p) {
59         parser = p;
60     }
61 
62     public static void setOfficeDTDURL(String url) {
63         officedtdurl = url;
64     }
65 
66     private static class DefaultParser implements XMLParser {
67 
68         private DocumentBuilderFactory factory;
69 
70         public DefaultParser() {
71             factory = DocumentBuilderFactory.newInstance();
72         }
73 
74         public Document parse(InputStream inputStream) throws IOException {
75             Document result = null;
76             InputSource is = null;
77 
78             try {
79                 DocumentBuilder builder = factory.newDocumentBuilder();
80 
81                 is = new InputSource(inputStream);
82 
83                 if (officedtdurl != null) {
84                     is.setSystemId(officedtdurl);
85                 }
86 
87                 result = builder.parse(is);
88             }
89             catch (SAXParseException spe) {
90                 throw new IOException(spe.getMessage());
91             }
92             catch (SAXException se) {
93                 throw new IOException(se.getMessage());
94             }
95             catch (ParserConfigurationException pce) {
96                 throw new IOException(pce.getMessage());
97             }
98             return result;
99         }
100 
101         public void write(Document doc, OutputStream out) throws IOException {
102             Class clazz = doc.getClass();
103             String name = clazz.getName();
104 
105             // depending on the class of the Document object use introspection
106             // to invoke the appropriate methods for writing the XML
107             // this code is based on the code used by the NetBeans
108             // class XMLUtilImpl in the openide module
109             try {
110                 if (name.equals("com.sun.xml.tree.XmlDocument") ||
111                     name.equals("org.apache.crimson.tree.XmlDocument")) {
112 
113                     // these DOM implementations are self writing
114                     Method write;
115                     write = clazz.getDeclaredMethod("write",
116                         new Class[] {OutputStream.class});
117                     write.invoke(doc, new Object[] {out});
118                 }
119                 else {
120                     // try xerces serialize package using introspection
121                     ClassLoader cl = this.getClass().getClassLoader();
122 
123                     Class serializerClass = null;
124                     Class formatterClass = null;
125 
126                     try {
127                         serializerClass = Class.forName(
128                             "org.apache.xml.serialize.XMLSerializer", true, cl);
129                         formatterClass = Class.forName(
130                             "org.apache.xml.serialize.OutputFormat", true, cl);
131                     } catch (ClassNotFoundException cnfe) {
132                         String prefix = "com.sun.org.apache.xml.internal.";
133 
134                         serializerClass = Class.forName(
135                             prefix +  "serialize.XMLSerializer" , true, cl);
136                         formatterClass = Class.forName(
137                             prefix + "serialize.OutputFormat", true, cl);
138                     }
139 
140                     Object serializerObject = serializerClass.newInstance();
141                     Object formatterObject = formatterClass.newInstance();
142 
143                     // improve output readability using the OutputFormat class
144                     Method method = null;
145                     method = formatterClass.getMethod("setMethod",
146                         new Class[] {String.class});
147                     method.invoke(formatterObject, new Object[] {"xml"});
148                     method = formatterClass.getMethod("setIndenting",
149                         new Class[] {Boolean.TYPE});
150                     method.invoke(formatterObject, new Object[] {Boolean.TRUE});
151 
152                     // now set up an instance of XMLSerializer with our
153                     // OutputStream and serialize our Document
154                     method = serializerClass.getMethod("setOutputByteStream",
155                         new Class[] {OutputStream.class});
156                     method.invoke(serializerObject, new Object[] {out});
157                     method = serializerClass.getMethod("setOutputFormat",
158                         new Class[] {formatterClass});
159                     method.invoke(serializerObject,
160                         new Object[] {formatterObject});
161 
162                     method = serializerClass.getMethod("asDOMSerializer",
163                         new Class[0]);
164                     Object impl = method.invoke(serializerObject,
165                         new Object[0]);
166 
167                     method = impl.getClass().getMethod("serialize",
168                         new Class[] {Document.class});
169                     method.invoke(impl, new Object[] {doc});
170                 }
171             } catch (NoSuchMethodException ex) {
172                 throw new IOException(ex.getMessage());
173             } catch (ClassNotFoundException ex) {
174                 throw new IOException(ex.getMessage());
175             } catch (Exception ex) {
176                 throw new IOException(ex.getMessage());
177             }
178         }
179     }
180 }
181