|
44 | 44 |
|
45 | 45 | import java.io.File;
|
46 | 46 | import java.io.IOException;
|
| 47 | +import java.io.InputStream; |
47 | 48 | import java.io.Writer;
|
48 | 49 | import java.net.URL;
|
49 | 50 | import java.util.AbstractList;
|
|
52 | 53 | import java.util.Objects;
|
53 | 54 | import java.util.SortedMap;
|
54 | 55 | import java.util.TreeMap;
|
| 56 | +import javax.xml.XMLConstants; |
55 | 57 | import javax.xml.parsers.DocumentBuilder;
|
56 | 58 | import javax.xml.parsers.DocumentBuilderFactory;
|
57 | 59 | import javax.xml.parsers.ParserConfigurationException;
|
@@ -174,6 +176,22 @@ public class DiffRepository {
|
174 | 176 | private static final LoadingCache<Key, DiffRepository> REPOSITORY_CACHE =
|
175 | 177 | CacheBuilder.newBuilder().build(CacheLoader.from(Key::toRepo));
|
176 | 178 |
|
| 179 | + private static final ThreadLocal<@Nullable DocumentBuilderFactory> DOCUMENT_BUILDER_FACTORY = |
| 180 | + ThreadLocal.withInitial(() -> { |
| 181 | + final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); |
| 182 | + documentBuilderFactory.setXIncludeAware(false); |
| 183 | + documentBuilderFactory.setExpandEntityReferences(false); |
| 184 | + documentBuilderFactory.setNamespaceAware(true); |
| 185 | + try { |
| 186 | + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); |
| 187 | + documentBuilderFactory |
| 188 | + .setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); |
| 189 | + } catch (final ParserConfigurationException e) { |
| 190 | + throw new IllegalStateException("Document Builder configuration failed", e); |
| 191 | + } |
| 192 | + return documentBuilderFactory; |
| 193 | + }); |
| 194 | + |
177 | 195 | //~ Instance fields --------------------------------------------------------
|
178 | 196 |
|
179 | 197 | private final DiffRepository baseRepository;
|
@@ -207,19 +225,17 @@ private DiffRepository(URL refFile, File logFile,
|
207 | 225 | this.modCount = 0;
|
208 | 226 |
|
209 | 227 | // Load the document.
|
210 |
| - DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); |
211 | 228 | try {
|
212 |
| - DocumentBuilder docBuilder = fac.newDocumentBuilder(); |
213 |
| - try { |
| 229 | + DocumentBuilder docBuilder = |
| 230 | + Nullness.castNonNull(DOCUMENT_BUILDER_FACTORY.get()).newDocumentBuilder(); |
| 231 | + try (InputStream inputStream = refFile.openStream()) { |
214 | 232 | // Parse the reference file.
|
215 |
| - this.doc = docBuilder.parse(refFile.openStream()); |
216 |
| - // Don't write a log file yet -- as far as we know, it's still |
217 |
| - // identical. |
| 233 | + this.doc = docBuilder.parse(inputStream); |
| 234 | + // Don't write a log file yet -- as far as we know, it's still identical. |
218 | 235 | } catch (IOException e) {
|
219 | 236 | // There's no reference file. Create and write a log file.
|
220 | 237 | this.doc = docBuilder.newDocument();
|
221 |
| - this.doc.appendChild( |
222 |
| - doc.createElement(ROOT_TAG)); |
| 238 | + this.doc.appendChild(doc.createElement(ROOT_TAG)); |
223 | 239 | flushDoc();
|
224 | 240 | }
|
225 | 241 | this.root = doc.getDocumentElement();
|
|
0 commit comments