001
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.security.pacl.DoPrivileged;
020 import com.liferay.portal.kernel.xml.Attribute;
021 import com.liferay.portal.kernel.xml.Document;
022 import com.liferay.portal.kernel.xml.DocumentException;
023 import com.liferay.portal.kernel.xml.Element;
024 import com.liferay.portal.kernel.xml.Entity;
025 import com.liferay.portal.kernel.xml.Namespace;
026 import com.liferay.portal.kernel.xml.Node;
027 import com.liferay.portal.kernel.xml.ProcessingInstruction;
028 import com.liferay.portal.kernel.xml.QName;
029 import com.liferay.portal.kernel.xml.SAXReader;
030 import com.liferay.portal.kernel.xml.Text;
031 import com.liferay.portal.kernel.xml.XMLSchema;
032 import com.liferay.portal.kernel.xml.XPath;
033 import com.liferay.portal.security.xml.SecureXMLFactoryProvider;
034 import com.liferay.portal.security.xml.SecureXMLFactoryProviderImpl;
035 import com.liferay.portal.util.ClassLoaderUtil;
036 import com.liferay.portal.util.EntityResolver;
037 import com.liferay.portal.util.PropsValues;
038 import com.liferay.util.xml.XMLSafeReader;
039
040 import java.io.File;
041 import java.io.InputStream;
042 import java.io.Reader;
043
044 import java.net.MalformedURLException;
045 import java.net.URL;
046
047 import java.util.ArrayList;
048 import java.util.HashMap;
049 import java.util.List;
050 import java.util.Map;
051
052 import org.dom4j.DocumentFactory;
053 import org.dom4j.DocumentHelper;
054
055
058 @DoPrivileged
059 public class SAXReaderImpl implements SAXReader {
060
061
064 public static SAXReaderImpl getInstance() {
065 return new SAXReaderImpl();
066 }
067
068 public static List<Attribute> toNewAttributes(
069 List<org.dom4j.Attribute> oldAttributes) {
070
071 List<Attribute> newAttributes = new ArrayList<Attribute>(
072 oldAttributes.size());
073
074 for (org.dom4j.Attribute oldAttribute : oldAttributes) {
075 newAttributes.add(new AttributeImpl(oldAttribute));
076 }
077
078 return new NodeList<Attribute, org.dom4j.Attribute>(
079 newAttributes, oldAttributes);
080 }
081
082 public static List<Element> toNewElements(
083 List<org.dom4j.Element> oldElements) {
084
085 List<Element> newElements = new ArrayList<Element>(oldElements.size());
086
087 for (org.dom4j.Element oldElement : oldElements) {
088 newElements.add(new ElementImpl(oldElement));
089 }
090
091 return new NodeList<Element, org.dom4j.Element>(
092 newElements, oldElements);
093 }
094
095 public static List<Namespace> toNewNamespaces(
096 List<org.dom4j.Namespace> oldNamespaces) {
097
098 List<Namespace> newNamespaces = new ArrayList<Namespace>(
099 oldNamespaces.size());
100
101 for (org.dom4j.Namespace oldNamespace : oldNamespaces) {
102 newNamespaces.add(new NamespaceImpl(oldNamespace));
103 }
104
105 return new NodeList<Namespace, org.dom4j.Namespace>(
106 newNamespaces, oldNamespaces);
107 }
108
109 public static List<Node> toNewNodes(List<org.dom4j.Node> oldNodes) {
110 List<Node> newNodes = new ArrayList<Node>(oldNodes.size());
111
112 for (org.dom4j.Node oldNode : oldNodes) {
113 if (oldNode instanceof org.dom4j.Element) {
114 newNodes.add(new ElementImpl((org.dom4j.Element)oldNode));
115 }
116 else {
117 newNodes.add(new NodeImpl(oldNode));
118 }
119 }
120
121 return new NodeList<Node, org.dom4j.Node>(newNodes, oldNodes);
122 }
123
124 public static List<ProcessingInstruction> toNewProcessingInstructions(
125 List<org.dom4j.ProcessingInstruction> oldProcessingInstructions) {
126
127 List<ProcessingInstruction> newProcessingInstructions =
128 new ArrayList<ProcessingInstruction>(
129 oldProcessingInstructions.size());
130
131 for (org.dom4j.ProcessingInstruction oldProcessingInstruction :
132 oldProcessingInstructions) {
133
134 newProcessingInstructions.add(
135 new ProcessingInstructionImpl(oldProcessingInstruction));
136 }
137
138 return new NodeList
139 <ProcessingInstruction, org.dom4j.ProcessingInstruction>(
140 newProcessingInstructions, oldProcessingInstructions);
141 }
142
143 public static List<org.dom4j.Attribute> toOldAttributes(
144 List<Attribute> newAttributes) {
145
146 List<org.dom4j.Attribute> oldAttributes =
147 new ArrayList<org.dom4j.Attribute>(newAttributes.size());
148
149 for (Attribute newAttribute : newAttributes) {
150 AttributeImpl newAttributeImpl = (AttributeImpl)newAttribute;
151
152 oldAttributes.add(newAttributeImpl.getWrappedAttribute());
153 }
154
155 return oldAttributes;
156 }
157
158 public static List<org.dom4j.Node> toOldNodes(List<Node> newNodes) {
159 List<org.dom4j.Node> oldNodes = new ArrayList<org.dom4j.Node>(
160 newNodes.size());
161
162 for (Node newNode : newNodes) {
163 NodeImpl newNodeImpl = (NodeImpl)newNode;
164
165 oldNodes.add(newNodeImpl.getWrappedNode());
166 }
167
168 return oldNodes;
169 }
170
171 public static List<org.dom4j.ProcessingInstruction>
172 toOldProcessingInstructions(
173 List<ProcessingInstruction> newProcessingInstructions) {
174
175 List<org.dom4j.ProcessingInstruction> oldProcessingInstructions =
176 new ArrayList<org.dom4j.ProcessingInstruction>(
177 newProcessingInstructions.size());
178
179 for (ProcessingInstruction newProcessingInstruction :
180 newProcessingInstructions) {
181
182 ProcessingInstructionImpl newProcessingInstructionImpl =
183 (ProcessingInstructionImpl)newProcessingInstruction;
184
185 oldProcessingInstructions.add(
186 newProcessingInstructionImpl.getWrappedProcessingInstruction());
187 }
188
189 return oldProcessingInstructions;
190 }
191
192 @Override
193 public Attribute createAttribute(
194 Element element, QName qName, String value) {
195
196 ElementImpl elementImpl = (ElementImpl)element;
197 QNameImpl qNameImpl = (QNameImpl)qName;
198
199 DocumentFactory documentFactory = DocumentFactory.getInstance();
200
201 return new AttributeImpl(
202 documentFactory.createAttribute(
203 elementImpl.getWrappedElement(), qNameImpl.getWrappedQName(),
204 value));
205 }
206
207 @Override
208 public Attribute createAttribute(
209 Element element, String name, String value) {
210
211 ElementImpl elementImpl = (ElementImpl)element;
212
213 DocumentFactory documentFactory = DocumentFactory.getInstance();
214
215 return new AttributeImpl(
216 documentFactory.createAttribute(
217 elementImpl.getWrappedElement(), name, value));
218 }
219
220 @Override
221 public Document createDocument() {
222 return new DocumentImpl(DocumentHelper.createDocument());
223 }
224
225 @Override
226 public Document createDocument(Element rootElement) {
227 ElementImpl rootElementImpl = (ElementImpl)rootElement;
228
229 return new DocumentImpl(
230 DocumentHelper.createDocument(rootElementImpl.getWrappedElement()));
231 }
232
233 @Override
234 public Document createDocument(String encoding) {
235 DocumentFactory documentFactory = DocumentFactory.getInstance();
236
237 return new DocumentImpl(documentFactory.createDocument(encoding));
238 }
239
240 @Override
241 public Element createElement(QName qName) {
242 QNameImpl qNameImpl = (QNameImpl)qName;
243
244 return new ElementImpl(
245 DocumentHelper.createElement(qNameImpl.getWrappedQName()));
246 }
247
248 @Override
249 public Element createElement(String name) {
250 return new ElementImpl(DocumentHelper.createElement(name));
251 }
252
253 @Override
254 public Entity createEntity(String name, String text) {
255 return new EntityImpl(DocumentHelper.createEntity(name, text));
256 }
257
258 @Override
259 public Namespace createNamespace(String uri) {
260 return new NamespaceImpl(org.dom4j.Namespace.get(uri));
261 }
262
263 @Override
264 public Namespace createNamespace(String prefix, String uri) {
265 return new NamespaceImpl(DocumentHelper.createNamespace(prefix, uri));
266 }
267
268 @Override
269 public ProcessingInstruction createProcessingInstruction(
270 String target, Map<String, 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 @Override
284 public ProcessingInstruction createProcessingInstruction(
285 String target, String data) {
286
287 org.dom4j.ProcessingInstruction processingInstruction =
288 DocumentHelper.createProcessingInstruction(target, data);
289
290 if (processingInstruction == null) {
291 return null;
292 }
293 else {
294 return new ProcessingInstructionImpl(processingInstruction);
295 }
296 }
297
298 @Override
299 public QName createQName(String localName) {
300 return new QNameImpl(DocumentHelper.createQName(localName));
301 }
302
303 @Override
304 public QName createQName(String localName, Namespace namespace) {
305 NamespaceImpl namespaceImpl = (NamespaceImpl)namespace;
306
307 return new QNameImpl(
308 DocumentHelper.createQName(
309 localName, namespaceImpl.getWrappedNamespace()));
310 }
311
312 @Override
313 public Text createText(String text) {
314 return new TextImpl(DocumentHelper.createText(text));
315 }
316
317 @Override
318 public XPath createXPath(String xPathExpression) {
319 return createXPath(xPathExpression, null);
320 }
321
322 @Override
323 public XPath createXPath(
324 String xPathExpression, Map<String, String> namespaceContextMap) {
325
326 return new XPathImpl(
327 DocumentHelper.createXPath(xPathExpression), namespaceContextMap);
328 }
329
330 @Override
331 public XPath createXPath(
332 String xPathExpression, String prefix, String namespace) {
333
334 Map<String, String> namespaceContextMap = new HashMap<String, String>();
335
336 namespaceContextMap.put(prefix, namespace);
337
338 return createXPath(xPathExpression, namespaceContextMap);
339 }
340
341 @Override
342 public Document read(File file) throws DocumentException {
343 return read(file, false);
344 }
345
346 @Override
347 public Document read(File file, boolean validate) throws DocumentException {
348 Class<?> clazz = getClass();
349
350 ClassLoader classLoader = clazz.getClassLoader();
351
352 ClassLoader contextClassLoader =
353 ClassLoaderUtil.getContextClassLoader();
354
355 try {
356 if (classLoader != contextClassLoader) {
357 ClassLoaderUtil.setContextClassLoader(classLoader);
358 }
359
360 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
361
362 return new DocumentImpl(saxReader.read(file));
363 }
364 catch (org.dom4j.DocumentException de) {
365 throw new DocumentException(de.getMessage(), de);
366 }
367 finally {
368 if (classLoader != contextClassLoader) {
369 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
370 }
371 }
372 }
373
374 @Override
375 public Document read(InputStream is) throws DocumentException {
376 return read(is, false);
377 }
378
379 @Override
380 public Document read(InputStream is, boolean validate)
381 throws DocumentException {
382
383 Class<?> clazz = getClass();
384
385 ClassLoader classLoader = clazz.getClassLoader();
386
387 ClassLoader contextClassLoader =
388 ClassLoaderUtil.getContextClassLoader();
389
390 try {
391 if (classLoader != contextClassLoader) {
392 ClassLoaderUtil.setContextClassLoader(classLoader);
393 }
394
395 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
396
397 return new DocumentImpl(saxReader.read(is));
398 }
399 catch (org.dom4j.DocumentException de) {
400 throw new DocumentException(de.getMessage(), de);
401 }
402 finally {
403 if (classLoader != contextClassLoader) {
404 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
405 }
406 }
407 }
408
409 @Override
410 public Document read(Reader reader) throws DocumentException {
411 return read(reader, false);
412 }
413
414 @Override
415 public Document read(Reader reader, boolean validate)
416 throws DocumentException {
417
418 Class<?> clazz = getClass();
419
420 ClassLoader classLoader = clazz.getClassLoader();
421
422 ClassLoader contextClassLoader =
423 ClassLoaderUtil.getContextClassLoader();
424
425 try {
426 if (classLoader != contextClassLoader) {
427 ClassLoaderUtil.setContextClassLoader(classLoader);
428 }
429
430 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
431
432 return new DocumentImpl(saxReader.read(reader));
433 }
434 catch (org.dom4j.DocumentException de) {
435 throw new DocumentException(de.getMessage(), de);
436 }
437 finally {
438 if (classLoader != contextClassLoader) {
439 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
440 }
441 }
442 }
443
444 @Override
445 public Document read(String xml) throws DocumentException {
446 return read(new XMLSafeReader(xml));
447 }
448
449 @Override
450 public Document read(String xml, boolean validate)
451 throws DocumentException {
452
453 return read(new XMLSafeReader(xml), validate);
454 }
455
456 @Override
457 public Document read(String xml, XMLSchema xmlSchema)
458 throws DocumentException {
459
460 Class<?> clazz = getClass();
461
462 ClassLoader classLoader = clazz.getClassLoader();
463
464 ClassLoader contextClassLoader =
465 ClassLoaderUtil.getContextClassLoader();
466
467 try {
468 if (classLoader != contextClassLoader) {
469 ClassLoaderUtil.setContextClassLoader(classLoader);
470 }
471
472 org.dom4j.io.SAXReader saxReader = getSAXReader(xmlSchema);
473
474 Reader reader = new XMLSafeReader(xml);
475
476 return new DocumentImpl(saxReader.read(reader));
477 }
478 catch (org.dom4j.DocumentException de) {
479 throw new DocumentException(de.getMessage(), de);
480 }
481 finally {
482 if (classLoader != contextClassLoader) {
483 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
484 }
485 }
486 }
487
488 @Override
489 public Document read(URL url) throws DocumentException {
490 return read(url, false);
491 }
492
493 @Override
494 public Document read(URL url, boolean validate) throws DocumentException {
495 Class<?> clazz = getClass();
496
497 ClassLoader classLoader = clazz.getClassLoader();
498
499 ClassLoader contextClassLoader =
500 ClassLoaderUtil.getContextClassLoader();
501
502 try {
503 if (classLoader != contextClassLoader) {
504 ClassLoaderUtil.setContextClassLoader(classLoader);
505 }
506
507 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
508
509 return new DocumentImpl(saxReader.read(url));
510 }
511 catch (org.dom4j.DocumentException de) {
512 throw new DocumentException(de.getMessage(), de);
513 }
514 finally {
515 if (classLoader != contextClassLoader) {
516 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
517 }
518 }
519 }
520
521 @Override
522 public Document readURL(String url)
523 throws DocumentException, MalformedURLException {
524
525 return read(new URL(url), false);
526 }
527
528 @Override
529 public Document readURL(String url, boolean validate)
530 throws DocumentException, MalformedURLException {
531
532 return read(new URL(url), validate);
533 }
534
535 @Override
536 public List<Node> selectNodes(
537 String xPathFilterExpression, List<Node> nodes) {
538
539 return toNewNodes(
540 DocumentHelper.selectNodes(
541 xPathFilterExpression, toOldNodes(nodes)));
542 }
543
544 @Override
545 public List<Node> selectNodes(String xPathFilterExpression, Node node) {
546 NodeImpl nodeImpl = (NodeImpl)node;
547
548 return toNewNodes(
549 DocumentHelper.selectNodes(
550 xPathFilterExpression, nodeImpl.getWrappedNode()));
551 }
552
553 public void setSecure(boolean secure) {
554 _secure = secure;
555 }
556
557 public void setSecureXMLFactoryProvider(
558 SecureXMLFactoryProvider secureXMLFactoryProvider) {
559
560 _secureXMLFactoryProvider = secureXMLFactoryProvider;
561 }
562
563 @Override
564 public void sort(List<Node> nodes, String xPathExpression) {
565 DocumentHelper.sort(toOldNodes(nodes), xPathExpression);
566 }
567
568 @Override
569 public void sort(
570 List<Node> nodes, String xPathExpression, boolean distinct) {
571
572 DocumentHelper.sort(toOldNodes(nodes), xPathExpression, distinct);
573 }
574
575 protected org.dom4j.io.SAXReader getSAXReader(boolean validate) {
576 org.dom4j.io.SAXReader reader = null;
577
578 if (!PropsValues.XML_VALIDATION_ENABLED) {
579 validate = false;
580 }
581
582 try {
583 reader = new org.dom4j.io.SAXReader(
584 _secureXMLFactoryProvider.newXMLReader(), validate);
585
586 reader.setEntityResolver(new EntityResolver());
587 reader.setFeature(_FEATURES_DYNAMIC, validate);
588 reader.setFeature(_FEATURES_VALIDATION, validate);
589 reader.setFeature(_FEATURES_VALIDATION_SCHEMA, validate);
590 reader.setFeature(
591 _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, validate);
592
593 if (!_secure) {
594 reader.setFeature(_FEATURES_DISALLOW_DOCTYPE_DECL, false);
595 reader.setFeature(_FEATURES_LOAD_DTD_GRAMMAR, validate);
596 reader.setFeature(_FEATURES_LOAD_EXTERNAL_DTD, validate);
597 }
598 }
599 catch (Exception e) {
600 if (_log.isWarnEnabled()) {
601 _log.warn(
602 "XSD validation is disabled because " + e.getMessage());
603 }
604
605 reader = new org.dom4j.io.SAXReader(
606 _secureXMLFactoryProvider.newXMLReader(), false);
607
608 reader.setEntityResolver(new EntityResolver());
609 }
610
611 return reader;
612 }
613
614 protected org.dom4j.io.SAXReader getSAXReader(XMLSchema xmlSchema) {
615 boolean validate = true;
616
617 if (!PropsValues.XML_VALIDATION_ENABLED) {
618 validate = false;
619 }
620
621 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
622
623 if ((xmlSchema == null) || (validate == false)) {
624 return saxReader;
625 }
626
627 try {
628 saxReader.setProperty(
629 _PROPERTY_SCHEMA_LANGUAGE, xmlSchema.getSchemaLanguage());
630 saxReader.setProperty(
631 _PROPERTY_SCHEMA_SOURCE, xmlSchema.getSchemaSource());
632 }
633 catch (Exception e) {
634 if (_log.isWarnEnabled()) {
635 _log.warn(
636 "XSD validation is disabled because " + e.getMessage());
637 }
638 }
639
640 return saxReader;
641 }
642
643 private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
644 "http:
645
646 private static final String _FEATURES_DYNAMIC =
647 "http:
648
649 private static final String _FEATURES_LOAD_DTD_GRAMMAR =
650 "http:
651
652 private static final String _FEATURES_LOAD_EXTERNAL_DTD =
653 "http:
654
655 private static final String _FEATURES_VALIDATION =
656 "http:
657
658 private static final String _FEATURES_VALIDATION_SCHEMA =
659 "http:
660
661 private static final String _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING =
662 "http:
663
664 private static final String _PROPERTY_SCHEMA_LANGUAGE =
665 "http:
666
667 private static final String _PROPERTY_SCHEMA_SOURCE =
668 "http:
669
670 private static Log _log = LogFactoryUtil.getLog(SAXReaderImpl.class);
671
672 private boolean _secure;
673 private SecureXMLFactoryProvider _secureXMLFactoryProvider =
674 new SecureXMLFactoryProviderImpl();
675
676 }