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 public class XmlLoader
54 extends DefaultHandler {
55
56
57 private final Map<String, String> publicIdToResourceNameMap;
58
59 private final XMLReader parser;
60
61
62
63
64
65
66
67
68 protected XmlLoader(Map<String, String> publicIdToResourceNameMap)
69 throws SAXException, ParserConfigurationException {
70 this.publicIdToResourceNameMap =
71 UnmodifiableCollectionUtil.copyOfMap(publicIdToResourceNameMap);
72 parser = createXmlReader(this);
73 }
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 InputSource inputSource = null;
90 if (publicId != null) {
91 final String dtdResourceName = publicIdToResourceNameMap.get(publicId);
92
93 if (dtdResourceName != null) {
94 final ClassLoader loader = getClass().getClassLoader();
95 final InputStream dtdIs = loader.getResourceAsStream(dtdResourceName);
96 inputSource = new InputSource(dtdIs);
97 }
98 }
99 return inputSource;
100 }
101
102 @Override
103 public void error(SAXParseException exception) throws SAXException {
104 throw exception;
105 }
106
107
108
109
110
111
112
113
114
115 private static XMLReader createXmlReader(DefaultHandler handler)
116 throws SAXException, ParserConfigurationException {
117 final SAXParserFactory factory = SAXParserFactory.newInstance();
118 LoadExternalDtdFeatureProvider.setFeaturesBySystemProperty(factory);
119 factory.setValidating(true);
120 final XMLReader xmlReader = factory.newSAXParser().getXMLReader();
121 xmlReader.setContentHandler(handler);
122 xmlReader.setEntityResolver(handler);
123 xmlReader.setErrorHandler(handler);
124 return xmlReader;
125 }
126
127
128
129
130
131 public static final class LoadExternalDtdFeatureProvider {
132
133
134 public static final String ENABLE_EXTERNAL_DTD_LOAD = "checkstyle.enableExternalDtdLoad";
135
136
137 public static final String LOAD_EXTERNAL_DTD =
138 "http://apache.org/xml/features/nonvalidating/load-external-dtd";
139
140 public static final String EXTERNAL_GENERAL_ENTITIES =
141 "http://xml.org/sax/features/external-general-entities";
142
143 public static final String EXTERNAL_PARAMETER_ENTITIES =
144 "http://xml.org/sax/features/external-parameter-entities";
145
146
147 private LoadExternalDtdFeatureProvider() {
148 }
149
150
151
152
153
154
155
156
157
158
159
160 public static void setFeaturesBySystemProperty(SAXParserFactory factory)
161 throws SAXException, ParserConfigurationException {
162
163 final boolean enableExternalDtdLoad = Boolean.parseBoolean(
164 System.getProperty(ENABLE_EXTERNAL_DTD_LOAD, "false"));
165
166 factory.setFeature(LOAD_EXTERNAL_DTD, enableExternalDtdLoad);
167 factory.setFeature(EXTERNAL_GENERAL_ENTITIES, enableExternalDtdLoad);
168 factory.setFeature(EXTERNAL_PARAMETER_ENTITIES, enableExternalDtdLoad);
169 }
170
171 }
172
173 }