1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.parsers.SAXParserFactory;
29
30 import org.xml.sax.InputSource;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.SAXParseException;
33 import org.xml.sax.XMLReader;
34 import org.xml.sax.helpers.DefaultHandler;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class XmlLoader
51 extends DefaultHandler {
52
53
54 private final Map<String, String> publicIdToResourceNameMap;
55
56 private final XMLReader parser;
57
58
59
60
61
62
63
64 protected XmlLoader(Map<String, String> publicIdToResourceNameMap)
65 throws SAXException, ParserConfigurationException {
66 this.publicIdToResourceNameMap = new HashMap<>(publicIdToResourceNameMap);
67 final SAXParserFactory factory = SAXParserFactory.newInstance();
68 LoadExternalDtdFeatureProvider.setFeaturesBySystemProperty(factory);
69 factory.setValidating(true);
70 parser = factory.newSAXParser().getXMLReader();
71 parser.setContentHandler(this);
72 parser.setEntityResolver(this);
73 parser.setErrorHandler(this);
74 }
75
76
77
78
79
80
81
82 public void parseInputSource(InputSource inputSource)
83 throws IOException, SAXException {
84 parser.parse(inputSource);
85 }
86
87 @Override
88 public InputSource resolveEntity(String publicId, String systemId)
89 throws SAXException, IOException {
90 final InputSource inputSource;
91 if (publicIdToResourceNameMap.keySet().contains(publicId)) {
92 final String dtdResourceName =
93 publicIdToResourceNameMap.get(publicId);
94 final ClassLoader loader =
95 getClass().getClassLoader();
96 final InputStream dtdIs =
97 loader.getResourceAsStream(dtdResourceName);
98
99 inputSource = new InputSource(dtdIs);
100 }
101 else {
102 inputSource = super.resolveEntity(publicId, systemId);
103 }
104 return inputSource;
105 }
106
107 @Override
108 public void error(SAXParseException exception) throws SAXException {
109 throw exception;
110 }
111
112
113
114
115
116 public static final class LoadExternalDtdFeatureProvider {
117
118
119 public static final String ENABLE_EXTERNAL_DTD_LOAD = "checkstyle.enableExternalDtdLoad";
120
121
122 public static final String LOAD_EXTERNAL_DTD =
123 "http://apache.org/xml/features/nonvalidating/load-external-dtd";
124
125 public static final String EXTERNAL_GENERAL_ENTITIES =
126 "http://xml.org/sax/features/external-general-entities";
127
128
129 private LoadExternalDtdFeatureProvider() {
130 }
131
132
133
134
135
136
137
138
139
140
141 public static void setFeaturesBySystemProperty(SAXParserFactory factory)
142 throws SAXException, ParserConfigurationException {
143
144 final boolean enableExternalDtdLoad = Boolean.valueOf(
145 System.getProperty(ENABLE_EXTERNAL_DTD_LOAD, "false"));
146
147 factory.setFeature(LOAD_EXTERNAL_DTD, enableExternalDtdLoad);
148 factory.setFeature(EXTERNAL_GENERAL_ENTITIES, enableExternalDtdLoad);
149 }
150
151 }
152
153 }