BUG-7057: introduce UntrustedXML class
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / xml / UntrustedXML.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util.xml;
9
10 import com.google.common.annotations.Beta;
11 import javax.annotation.Nonnull;
12 import javax.xml.XMLConstants;
13 import javax.xml.parsers.DocumentBuilder;
14 import javax.xml.parsers.DocumentBuilderFactory;
15 import javax.xml.parsers.ParserConfigurationException;
16 import javax.xml.parsers.SAXParser;
17 import javax.xml.parsers.SAXParserFactory;
18 import org.xml.sax.SAXException;
19
20 /**
21  * Set of utility methods for instantiating parser that deal with untrusted XML sources.
22  *
23  * @author Robert Varga
24  */
25 @Beta
26 public final class UntrustedXML {
27     private static final DocumentBuilderFactory DBF;
28     static {
29         final DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
30         f.setCoalescing(true);
31         f.setExpandEntityReferences(false);
32         f.setIgnoringElementContentWhitespace(true);
33         f.setIgnoringComments(true);
34         f.setNamespaceAware(true);
35         f.setXIncludeAware(false);
36         try {
37             f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
38             f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
39             f.setFeature("http://xml.org/sax/features/external-general-entities", false);
40             f.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
41         } catch (final ParserConfigurationException e) {
42             throw new ExceptionInInitializerError(e);
43         }
44         DBF = f;
45     }
46
47     private static final SAXParserFactory SPF;
48     static {
49         final SAXParserFactory f = SAXParserFactory.newInstance();
50         f.setNamespaceAware(true);
51         f.setXIncludeAware(false);
52         try {
53             f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
54             f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
55             f.setFeature("http://xml.org/sax/features/external-general-entities", false);
56             f.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
57         } catch (final Exception e) {
58             throw new ExceptionInInitializerError(e);
59         }
60
61         SPF = f;
62     }
63
64     /**
65      * Create a new {@link DocumentBuilder} for dealing with untrusted XML data. This method is equivalent to
66      * {@link DocumentBuilderFactory#newDocumentBuilder()}, except it does not throw a checked exception.
67      *
68      * @return A new DocumentBuilder
69      * @throws UnsupportedOperationException if the runtime fails to instantiate a good enough builder
70      */
71     public static @Nonnull DocumentBuilder newDocumentBuilder() {
72         try {
73             return DBF.newDocumentBuilder();
74         } catch (ParserConfigurationException e) {
75             throw new UnsupportedOperationException("Failed to instantiate a DocumentBuilder", e);
76         }
77     }
78
79     /**
80      * Create a new {@link SAXParser} for dealing with untrusted XML data. This method is equivalent to
81      * {@link SAXParserFactory#newSAXParser()}, except it does not throw a checked exception.
82      *
83      * @return A new SAXParser
84      * @throws UnsupportedOperationException if the runtime fails to instantiate a good enough builder
85      */
86     public static @Nonnull SAXParser newSAXParser() {
87         try {
88             return SPF.newSAXParser();
89         } catch (ParserConfigurationException | SAXException e) {
90             throw new UnsupportedOperationException("Failed to instantiate a SAXParser", e);
91         }
92     }
93 }