1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.xml;
24  
25  import com.liferay.portal.kernel.xml.Attribute;
26  import com.liferay.portal.kernel.xml.Document;
27  import com.liferay.portal.kernel.xml.DocumentException;
28  import com.liferay.portal.kernel.xml.Element;
29  import com.liferay.portal.kernel.xml.Entity;
30  import com.liferay.portal.kernel.xml.Namespace;
31  import com.liferay.portal.kernel.xml.Node;
32  import com.liferay.portal.kernel.xml.ProcessingInstruction;
33  import com.liferay.portal.kernel.xml.QName;
34  import com.liferay.portal.kernel.xml.SAXReader;
35  import com.liferay.portal.kernel.xml.Text;
36  import com.liferay.portal.kernel.xml.XPath;
37  import com.liferay.portal.util.EntityResolver;
38  import com.liferay.util.xml.XMLSafeReader;
39  
40  import java.io.File;
41  import java.io.InputStream;
42  import java.io.Reader;
43  
44  import java.net.MalformedURLException;
45  import java.net.URL;
46  
47  import java.util.ArrayList;
48  import java.util.List;
49  import java.util.Map;
50  
51  import org.apache.commons.logging.Log;
52  import org.apache.commons.logging.LogFactory;
53  
54  import org.dom4j.DocumentFactory;
55  import org.dom4j.DocumentHelper;
56  
57  /**
58   * <a href="SAXReaderImpl.java.html"><b><i>View Source</i></b></a>
59   *
60   * @author Brian Wing Shun Chan
61   *
62   */
63  public class SAXReaderImpl implements SAXReader {
64  
65      public static List<Attribute> toNewAttributes(
66          List<org.dom4j.Attribute> oldAttributes) {
67  
68          List<Attribute> newAttributes = new ArrayList<Attribute>(
69              oldAttributes.size());
70  
71          for (org.dom4j.Attribute oldAttribute : oldAttributes) {
72              newAttributes.add(new AttributeImpl(oldAttribute));
73          }
74  
75          return new NodeList<Attribute, org.dom4j.Attribute>(
76              newAttributes, oldAttributes);
77      }
78  
79      public static List<Element> toNewElements(
80          List<org.dom4j.Element> oldElements) {
81  
82          List<Element> newElements = new ArrayList<Element>(oldElements.size());
83  
84          for (org.dom4j.Element oldElement : oldElements) {
85              newElements.add(new ElementImpl(oldElement));
86          }
87  
88          return new NodeList<Element, org.dom4j.Element>(
89              newElements, oldElements);
90      }
91  
92      public static List<Namespace> toNewNamespaces(
93          List<org.dom4j.Namespace> oldNamespaces) {
94  
95          List<Namespace> newNamespaces = new ArrayList<Namespace>(
96              oldNamespaces.size());
97  
98          for (org.dom4j.Namespace oldNamespace : oldNamespaces) {
99              newNamespaces.add(new NamespaceImpl(oldNamespace));
100         }
101 
102         return new NodeList<Namespace, org.dom4j.Namespace>(
103             newNamespaces, oldNamespaces);
104     }
105 
106     public static List<Node> toNewNodes(List<org.dom4j.Node> oldNodes) {
107         List<Node> newNodes = new ArrayList<Node>(oldNodes.size());
108 
109         for (org.dom4j.Node oldNode : oldNodes) {
110             if (oldNode instanceof org.dom4j.Element) {
111                 newNodes.add(new ElementImpl((org.dom4j.Element)oldNode));
112             }
113             else {
114                 newNodes.add(new NodeImpl(oldNode));
115             }
116         }
117 
118         return new NodeList<Node, org.dom4j.Node>(newNodes, oldNodes);
119     }
120 
121     public static List<ProcessingInstruction> toNewProcessingInstructions(
122         List<org.dom4j.ProcessingInstruction> oldProcessingInstructions) {
123 
124         List<ProcessingInstruction> newProcessingInstructions =
125             new ArrayList<ProcessingInstruction>(
126                 oldProcessingInstructions.size());
127 
128         for (org.dom4j.ProcessingInstruction oldProcessingInstruction :
129                 oldProcessingInstructions) {
130 
131             newProcessingInstructions.add(
132                 new ProcessingInstructionImpl(oldProcessingInstruction));
133         }
134 
135         return new NodeList
136             <ProcessingInstruction, org.dom4j.ProcessingInstruction>(
137                 newProcessingInstructions, oldProcessingInstructions);
138     }
139 
140     public static List<org.dom4j.Attribute> toOldAttributes(
141         List<Attribute> newAttributes) {
142 
143         List<org.dom4j.Attribute> oldAttributes =
144             new ArrayList<org.dom4j.Attribute>(newAttributes.size());
145 
146         for (Attribute newAttribute : newAttributes) {
147             AttributeImpl newAttributeImpl = (AttributeImpl)newAttribute;
148 
149             oldAttributes.add(newAttributeImpl.getWrappedAttribute());
150         }
151 
152         return oldAttributes;
153     }
154 
155     public static List<org.dom4j.Node> toOldNodes(List<Node> newNodes) {
156         List<org.dom4j.Node> oldNodes = new ArrayList<org.dom4j.Node>(
157             newNodes.size());
158 
159         for (Node newNode : newNodes) {
160             NodeImpl newNodeImpl = (NodeImpl)newNode;
161 
162             oldNodes.add(newNodeImpl.getWrappedNode());
163         }
164 
165         return oldNodes;
166     }
167 
168     public static List<org.dom4j.ProcessingInstruction>
169         toOldProcessingInstructions(
170             List<ProcessingInstruction> newProcessingInstructions) {
171 
172         List<org.dom4j.ProcessingInstruction> oldProcessingInstructions =
173             new ArrayList<org.dom4j.ProcessingInstruction>(
174                 newProcessingInstructions.size());
175 
176         for (ProcessingInstruction newProcessingInstruction :
177                 newProcessingInstructions) {
178 
179             ProcessingInstructionImpl newProcessingInstructionImpl =
180                 (ProcessingInstructionImpl)newProcessingInstruction;
181 
182             oldProcessingInstructions.add(
183                 newProcessingInstructionImpl.getWrappedProcessingInstruction());
184         }
185 
186         return oldProcessingInstructions;
187     }
188 
189     public Attribute createAttribute(
190         Element element, QName qName, String value) {
191 
192         ElementImpl elementImpl = (ElementImpl)element;
193         QNameImpl qNameImpl = (QNameImpl)qName;
194 
195         DocumentFactory documentFactory = DocumentFactory.getInstance();
196 
197         return new AttributeImpl(
198             documentFactory.createAttribute(
199                 elementImpl.getWrappedElement(), qNameImpl.getWrappedQName(),
200                 value));
201     }
202 
203     public Attribute createAttribute(
204         Element element, String name, String value) {
205 
206         ElementImpl elementImpl = (ElementImpl)element;
207 
208         DocumentFactory documentFactory = DocumentFactory.getInstance();
209 
210         return new AttributeImpl(
211             documentFactory.createAttribute(
212                 elementImpl.getWrappedElement(), name, value));
213     }
214 
215     public Document createDocument() {
216         return new DocumentImpl(DocumentHelper.createDocument());
217     }
218 
219     public Document createDocument(Element rootElement) {
220         ElementImpl rootElementImpl = (ElementImpl)rootElement;
221 
222         return new DocumentImpl(
223             DocumentHelper.createDocument(rootElementImpl.getWrappedElement()));
224     }
225 
226     public Document createDocument(String encoding) {
227         DocumentFactory documentFactory = DocumentFactory.getInstance();
228 
229         return new DocumentImpl(documentFactory.createDocument(encoding));
230     }
231 
232     public Element createElement(QName qName) {
233         QNameImpl qNameImpl = (QNameImpl)qName;
234 
235         return new ElementImpl(
236             DocumentHelper.createElement(qNameImpl.getWrappedQName()));
237     }
238 
239     public Element createElement(String name) {
240         return new ElementImpl(DocumentHelper.createElement(name));
241     }
242 
243     public Entity createEntity(String name, String text) {
244         return new EntityImpl(DocumentHelper.createEntity(name, text));
245     }
246 
247     public Namespace createNamespace(String uri) {
248         return new NamespaceImpl(org.dom4j.Namespace.get(uri));
249     }
250 
251     public Namespace createNamespace(String prefix, String uri) {
252         return new NamespaceImpl(DocumentHelper.createNamespace(prefix, uri));
253     }
254 
255     public ProcessingInstruction createProcessingInstruction(
256         String target, Map<String, String> data) {
257 
258         org.dom4j.ProcessingInstruction processingInstruction =
259             DocumentHelper.createProcessingInstruction(target, data);
260 
261         if (processingInstruction == null) {
262             return null;
263         }
264         else {
265             return new ProcessingInstructionImpl(processingInstruction);
266         }
267     }
268 
269     public ProcessingInstruction createProcessingInstruction(
270         String target, String data) {
271 
272         org.dom4j.ProcessingInstruction processingInstruction =
273             DocumentHelper.createProcessingInstruction(target, data);
274 
275         if (processingInstruction == null) {
276             return null;
277         }
278         else {
279             return new ProcessingInstructionImpl(processingInstruction);
280         }
281     }
282 
283     public QName createQName(String localName) {
284         return new QNameImpl(DocumentHelper.createQName(localName));
285     }
286 
287     public QName createQName(String localName, Namespace namespace) {
288         NamespaceImpl namespaceImpl = (NamespaceImpl)namespace;
289 
290         return new QNameImpl(
291             DocumentHelper.createQName(
292                 localName, namespaceImpl.getWrappedNamespace()));
293     }
294 
295     public Text createText(String text) {
296         return new TextImpl(DocumentHelper.createText(text));
297     }
298 
299     public XPath createXPath(String xpathExpression) {
300         return new XPathImpl(DocumentHelper.createXPath(xpathExpression));
301     }
302 
303     public List<Node> selectNodes(
304         String xpathFilterExpression, List<Node> nodes) {
305 
306         return toNewNodes(
307             DocumentHelper.selectNodes(
308                 xpathFilterExpression, toOldNodes(nodes)));
309     }
310 
311     public List<Node> selectNodes(
312         String xpathFilterExpression, Node node) {
313 
314         NodeImpl nodeImpl = (NodeImpl)node;
315 
316         return toNewNodes(
317             DocumentHelper.selectNodes(
318                 xpathFilterExpression, nodeImpl.getWrappedNode()));
319     }
320 
321     public void sort(List<Node> nodes, String xpathExpression) {
322         DocumentHelper.sort(toOldNodes(nodes), xpathExpression);
323     }
324 
325     public void sort(
326         List<Node> nodes, String xpathExpression, boolean distinct) {
327 
328         DocumentHelper.sort(toOldNodes(nodes), xpathExpression, distinct);
329     }
330 
331     public Document read(File file) throws DocumentException {
332         return read(file, false);
333     }
334 
335     public Document read(File file, boolean validate)
336         throws DocumentException {
337 
338         try {
339             org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
340 
341             return new DocumentImpl(saxReader.read(file));
342         }
343         catch (org.dom4j.DocumentException de) {
344             throw new DocumentException(de.getMessage());
345         }
346     }
347 
348     public Document read(InputStream is) throws DocumentException {
349         return read(is, false);
350     }
351 
352     public Document read(InputStream is, boolean validate)
353         throws DocumentException {
354 
355         try {
356             org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
357 
358             return new DocumentImpl(saxReader.read(is));
359         }
360         catch (org.dom4j.DocumentException de) {
361             throw new DocumentException(de.getMessage());
362         }
363     }
364 
365     public Document read(Reader reader) throws DocumentException {
366         return read(reader, false);
367     }
368 
369     public Document read(Reader reader, boolean validate)
370         throws DocumentException {
371 
372         try {
373             org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
374 
375             return new DocumentImpl(saxReader.read(reader));
376         }
377         catch (org.dom4j.DocumentException de) {
378             throw new DocumentException(de.getMessage());
379         }
380     }
381 
382     public Document read(String xml) throws DocumentException {
383         return read(new XMLSafeReader(xml));
384     }
385 
386     public Document read(String xml, boolean validate)
387         throws DocumentException {
388 
389         return read(new XMLSafeReader(xml), validate);
390     }
391 
392     public Document read(URL url) throws DocumentException {
393         return read(url, false);
394     }
395 
396     public Document read(URL url, boolean validate) throws DocumentException {
397         try {
398             org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
399 
400             return new DocumentImpl(saxReader.read(url));
401         }
402         catch (org.dom4j.DocumentException de) {
403             throw new DocumentException(de.getMessage());
404         }
405     }
406 
407     public Document readURL(String url)
408         throws DocumentException, MalformedURLException {
409 
410         return read(new URL(url), false);
411     }
412 
413     public Document readURL(String url, boolean validate)
414         throws DocumentException, MalformedURLException {
415 
416         return read(new URL(url), validate);
417     }
418 
419     protected org.dom4j.io.SAXReader getSAXReader(boolean validate) {
420 
421         // Crimson cannot do XSD validation. See the following links:
422         //
423         // http://www.geocities.com/herong_yang/jdk/xsd_validation.html
424         // http://www.burnthacker.com/archives/000086.html
425         // http://www.theserverside.com/news/thread.tss?thread_id=22525
426 
427         org.dom4j.io.SAXReader reader = null;
428 
429         try {
430             reader = new org.dom4j.io.SAXReader(_SAX_PARSER_IMPL, validate);
431 
432             reader.setEntityResolver(new EntityResolver());
433 
434             reader.setFeature(_FEATURES_VALIDATION, validate);
435             reader.setFeature(_FEATURES_VALIDATION_SCHEMA, validate);
436             reader.setFeature(
437                 _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, validate);
438             reader.setFeature(_FEATURES_DYNAMIC, validate);
439         }
440         catch (Exception e) {
441             _log.warn("XSD validation is diasabled because " + e.getMessage());
442 
443             reader = new org.dom4j.io.SAXReader(validate);
444 
445             reader.setEntityResolver(new EntityResolver());
446         }
447 
448         return reader;
449     }
450 
451     private static final String _SAX_PARSER_IMPL =
452         "org.apache.xerces.parsers.SAXParser";
453 
454     private static final String _FEATURES_VALIDATION =
455         "http://xml.org/sax/features/validation";
456 
457     private static final String _FEATURES_VALIDATION_SCHEMA =
458         "http://apache.org/xml/features/validation/schema";
459 
460     private static final String _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING =
461         "http://apache.org/xml/features/validation/schema-full-checking";
462 
463     private static final String _FEATURES_DYNAMIC =
464         "http://apache.org/xml/features/validation/dynamic";
465 
466     private static Log _log = LogFactory.getLog(SAXReaderImpl.class);
467 
468 }