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