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.Map;
25
26 import javax.xml.parsers.ParserConfigurationException;
27 import javax.xml.parsers.SAXParserFactory;
28
29 import org.xml.sax.InputSource;
30 import org.xml.sax.SAXException;
31 import org.xml.sax.SAXParseException;
32 import org.xml.sax.XMLReader;
33 import org.xml.sax.helpers.DefaultHandler;
34
35 import com.puppycrawl.tools.checkstyle.utils.UnmodifiableCollectionUtil;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class XmlLoader
55 extends DefaultHandler {
56
57
58 private final Map<String, String> publicIdToResourceNameMap;
59
60 private final XMLReader parser;
61
62
63
64
65
66
67
68
69 protected XmlLoader(Map<String, String> publicIdToResourceNameMap)
70 throws SAXException, ParserConfigurationException {
71 this.publicIdToResourceNameMap =
72 UnmodifiableCollectionUtil.copyOfMap(publicIdToResourceNameMap);
73 parser = createXmlReader(this);
74 }
75
76
77
78
79
80
81
82
83 public void parseInputSource(InputSource inputSource)
84 throws IOException, SAXException {
85 parser.parse(inputSource);
86 }
87
88 @Override
89 public InputSource resolveEntity(String publicId, String systemId) {
90 InputSource inputSource = null;
91 if (publicId != null) {
92 final String dtdResourceName = publicIdToResourceNameMap.get(publicId);
93
94 if (dtdResourceName != null) {
95 final ClassLoader loader = getClass().getClassLoader();
96 final InputStream dtdIs = loader.getResourceAsStream(dtdResourceName);
97 inputSource = new InputSource(dtdIs);
98 }
99 }
100 return inputSource;
101 }
102
103 @Override
104 public void error(SAXParseException exception) throws SAXException {
105 throw exception;
106 }
107
108
109
110
111
112
113
114
115
116 private static XMLReader createXmlReader(DefaultHandler handler)
117 throws SAXException, ParserConfigurationException {
118 final SAXParserFactory factory = SAXParserFactory.newInstance();
119 LoadExternalDtdFeatureProvider.setFeaturesBySystemProperty(factory);
120 factory.setValidating(true);
121 final XMLReader xmlReader = factory.newSAXParser().getXMLReader();
122 xmlReader.setContentHandler(handler);
123 xmlReader.setEntityResolver(handler);
124 xmlReader.setErrorHandler(handler);
125 return xmlReader;
126 }
127
128
129
130
131
132 public static final class LoadExternalDtdFeatureProvider {
133
134
135 public static final String ENABLE_EXTERNAL_DTD_LOAD = "checkstyle.enableExternalDtdLoad";
136
137
138 public static final String LOAD_EXTERNAL_DTD =
139 "http://apache.org/xml/features/nonvalidating/load-external-dtd";
140
141 public static final String EXTERNAL_GENERAL_ENTITIES =
142 "http://xml.org/sax/features/external-general-entities";
143
144 public static final String EXTERNAL_PARAMETER_ENTITIES =
145 "http://xml.org/sax/features/external-parameter-entities";
146
147
148 private LoadExternalDtdFeatureProvider() {
149 }
150
151
152
153
154
155
156
157
158
159
160
161 public static void setFeaturesBySystemProperty(SAXParserFactory factory)
162 throws SAXException, ParserConfigurationException {
163
164 final boolean enableExternalDtdLoad = Boolean.parseBoolean(
165 System.getProperty(ENABLE_EXTERNAL_DTD_LOAD, "false"));
166
167 factory.setFeature(LOAD_EXTERNAL_DTD, enableExternalDtdLoad);
168 factory.setFeature(EXTERNAL_GENERAL_ENTITIES, enableExternalDtdLoad);
169 factory.setFeature(EXTERNAL_PARAMETER_ENTITIES, enableExternalDtdLoad);
170 }
171
172 }
173
174 }