001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.xml;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.xml.Attribute;
020    import com.liferay.portal.kernel.xml.Document;
021    import com.liferay.portal.kernel.xml.DocumentException;
022    import com.liferay.portal.kernel.xml.Element;
023    import com.liferay.portal.kernel.xml.Entity;
024    import com.liferay.portal.kernel.xml.Namespace;
025    import com.liferay.portal.kernel.xml.Node;
026    import com.liferay.portal.kernel.xml.ProcessingInstruction;
027    import com.liferay.portal.kernel.xml.QName;
028    import com.liferay.portal.kernel.xml.SAXReader;
029    import com.liferay.portal.kernel.xml.Text;
030    import com.liferay.portal.kernel.xml.XPath;
031    import com.liferay.portal.util.EntityResolver;
032    import com.liferay.util.xml.XMLSafeReader;
033    
034    import java.io.File;
035    import java.io.InputStream;
036    import java.io.Reader;
037    
038    import java.net.MalformedURLException;
039    import java.net.URL;
040    
041    import java.util.ArrayList;
042    import java.util.List;
043    import java.util.Map;
044    
045    import org.apache.xerces.parsers.SAXParser;
046    
047    import org.dom4j.DocumentFactory;
048    import org.dom4j.DocumentHelper;
049    
050    /**
051     * @author Brian Wing Shun Chan
052     */
053    public class SAXReaderImpl implements SAXReader {
054    
055            public static SAXReaderImpl getInstance() {
056                    return _instance;
057            }
058    
059            public static List<Attribute> toNewAttributes(
060                    List<org.dom4j.Attribute> oldAttributes) {
061    
062                    List<Attribute> newAttributes = new ArrayList<Attribute>(
063                            oldAttributes.size());
064    
065                    for (org.dom4j.Attribute oldAttribute : oldAttributes) {
066                            newAttributes.add(new AttributeImpl(oldAttribute));
067                    }
068    
069                    return new NodeList<Attribute, org.dom4j.Attribute>(
070                            newAttributes, oldAttributes);
071            }
072    
073            public static List<Element> toNewElements(
074                    List<org.dom4j.Element> oldElements) {
075    
076                    List<Element> newElements = new ArrayList<Element>(oldElements.size());
077    
078                    for (org.dom4j.Element oldElement : oldElements) {
079                            newElements.add(new ElementImpl(oldElement));
080                    }
081    
082                    return new NodeList<Element, org.dom4j.Element>(
083                            newElements, oldElements);
084            }
085    
086            public static List<Namespace> toNewNamespaces(
087                    List<org.dom4j.Namespace> oldNamespaces) {
088    
089                    List<Namespace> newNamespaces = new ArrayList<Namespace>(
090                            oldNamespaces.size());
091    
092                    for (org.dom4j.Namespace oldNamespace : oldNamespaces) {
093                            newNamespaces.add(new NamespaceImpl(oldNamespace));
094                    }
095    
096                    return new NodeList<Namespace, org.dom4j.Namespace>(
097                            newNamespaces, oldNamespaces);
098            }
099    
100            public static List<Node> toNewNodes(List<org.dom4j.Node> oldNodes) {
101                    List<Node> newNodes = new ArrayList<Node>(oldNodes.size());
102    
103                    for (org.dom4j.Node oldNode : oldNodes) {
104                            if (oldNode instanceof org.dom4j.Element) {
105                                    newNodes.add(new ElementImpl((org.dom4j.Element)oldNode));
106                            }
107                            else {
108                                    newNodes.add(new NodeImpl(oldNode));
109                            }
110                    }
111    
112                    return new NodeList<Node, org.dom4j.Node>(newNodes, oldNodes);
113            }
114    
115            public static List<ProcessingInstruction> toNewProcessingInstructions(
116                    List<org.dom4j.ProcessingInstruction> oldProcessingInstructions) {
117    
118                    List<ProcessingInstruction> newProcessingInstructions =
119                            new ArrayList<ProcessingInstruction>(
120                                    oldProcessingInstructions.size());
121    
122                    for (org.dom4j.ProcessingInstruction oldProcessingInstruction :
123                                    oldProcessingInstructions) {
124    
125                            newProcessingInstructions.add(
126                                    new ProcessingInstructionImpl(oldProcessingInstruction));
127                    }
128    
129                    return new NodeList
130                            <ProcessingInstruction, org.dom4j.ProcessingInstruction>(
131                                    newProcessingInstructions, oldProcessingInstructions);
132            }
133    
134            public static List<org.dom4j.Attribute> toOldAttributes(
135                    List<Attribute> newAttributes) {
136    
137                    List<org.dom4j.Attribute> oldAttributes =
138                            new ArrayList<org.dom4j.Attribute>(newAttributes.size());
139    
140                    for (Attribute newAttribute : newAttributes) {
141                            AttributeImpl newAttributeImpl = (AttributeImpl)newAttribute;
142    
143                            oldAttributes.add(newAttributeImpl.getWrappedAttribute());
144                    }
145    
146                    return oldAttributes;
147            }
148    
149            public static List<org.dom4j.Node> toOldNodes(List<Node> newNodes) {
150                    List<org.dom4j.Node> oldNodes = new ArrayList<org.dom4j.Node>(
151                            newNodes.size());
152    
153                    for (Node newNode : newNodes) {
154                            NodeImpl newNodeImpl = (NodeImpl)newNode;
155    
156                            oldNodes.add(newNodeImpl.getWrappedNode());
157                    }
158    
159                    return oldNodes;
160            }
161    
162            public static List<org.dom4j.ProcessingInstruction>
163                    toOldProcessingInstructions(
164                            List<ProcessingInstruction> newProcessingInstructions) {
165    
166                    List<org.dom4j.ProcessingInstruction> oldProcessingInstructions =
167                            new ArrayList<org.dom4j.ProcessingInstruction>(
168                                    newProcessingInstructions.size());
169    
170                    for (ProcessingInstruction newProcessingInstruction :
171                                    newProcessingInstructions) {
172    
173                            ProcessingInstructionImpl newProcessingInstructionImpl =
174                                    (ProcessingInstructionImpl)newProcessingInstruction;
175    
176                            oldProcessingInstructions.add(
177                                    newProcessingInstructionImpl.getWrappedProcessingInstruction());
178                    }
179    
180                    return oldProcessingInstructions;
181            }
182    
183            public Attribute createAttribute(
184                    Element element, QName qName, String value) {
185    
186                    ElementImpl elementImpl = (ElementImpl)element;
187                    QNameImpl qNameImpl = (QNameImpl)qName;
188    
189                    DocumentFactory documentFactory = DocumentFactory.getInstance();
190    
191                    return new AttributeImpl(
192                            documentFactory.createAttribute(
193                                    elementImpl.getWrappedElement(), qNameImpl.getWrappedQName(),
194                                    value));
195            }
196    
197            public Attribute createAttribute(
198                    Element element, String name, String value) {
199    
200                    ElementImpl elementImpl = (ElementImpl)element;
201    
202                    DocumentFactory documentFactory = DocumentFactory.getInstance();
203    
204                    return new AttributeImpl(
205                            documentFactory.createAttribute(
206                                    elementImpl.getWrappedElement(), name, value));
207            }
208    
209            public Document createDocument() {
210                    return new DocumentImpl(DocumentHelper.createDocument());
211            }
212    
213            public Document createDocument(Element rootElement) {
214                    ElementImpl rootElementImpl = (ElementImpl)rootElement;
215    
216                    return new DocumentImpl(
217                            DocumentHelper.createDocument(rootElementImpl.getWrappedElement()));
218            }
219    
220            public Document createDocument(String encoding) {
221                    DocumentFactory documentFactory = DocumentFactory.getInstance();
222    
223                    return new DocumentImpl(documentFactory.createDocument(encoding));
224            }
225    
226            public Element createElement(QName qName) {
227                    QNameImpl qNameImpl = (QNameImpl)qName;
228    
229                    return new ElementImpl(
230                            DocumentHelper.createElement(qNameImpl.getWrappedQName()));
231            }
232    
233            public Element createElement(String name) {
234                    return new ElementImpl(DocumentHelper.createElement(name));
235            }
236    
237            public Entity createEntity(String name, String text) {
238                    return new EntityImpl(DocumentHelper.createEntity(name, text));
239            }
240    
241            public Namespace createNamespace(String uri) {
242                    return new NamespaceImpl(org.dom4j.Namespace.get(uri));
243            }
244    
245            public Namespace createNamespace(String prefix, String uri) {
246                    return new NamespaceImpl(DocumentHelper.createNamespace(prefix, uri));
247            }
248    
249            public ProcessingInstruction createProcessingInstruction(
250                    String target, Map<String, String> data) {
251    
252                    org.dom4j.ProcessingInstruction processingInstruction =
253                            DocumentHelper.createProcessingInstruction(target, data);
254    
255                    if (processingInstruction == null) {
256                            return null;
257                    }
258                    else {
259                            return new ProcessingInstructionImpl(processingInstruction);
260                    }
261            }
262    
263            public ProcessingInstruction createProcessingInstruction(
264                    String target, String data) {
265    
266                    org.dom4j.ProcessingInstruction processingInstruction =
267                            DocumentHelper.createProcessingInstruction(target, data);
268    
269                    if (processingInstruction == null) {
270                            return null;
271                    }
272                    else {
273                            return new ProcessingInstructionImpl(processingInstruction);
274                    }
275            }
276    
277            public QName createQName(String localName) {
278                    return new QNameImpl(DocumentHelper.createQName(localName));
279            }
280    
281            public QName createQName(String localName, Namespace namespace) {
282                    NamespaceImpl namespaceImpl = (NamespaceImpl)namespace;
283    
284                    return new QNameImpl(
285                            DocumentHelper.createQName(
286                                    localName, namespaceImpl.getWrappedNamespace()));
287            }
288    
289            public Text createText(String text) {
290                    return new TextImpl(DocumentHelper.createText(text));
291            }
292    
293            public XPath createXPath(String xpathExpression) {
294                    return new XPathImpl(DocumentHelper.createXPath(xpathExpression));
295            }
296    
297            public List<Node> selectNodes(
298                    String xpathFilterExpression, List<Node> nodes) {
299    
300                    return toNewNodes(
301                            DocumentHelper.selectNodes(
302                                    xpathFilterExpression, toOldNodes(nodes)));
303            }
304    
305            public List<Node> selectNodes(
306                    String xpathFilterExpression, Node node) {
307    
308                    NodeImpl nodeImpl = (NodeImpl)node;
309    
310                    return toNewNodes(
311                            DocumentHelper.selectNodes(
312                                    xpathFilterExpression, nodeImpl.getWrappedNode()));
313            }
314    
315            public void sort(List<Node> nodes, String xpathExpression) {
316                    DocumentHelper.sort(toOldNodes(nodes), xpathExpression);
317            }
318    
319            public void sort(
320                    List<Node> nodes, String xpathExpression, boolean distinct) {
321    
322                    DocumentHelper.sort(toOldNodes(nodes), xpathExpression, distinct);
323            }
324    
325            public Document read(File file) throws DocumentException {
326                    return read(file, false);
327            }
328    
329            public Document read(File file, boolean validate)
330                    throws DocumentException {
331    
332                    try {
333                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
334    
335                            return new DocumentImpl(saxReader.read(file));
336                    }
337                    catch (org.dom4j.DocumentException de) {
338                            throw new DocumentException(de.getMessage(), de);
339                    }
340            }
341    
342            public Document read(InputStream is) throws DocumentException {
343                    return read(is, false);
344            }
345    
346            public Document read(InputStream is, boolean validate)
347                    throws DocumentException {
348    
349                    try {
350                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
351    
352                            return new DocumentImpl(saxReader.read(is));
353                    }
354                    catch (org.dom4j.DocumentException de) {
355                            throw new DocumentException(de.getMessage(), de);
356                    }
357            }
358    
359            public Document read(Reader reader) throws DocumentException {
360                    return read(reader, false);
361            }
362    
363            public Document read(Reader reader, boolean validate)
364                    throws DocumentException {
365    
366                    try {
367                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
368    
369                            return new DocumentImpl(saxReader.read(reader));
370                    }
371                    catch (org.dom4j.DocumentException de) {
372                            throw new DocumentException(de.getMessage(), de);
373                    }
374            }
375    
376            public Document read(String xml) throws DocumentException {
377                    return read(new XMLSafeReader(xml));
378            }
379    
380            public Document read(String xml, boolean validate)
381                    throws DocumentException {
382    
383                    return read(new XMLSafeReader(xml), validate);
384            }
385    
386            public Document read(URL url) throws DocumentException {
387                    return read(url, false);
388            }
389    
390            public Document read(URL url, boolean validate) throws DocumentException {
391                    try {
392                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
393    
394                            return new DocumentImpl(saxReader.read(url));
395                    }
396                    catch (org.dom4j.DocumentException de) {
397                            throw new DocumentException(de.getMessage(), de);
398                    }
399            }
400    
401            public Document readURL(String url)
402                    throws DocumentException, MalformedURLException {
403    
404                    return read(new URL(url), false);
405            }
406    
407            public Document readURL(String url, boolean validate)
408                    throws DocumentException, MalformedURLException {
409    
410                    return read(new URL(url), validate);
411            }
412    
413            protected org.dom4j.io.SAXReader getSAXReader(boolean validate) {
414                    org.dom4j.io.SAXReader reader = null;
415    
416                    try {
417                            reader = new org.dom4j.io.SAXReader(new SAXParser(), validate);
418    
419                            reader.setEntityResolver(new EntityResolver());
420    
421                            reader.setFeature(_FEATURES_VALIDATION, validate);
422                            reader.setFeature(_FEATURES_VALIDATION_SCHEMA, validate);
423                            reader.setFeature(
424                                    _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, validate);
425                            reader.setFeature(_FEATURES_DYNAMIC, validate);
426                    }
427                    catch (Exception e) {
428                            if (_log.isWarnEnabled()) {
429                                    _log.warn(
430                                            "XSD validation is diasabled because " + e.getMessage());
431                            }
432    
433                            reader = new org.dom4j.io.SAXReader(false);
434    
435                            reader.setEntityResolver(new EntityResolver());
436                    }
437    
438                    return reader;
439            }
440    
441            private static final String _FEATURES_VALIDATION =
442                    "http://xml.org/sax/features/validation";
443    
444            private static final String _FEATURES_VALIDATION_SCHEMA =
445                    "http://apache.org/xml/features/validation/schema";
446    
447            private static final String _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING =
448                    "http://apache.org/xml/features/validation/schema-full-checking";
449    
450            private static final String _FEATURES_DYNAMIC =
451                    "http://apache.org/xml/features/validation/dynamic";
452    
453            private static Log _log = LogFactoryUtil.getLog(SAXReaderImpl.class);
454    
455            private static SAXReaderImpl _instance = new SAXReaderImpl();
456    
457    }