-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathXmlProcessorFactoryRelEng.java
More file actions
113 lines (102 loc) · 4.4 KB
/
XmlProcessorFactoryRelEng.java
File metadata and controls
113 lines (102 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*******************************************************************************
* Copyright (c) 2023, 2025 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package utilities;
import java.io.ByteArrayInputStream;
import java.util.stream.IntStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* XML processing which prohibits external entities.
*
* @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
*/
public class XmlProcessorFactoryRelEng {
private XmlProcessorFactoryRelEng() {
// static Utility only
}
// using these factories is synchronized with creating & configuring them
// potentially concurrently in another thread:
private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_IGNORING_DOCTYPE = createDocumentBuilderFactoryIgnoringDOCTYPE();
/**
* Creates DocumentBuilderFactory which throws SAXParseException when detecting
* external entities. It's magnitudes faster to call
* {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
*
* @return javax.xml.parsers.DocumentBuilderFactory
*/
private static synchronized DocumentBuilderFactory createDocumentBuilderFactoryWithErrorOnDOCTYPE() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// completely disable DOCTYPE declaration:
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
} catch (ParserConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
}
return factory;
}
/**
* Creates DocumentBuilderFactory which ignores external entities. Beware:
* DocumentBuilder created with this Factory may load DTDs from a remote Host -
* which may be slow and a security risk. It's recommended to call
* DocumentBuilder.setEntityResolver(EntityResolver) with fixed DTDs. <br>
* It's magnitudes faster to call
* {@link #createDocumentBuilderIgnoringDOCTYPE()}.
*
* @return javax.xml.parsers.DocumentBuilderFactory
* @see javax.xml.parsers.DocumentBuilder#setEntityResolver(EntityResolver)
*/
public static synchronized DocumentBuilderFactory createDocumentBuilderFactoryIgnoringDOCTYPE() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
// completely disable external entities declarations:
factory.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
} catch (ParserConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
}
return factory;
}
/**
* Creates DocumentBuilder which throws SAXParseException when detecting
* external entities. The builder is not thread safe.
*
* @return javax.xml.parsers.DocumentBuilder
*/
public static synchronized DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE()
throws ParserConfigurationException {
return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
}
/**
* Creates DocumentBuilder which ignores external entities and does not load
* remote DTDs. The builder is not thread safe.
*
* @return javax.xml.parsers.DocumentBuilder
*/
public static synchronized DocumentBuilder createDocumentBuilderIgnoringDOCTYPE()
throws ParserConfigurationException {
DocumentBuilder builder = DOCUMENT_BUILDER_FACTORY_IGNORING_DOCTYPE.newDocumentBuilder();
builder.setEntityResolver((__, ___) -> new InputSource(new ByteArrayInputStream(new byte[0])));
return builder;
}
public static Iterable<Element> elements(NodeList list) {
return () -> IntStream.range(0, list.getLength()).mapToObj(list::item).filter(Element.class::isInstance)
.map(Element.class::cast).iterator();
}
}