001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.portal.util.PropsValues;
033    import com.liferay.util.xml.XMLSafeReader;
034    
035    import java.io.File;
036    import java.io.InputStream;
037    import java.io.Reader;
038    
039    import java.net.MalformedURLException;
040    import java.net.URL;
041    
042    import java.util.ArrayList;
043    import java.util.List;
044    import java.util.Map;
045    
046    import org.apache.xerces.parsers.SAXParser;
047    
048    import org.dom4j.DocumentFactory;
049    import org.dom4j.DocumentHelper;
050    
051    /**
052     * @author Brian Wing Shun Chan
053     */
054    public class SAXReaderImpl implements SAXReader {
055    
056            public static SAXReaderImpl getInstance() {
057                    return _instance;
058            }
059    
060            public static List<Attribute> toNewAttributes(
061                    List<org.dom4j.Attribute> oldAttributes) {
062    
063                    List<Attribute> newAttributes = new ArrayList<Attribute>(
064                            oldAttributes.size());
065    
066                    for (org.dom4j.Attribute oldAttribute : oldAttributes) {
067                            newAttributes.add(new AttributeImpl(oldAttribute));
068                    }
069    
070                    return new NodeList<Attribute, org.dom4j.Attribute>(
071                            newAttributes, oldAttributes);
072            }
073    
074            public static List<Element> toNewElements(
075                    List<org.dom4j.Element> oldElements) {
076    
077                    List<Element> newElements = new ArrayList<Element>(oldElements.size());
078    
079                    for (org.dom4j.Element oldElement : oldElements) {
080                            newElements.add(new ElementImpl(oldElement));
081                    }
082    
083                    return new NodeList<Element, org.dom4j.Element>(
084                            newElements, oldElements);
085            }
086    
087            public static List<Namespace> toNewNamespaces(
088                    List<org.dom4j.Namespace> oldNamespaces) {
089    
090                    List<Namespace> newNamespaces = new ArrayList<Namespace>(
091                            oldNamespaces.size());
092    
093                    for (org.dom4j.Namespace oldNamespace : oldNamespaces) {
094                            newNamespaces.add(new NamespaceImpl(oldNamespace));
095                    }
096    
097                    return new NodeList<Namespace, org.dom4j.Namespace>(
098                            newNamespaces, oldNamespaces);
099            }
100    
101            public static List<Node> toNewNodes(List<org.dom4j.Node> oldNodes) {
102                    List<Node> newNodes = new ArrayList<Node>(oldNodes.size());
103    
104                    for (org.dom4j.Node oldNode : oldNodes) {
105                            if (oldNode instanceof org.dom4j.Element) {
106                                    newNodes.add(new ElementImpl((org.dom4j.Element)oldNode));
107                            }
108                            else {
109                                    newNodes.add(new NodeImpl(oldNode));
110                            }
111                    }
112    
113                    return new NodeList<Node, org.dom4j.Node>(newNodes, oldNodes);
114            }
115    
116            public static List<ProcessingInstruction> toNewProcessingInstructions(
117                    List<org.dom4j.ProcessingInstruction> oldProcessingInstructions) {
118    
119                    List<ProcessingInstruction> newProcessingInstructions =
120                            new ArrayList<ProcessingInstruction>(
121                                    oldProcessingInstructions.size());
122    
123                    for (org.dom4j.ProcessingInstruction oldProcessingInstruction :
124                                    oldProcessingInstructions) {
125    
126                            newProcessingInstructions.add(
127                                    new ProcessingInstructionImpl(oldProcessingInstruction));
128                    }
129    
130                    return new NodeList
131                            <ProcessingInstruction, org.dom4j.ProcessingInstruction>(
132                                    newProcessingInstructions, oldProcessingInstructions);
133            }
134    
135            public static List<org.dom4j.Attribute> toOldAttributes(
136                    List<Attribute> newAttributes) {
137    
138                    List<org.dom4j.Attribute> oldAttributes =
139                            new ArrayList<org.dom4j.Attribute>(newAttributes.size());
140    
141                    for (Attribute newAttribute : newAttributes) {
142                            AttributeImpl newAttributeImpl = (AttributeImpl)newAttribute;
143    
144                            oldAttributes.add(newAttributeImpl.getWrappedAttribute());
145                    }
146    
147                    return oldAttributes;
148            }
149    
150            public static List<org.dom4j.Node> toOldNodes(List<Node> newNodes) {
151                    List<org.dom4j.Node> oldNodes = new ArrayList<org.dom4j.Node>(
152                            newNodes.size());
153    
154                    for (Node newNode : newNodes) {
155                            NodeImpl newNodeImpl = (NodeImpl)newNode;
156    
157                            oldNodes.add(newNodeImpl.getWrappedNode());
158                    }
159    
160                    return oldNodes;
161            }
162    
163            public static List<org.dom4j.ProcessingInstruction>
164                    toOldProcessingInstructions(
165                            List<ProcessingInstruction> newProcessingInstructions) {
166    
167                    List<org.dom4j.ProcessingInstruction> oldProcessingInstructions =
168                            new ArrayList<org.dom4j.ProcessingInstruction>(
169                                    newProcessingInstructions.size());
170    
171                    for (ProcessingInstruction newProcessingInstruction :
172                                    newProcessingInstructions) {
173    
174                            ProcessingInstructionImpl newProcessingInstructionImpl =
175                                    (ProcessingInstructionImpl)newProcessingInstruction;
176    
177                            oldProcessingInstructions.add(
178                                    newProcessingInstructionImpl.getWrappedProcessingInstruction());
179                    }
180    
181                    return oldProcessingInstructions;
182            }
183    
184            public Attribute createAttribute(
185                    Element element, QName qName, String value) {
186    
187                    ElementImpl elementImpl = (ElementImpl)element;
188                    QNameImpl qNameImpl = (QNameImpl)qName;
189    
190                    DocumentFactory documentFactory = DocumentFactory.getInstance();
191    
192                    return new AttributeImpl(
193                            documentFactory.createAttribute(
194                                    elementImpl.getWrappedElement(), qNameImpl.getWrappedQName(),
195                                    value));
196            }
197    
198            public Attribute createAttribute(
199                    Element element, String name, String value) {
200    
201                    ElementImpl elementImpl = (ElementImpl)element;
202    
203                    DocumentFactory documentFactory = DocumentFactory.getInstance();
204    
205                    return new AttributeImpl(
206                            documentFactory.createAttribute(
207                                    elementImpl.getWrappedElement(), name, value));
208            }
209    
210            public Document createDocument() {
211                    return new DocumentImpl(DocumentHelper.createDocument());
212            }
213    
214            public Document createDocument(Element rootElement) {
215                    ElementImpl rootElementImpl = (ElementImpl)rootElement;
216    
217                    return new DocumentImpl(
218                            DocumentHelper.createDocument(rootElementImpl.getWrappedElement()));
219            }
220    
221            public Document createDocument(String encoding) {
222                    DocumentFactory documentFactory = DocumentFactory.getInstance();
223    
224                    return new DocumentImpl(documentFactory.createDocument(encoding));
225            }
226    
227            public Element createElement(QName qName) {
228                    QNameImpl qNameImpl = (QNameImpl)qName;
229    
230                    return new ElementImpl(
231                            DocumentHelper.createElement(qNameImpl.getWrappedQName()));
232            }
233    
234            public Element createElement(String name) {
235                    return new ElementImpl(DocumentHelper.createElement(name));
236            }
237    
238            public Entity createEntity(String name, String text) {
239                    return new EntityImpl(DocumentHelper.createEntity(name, text));
240            }
241    
242            public Namespace createNamespace(String uri) {
243                    return new NamespaceImpl(org.dom4j.Namespace.get(uri));
244            }
245    
246            public Namespace createNamespace(String prefix, String uri) {
247                    return new NamespaceImpl(DocumentHelper.createNamespace(prefix, uri));
248            }
249    
250            public ProcessingInstruction createProcessingInstruction(
251                    String target, Map<String, String> data) {
252    
253                    org.dom4j.ProcessingInstruction processingInstruction =
254                            DocumentHelper.createProcessingInstruction(target, data);
255    
256                    if (processingInstruction == null) {
257                            return null;
258                    }
259                    else {
260                            return new ProcessingInstructionImpl(processingInstruction);
261                    }
262            }
263    
264            public ProcessingInstruction createProcessingInstruction(
265                    String target, String data) {
266    
267                    org.dom4j.ProcessingInstruction processingInstruction =
268                            DocumentHelper.createProcessingInstruction(target, data);
269    
270                    if (processingInstruction == null) {
271                            return null;
272                    }
273                    else {
274                            return new ProcessingInstructionImpl(processingInstruction);
275                    }
276            }
277    
278            public QName createQName(String localName) {
279                    return new QNameImpl(DocumentHelper.createQName(localName));
280            }
281    
282            public QName createQName(String localName, Namespace namespace) {
283                    NamespaceImpl namespaceImpl = (NamespaceImpl)namespace;
284    
285                    return new QNameImpl(
286                            DocumentHelper.createQName(
287                                    localName, namespaceImpl.getWrappedNamespace()));
288            }
289    
290            public Text createText(String text) {
291                    return new TextImpl(DocumentHelper.createText(text));
292            }
293    
294            public XPath createXPath(String xPathExpression) {
295                    return new XPathImpl(DocumentHelper.createXPath(xPathExpression));
296            }
297    
298            public List<Node> selectNodes(
299                    String xpathFilterExpression, List<Node> nodes) {
300    
301                    return toNewNodes(
302                            DocumentHelper.selectNodes(
303                                    xpathFilterExpression, toOldNodes(nodes)));
304            }
305    
306            public List<Node> selectNodes(
307                    String xpathFilterExpression, Node node) {
308    
309                    NodeImpl nodeImpl = (NodeImpl)node;
310    
311                    return toNewNodes(
312                            DocumentHelper.selectNodes(
313                                    xpathFilterExpression, nodeImpl.getWrappedNode()));
314            }
315    
316            public void sort(List<Node> nodes, String xpathExpression) {
317                    DocumentHelper.sort(toOldNodes(nodes), xpathExpression);
318            }
319    
320            public void sort(
321                    List<Node> nodes, String xpathExpression, boolean distinct) {
322    
323                    DocumentHelper.sort(toOldNodes(nodes), xpathExpression, distinct);
324            }
325    
326            public Document read(File file) throws DocumentException {
327                    return read(file, false);
328            }
329    
330            public Document read(File file, boolean validate)
331                    throws DocumentException {
332    
333                    ClassLoader classLoader = getClass().getClassLoader();
334    
335                    Thread currentThread = Thread.currentThread();
336    
337                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
338    
339                    try {
340                            if (contextClassLoader != classLoader) {
341                                    currentThread.setContextClassLoader(classLoader);
342                            }
343    
344                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
345    
346                            return new DocumentImpl(saxReader.read(file));
347                    }
348                    catch (org.dom4j.DocumentException de) {
349                            throw new DocumentException(de.getMessage(), de);
350                    }
351                    finally {
352                            if (contextClassLoader != classLoader) {
353                                    currentThread.setContextClassLoader(contextClassLoader);
354                            }
355                    }
356            }
357    
358            public Document read(InputStream is) throws DocumentException {
359                    return read(is, false);
360            }
361    
362            public Document read(InputStream is, boolean validate)
363                    throws DocumentException {
364    
365                    ClassLoader classLoader = getClass().getClassLoader();
366    
367                    Thread currentThread = Thread.currentThread();
368    
369                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
370    
371                    try {
372                            if (contextClassLoader != classLoader) {
373                                    currentThread.setContextClassLoader(classLoader);
374                            }
375    
376                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
377    
378                            return new DocumentImpl(saxReader.read(is));
379                    }
380                    catch (org.dom4j.DocumentException de) {
381                            throw new DocumentException(de.getMessage(), de);
382                    }
383                    finally {
384                            if (contextClassLoader != classLoader) {
385                                    currentThread.setContextClassLoader(contextClassLoader);
386                            }
387                    }
388            }
389    
390            public Document read(Reader reader) throws DocumentException {
391                    return read(reader, false);
392            }
393    
394            public Document read(Reader reader, boolean validate)
395                    throws DocumentException {
396    
397                    ClassLoader classLoader = getClass().getClassLoader();
398    
399                    Thread currentThread = Thread.currentThread();
400    
401                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
402    
403                    try {
404                            if (contextClassLoader != classLoader) {
405                                    currentThread.setContextClassLoader(classLoader);
406                            }
407    
408                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
409    
410                            return new DocumentImpl(saxReader.read(reader));
411                    }
412                    catch (org.dom4j.DocumentException de) {
413                            throw new DocumentException(de.getMessage(), de);
414                    }
415                    finally {
416                            if (contextClassLoader != classLoader) {
417                                    currentThread.setContextClassLoader(contextClassLoader);
418                            }
419                    }
420            }
421    
422            public Document read(String xml) throws DocumentException {
423                    return read(new XMLSafeReader(xml));
424            }
425    
426            public Document read(String xml, boolean validate)
427                    throws DocumentException {
428    
429                    return read(new XMLSafeReader(xml), validate);
430            }
431    
432            public Document read(URL url) throws DocumentException {
433                    return read(url, false);
434            }
435    
436            public Document read(URL url, boolean validate) throws DocumentException {
437                    ClassLoader classLoader = getClass().getClassLoader();
438    
439                    Thread currentThread = Thread.currentThread();
440    
441                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
442    
443                    try {
444                            if (contextClassLoader != classLoader) {
445                                    currentThread.setContextClassLoader(classLoader);
446                            }
447    
448                            org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
449    
450                            return new DocumentImpl(saxReader.read(url));
451                    }
452                    catch (org.dom4j.DocumentException de) {
453                            throw new DocumentException(de.getMessage(), de);
454                    }
455                    finally {
456                            if (contextClassLoader != classLoader) {
457                                    currentThread.setContextClassLoader(contextClassLoader);
458                            }
459                    }
460            }
461    
462            public Document readURL(String url)
463                    throws DocumentException, MalformedURLException {
464    
465                    return read(new URL(url), false);
466            }
467    
468            public Document readURL(String url, boolean validate)
469                    throws DocumentException, MalformedURLException {
470    
471                    return read(new URL(url), validate);
472            }
473    
474            protected org.dom4j.io.SAXReader getSAXReader(boolean validate) {
475                    org.dom4j.io.SAXReader reader = null;
476    
477                    if (!PropsValues.XML_VALIDATION_ENABLED) {
478                            validate = false;
479                    }
480    
481                    try {
482                            reader = new org.dom4j.io.SAXReader(new SAXParser(), validate);
483    
484                            reader.setEntityResolver(new EntityResolver());
485    
486                            reader.setFeature(_FEATURES_DYNAMIC, validate);
487                            reader.setFeature(_FEATURES_VALIDATION, validate);
488                            reader.setFeature(_FEATURES_VALIDATION_SCHEMA, validate);
489                            reader.setFeature(
490                                    _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, validate);
491    
492                            if (!validate) {
493                                    reader.setFeature(_FEATURES_LOAD_DTD_GRAMMAR, validate);
494                                    reader.setFeature(_FEATURES_LOAD_EXTERNAL_DTD, validate);
495                            }
496                    }
497                    catch (Exception e) {
498                            if (_log.isWarnEnabled()) {
499                                    _log.warn(
500                                            "XSD validation is disabled because " + e.getMessage());
501                            }
502    
503                            reader = new org.dom4j.io.SAXReader(false);
504    
505                            reader.setEntityResolver(new EntityResolver());
506                    }
507    
508                    return reader;
509            }
510    
511            private static final String _FEATURES_DYNAMIC =
512                    "http://apache.org/xml/features/validation/dynamic";
513    
514            private static final String _FEATURES_LOAD_DTD_GRAMMAR =
515                    "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
516    
517            private static final String _FEATURES_LOAD_EXTERNAL_DTD =
518                    "http://apache.org/xml/features/nonvalidating/load-external-dtd";
519    
520            private static final String _FEATURES_VALIDATION =
521                    "http://xml.org/sax/features/validation";
522    
523            private static final String _FEATURES_VALIDATION_SCHEMA =
524                    "http://apache.org/xml/features/validation/schema";
525    
526            private static final String _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING =
527                    "http://apache.org/xml/features/validation/schema-full-checking";
528    
529            private static Log _log = LogFactoryUtil.getLog(SAXReaderImpl.class);
530    
531            private static SAXReaderImpl _instance = new SAXReaderImpl();
532    
533    }