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 ClassLoader classLoader = getClass().getClassLoader();
349
350 ClassLoader contextClassLoader =
351 ClassLoaderUtil.getContextClassLoader();
352
353 try {
354 if (contextClassLoader != classLoader) {
355 ClassLoaderUtil.setContextClassLoader(classLoader);
356 }
357
358 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
359
360 return new DocumentImpl(saxReader.read(file));
361 }
362 catch (org.dom4j.DocumentException de) {
363 throw new DocumentException(de.getMessage(), de);
364 }
365 finally {
366 if (contextClassLoader != classLoader) {
367 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
368 }
369 }
370 }
371
372 @Override
373 public Document read(InputStream is) throws DocumentException {
374 return read(is, false);
375 }
376
377 @Override
378 public Document read(InputStream is, boolean validate)
379 throws DocumentException {
380
381 ClassLoader classLoader = getClass().getClassLoader();
382
383 ClassLoader contextClassLoader =
384 ClassLoaderUtil.getContextClassLoader();
385
386 try {
387 if (contextClassLoader != classLoader) {
388 ClassLoaderUtil.setContextClassLoader(classLoader);
389 }
390
391 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
392
393 return new DocumentImpl(saxReader.read(is));
394 }
395 catch (org.dom4j.DocumentException de) {
396 throw new DocumentException(de.getMessage(), de);
397 }
398 finally {
399 if (contextClassLoader != classLoader) {
400 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
401 }
402 }
403 }
404
405 @Override
406 public Document read(Reader reader) throws DocumentException {
407 return read(reader, false);
408 }
409
410 @Override
411 public Document read(Reader reader, boolean validate)
412 throws DocumentException {
413
414 ClassLoader classLoader = getClass().getClassLoader();
415
416 ClassLoader contextClassLoader =
417 ClassLoaderUtil.getContextClassLoader();
418
419 try {
420 if (contextClassLoader != classLoader) {
421 ClassLoaderUtil.setContextClassLoader(classLoader);
422 }
423
424 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
425
426 return new DocumentImpl(saxReader.read(reader));
427 }
428 catch (org.dom4j.DocumentException de) {
429 throw new DocumentException(de.getMessage(), de);
430 }
431 finally {
432 if (contextClassLoader != classLoader) {
433 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
434 }
435 }
436 }
437
438 @Override
439 public Document read(String xml) throws DocumentException {
440 return read(new XMLSafeReader(xml));
441 }
442
443 @Override
444 public Document read(String xml, boolean validate)
445 throws DocumentException {
446
447 return read(new XMLSafeReader(xml), validate);
448 }
449
450 @Override
451 public Document read(String xml, XMLSchema xmlSchema)
452 throws DocumentException {
453
454 ClassLoader classLoader = getClass().getClassLoader();
455
456 ClassLoader contextClassLoader =
457 ClassLoaderUtil.getContextClassLoader();
458
459 try {
460 if (contextClassLoader != classLoader) {
461 ClassLoaderUtil.setContextClassLoader(classLoader);
462 }
463
464 org.dom4j.io.SAXReader saxReader = getSAXReader(xmlSchema);
465
466 Reader reader = new XMLSafeReader(xml);
467
468 return new DocumentImpl(saxReader.read(reader));
469 }
470 catch (org.dom4j.DocumentException de) {
471 throw new DocumentException(de.getMessage(), de);
472 }
473 finally {
474 if (contextClassLoader != classLoader) {
475 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
476 }
477 }
478 }
479
480 @Override
481 public Document read(URL url) throws DocumentException {
482 return read(url, false);
483 }
484
485 @Override
486 public Document read(URL url, boolean validate) throws DocumentException {
487 ClassLoader classLoader = getClass().getClassLoader();
488
489 ClassLoader contextClassLoader =
490 ClassLoaderUtil.getContextClassLoader();
491
492 try {
493 if (contextClassLoader != classLoader) {
494 ClassLoaderUtil.setContextClassLoader(classLoader);
495 }
496
497 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
498
499 return new DocumentImpl(saxReader.read(url));
500 }
501 catch (org.dom4j.DocumentException de) {
502 throw new DocumentException(de.getMessage(), de);
503 }
504 finally {
505 if (contextClassLoader != classLoader) {
506 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
507 }
508 }
509 }
510
511 @Override
512 public Document readURL(String url)
513 throws DocumentException, MalformedURLException {
514
515 return read(new URL(url), false);
516 }
517
518 @Override
519 public Document readURL(String url, boolean validate)
520 throws DocumentException, MalformedURLException {
521
522 return read(new URL(url), validate);
523 }
524
525 @Override
526 public List<Node> selectNodes(
527 String xPathFilterExpression, List<Node> nodes) {
528
529 return toNewNodes(
530 DocumentHelper.selectNodes(
531 xPathFilterExpression, toOldNodes(nodes)));
532 }
533
534 @Override
535 public List<Node> selectNodes(String xPathFilterExpression, Node node) {
536 NodeImpl nodeImpl = (NodeImpl)node;
537
538 return toNewNodes(
539 DocumentHelper.selectNodes(
540 xPathFilterExpression, nodeImpl.getWrappedNode()));
541 }
542
543 public void setSecure(boolean secure) {
544 _secure = secure;
545 }
546
547 public void setSecureXMLFactoryProvider(
548 SecureXMLFactoryProvider secureXMLFactoryProvider) {
549
550 _secureXMLFactoryProvider = secureXMLFactoryProvider;
551 }
552
553 @Override
554 public void sort(List<Node> nodes, String xPathExpression) {
555 DocumentHelper.sort(toOldNodes(nodes), xPathExpression);
556 }
557
558 @Override
559 public void sort(
560 List<Node> nodes, String xPathExpression, boolean distinct) {
561
562 DocumentHelper.sort(toOldNodes(nodes), xPathExpression, distinct);
563 }
564
565 protected org.dom4j.io.SAXReader getSAXReader(boolean validate) {
566 org.dom4j.io.SAXReader reader = null;
567
568 if (!PropsValues.XML_VALIDATION_ENABLED) {
569 validate = false;
570 }
571
572 try {
573 reader = new org.dom4j.io.SAXReader(
574 _secureXMLFactoryProvider.newXMLReader(), validate);
575
576 reader.setEntityResolver(new EntityResolver());
577 reader.setFeature(_FEATURES_DYNAMIC, validate);
578 reader.setFeature(_FEATURES_VALIDATION, validate);
579 reader.setFeature(_FEATURES_VALIDATION_SCHEMA, validate);
580 reader.setFeature(
581 _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, validate);
582
583 if (!_secure) {
584 reader.setFeature(_FEATURES_DISALLOW_DOCTYPE_DECL, false);
585 reader.setFeature(_FEATURES_LOAD_DTD_GRAMMAR, validate);
586 reader.setFeature(_FEATURES_LOAD_EXTERNAL_DTD, validate);
587 }
588 }
589 catch (Exception e) {
590 if (_log.isWarnEnabled()) {
591 _log.warn(
592 "XSD validation is disabled because " + e.getMessage());
593 }
594
595 reader = new org.dom4j.io.SAXReader(
596 _secureXMLFactoryProvider.newXMLReader(), false);
597
598 reader.setEntityResolver(new EntityResolver());
599 }
600
601 return reader;
602 }
603
604 protected org.dom4j.io.SAXReader getSAXReader(XMLSchema xmlSchema) {
605 boolean validate = true;
606
607 if (!PropsValues.XML_VALIDATION_ENABLED) {
608 validate = false;
609 }
610
611 org.dom4j.io.SAXReader saxReader = getSAXReader(validate);
612
613 if ((xmlSchema == null) || (validate == false)) {
614 return saxReader;
615 }
616
617 try {
618 saxReader.setProperty(
619 _PROPERTY_SCHEMA_LANGUAGE, xmlSchema.getSchemaLanguage());
620 saxReader.setProperty(
621 _PROPERTY_SCHEMA_SOURCE, xmlSchema.getSchemaSource());
622 }
623 catch (Exception e) {
624 if (_log.isWarnEnabled()) {
625 _log.warn(
626 "XSD validation is disabled because " + e.getMessage());
627 }
628 }
629
630 return saxReader;
631 }
632
633 private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
634 "http:
635
636 private static final String _FEATURES_DYNAMIC =
637 "http:
638
639 private static final String _FEATURES_LOAD_DTD_GRAMMAR =
640 "http:
641
642 private static final String _FEATURES_LOAD_EXTERNAL_DTD =
643 "http:
644
645 private static final String _FEATURES_VALIDATION =
646 "http:
647
648 private static final String _FEATURES_VALIDATION_SCHEMA =
649 "http:
650
651 private static final String _FEATURES_VALIDATION_SCHEMA_FULL_CHECKING =
652 "http:
653
654 private static final String _PROPERTY_SCHEMA_LANGUAGE =
655 "http:
656
657 private static final String _PROPERTY_SCHEMA_SOURCE =
658 "http:
659
660 private static Log _log = LogFactoryUtil.getLog(SAXReaderImpl.class);
661
662 private boolean _secure;
663 private SecureXMLFactoryProvider _secureXMLFactoryProvider =
664 new SecureXMLFactoryProviderImpl();
665
666 }