File eclipse-CVE-2023-4218.patch of Package eclipse.32874

--- a/eclipse.jdt.core/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPathUtil.java	2024-03-19 10:01:54.583093542 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPathUtil.java	2024-03-19 13:58:56.303373550 +0100
@@ -25,6 +25,7 @@
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.eclipse.core.internal.runtime.XmlProcessorFactory;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -221,8 +222,9 @@
 		Element fpElement = null;
 
 		try {
-			DocumentBuilder parser = 
-				DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			@SuppressWarnings("restriction")
+			DocumentBuilder parser = org.eclipse.core.internal.runtime.XmlProcessorFactory
+					.createDocumentBuilderWithErrorOnDOCTYPE();
 			fpElement = parser.parse(new InputSource(reader)).getDocumentElement();
 
 		}
--- a/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLComparer.java	2024-03-19 10:01:54.613093606 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLComparer.java	2024-03-19 13:58:56.306706890 +0100
@@ -164,8 +164,7 @@
 			"</model>\n";
 		
 		// create "actual" model
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-		Document actualModel = factory.newDocumentBuilder().newDocument();
+		Document actualModel = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		Element modelNode = actualModel.createElement(MODEL_TAG);
 		// primary type
 		Element typeNode = actualModel.createElement(TYPE_ELEMENT_TAG);
@@ -203,7 +202,7 @@
 		
 		// load reference model
     	InputSource source = new InputSource(new StringReader(XML_FRAMEWORK_TEST_MODEL));
-        Document expectedModel = factory.newDocumentBuilder().parse(source);
+        Document expectedModel = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().parse(source);
 
         // compare actual and reference
         ByteArrayOutputStream out = new ByteArrayOutputStream();
--- a/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java	2024-03-19 10:01:54.613093606 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java	2024-03-19 13:58:56.306706890 +0100
@@ -65,7 +65,7 @@
 		StringWriter s = new StringWriter();
 		DOMSource domSource = new DOMSource(model);
 		StreamResult streamResult = new StreamResult(s);
-		TransformerFactory tf = TransformerFactory.newInstance();
+		TransformerFactory tf = org.eclipse.core.internal.runtime.XmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
 		Transformer serializer;
 		try {
 			serializer = tf.newTransformer();
@@ -146,8 +146,7 @@
 	 * @throws ParserConfigurationException
 	 */
 	public static Document convertModel(Iterable<? extends javax.lang.model.element.Element> declarations) throws ParserConfigurationException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-		Document model = factory.newDocumentBuilder().newDocument();
+		Document model = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		org.w3c.dom.Element modelNode = model.createElement(MODEL_TAG);
 		
 		XMLConverter converter = new XMLConverter(model);
--- a/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/negative/NegativeModelProc.java	2024-03-19 10:01:54.613093606 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/negative/NegativeModelProc.java	2024-03-19 13:58:56.306706890 +0100
@@ -41,7 +41,6 @@
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
-import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.eclipse.jdt.compiler.apt.tests.processors.base.XMLComparer;
 import org.eclipse.jdt.compiler.apt.tests.processors.base.XMLConverter;
@@ -844,8 +843,7 @@
 		Document actualModel = XMLConverter.convertModel(rootElements);
 		
     	InputSource source = new InputSource(new StringReader(expected));
-    	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        Document expectedModel = factory.newDocumentBuilder().parse(source);
+        Document expectedModel = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().parse(source);
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         StringBuilder summary = new StringBuilder();
--- a/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java	2024-03-19 10:01:54.859760804 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java	2024-03-19 13:58:56.306706890 +0100
@@ -54,7 +54,6 @@
 import java.util.zip.ZipFile;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.resources.IFile;
@@ -3612,7 +3611,8 @@
 				StringReader reader = new StringReader(xmlString);
 				Element cpElement;
 				try {
-					DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+					@SuppressWarnings("restriction")
+					DocumentBuilder parser = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 					cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
 				} catch(SAXException | ParserConfigurationException e){
 					return;
--- a/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java	2024-03-19 10:01:54.859760804 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java	2024-03-19 13:58:56.306706890 +0100
@@ -38,7 +38,6 @@
 import java.util.stream.Collectors;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import org.eclipse.core.resources.ICommand;
 import org.eclipse.core.resources.IFile;
@@ -1268,7 +1267,8 @@
 		StringReader reader = new StringReader(xmlClasspath);
 		Element cpElement;
 		try {
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			@SuppressWarnings("restriction")
+			DocumentBuilder parser = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
 		} catch (SAXException | ParserConfigurationException e) {
 			throw new IOException(Messages.file_badFormat, e);
@@ -1329,8 +1329,9 @@
 			Element node;
 
 			try {
+				@SuppressWarnings("restriction")
 				DocumentBuilder parser =
-					DocumentBuilderFactory.newInstance().newDocumentBuilder();
+						org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 				node = parser.parse(new InputSource(reader)).getDocumentElement();
 			} catch (SAXException | ParserConfigurationException e) {
 				return null;
--- a/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java	2024-03-19 10:01:54.859760804 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java	2024-03-19 13:58:56.310040231 +0100
@@ -21,7 +21,6 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.runtime.Assert;
@@ -150,7 +149,8 @@
 	public static UserLibrary createFromString(Reader reader) throws IOException {
 		Element cpElement;
 		try {
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			@SuppressWarnings("restriction")
+			DocumentBuilder parser = org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
 		} catch (SAXException | ParserConfigurationException e) {
 			throw new IOException(Messages.file_badFormat, e);
--- a/eclipse.jdt.core/org.eclipse.jdt.core.internal.tools/src/org/eclipse/jdt/core/internal/tools/unicode/TableBuilder.java	2024-03-19 10:01:54.613093606 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.core.internal.tools/src/org/eclipse/jdt/core/internal/tools/unicode/TableBuilder.java	2024-03-19 13:58:56.306706890 +0100
@@ -42,11 +42,10 @@
 		List<String> result = new ArrayList<>();
 		SAXParser saxParser = null;
 		try {
-			saxParser = SAXParserFactory.newInstance().newSAXParser();
-		} catch (ParserConfigurationException e) {
-			e.printStackTrace();
-			return null;
-		} catch (SAXException e) {
+			@SuppressWarnings("restriction")
+			SAXParser p = org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
+			saxParser =p;
+		} catch (SAXException | ParserConfigurationException e) {
 			e.printStackTrace();
 			return null;
 		}
--- a/eclipse.jdt.core/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/DecodeCodeFormatterPreferences.java	2024-03-19 10:01:54.633093649 +0100
+++ b/eclipse.jdt.core/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/DecodeCodeFormatterPreferences.java	2024-03-19 13:58:56.306706890 +0100
@@ -26,8 +26,8 @@
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
+import org.eclipse.core.internal.runtime.XmlProcessorFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -63,7 +63,7 @@
 
 	public static Map decodeCodeFormatterOptions(String fileName, String profileName) {
 		try {
-			SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+			SAXParser saxParser = XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 			final DecodeCodeFormatterPreferences preferences = new DecodeCodeFormatterPreferences(profileName);
 			saxParser.parse(new File(fileName), preferences);
 			return preferences.getEntries();
@@ -89,7 +89,7 @@
 				return null;
 			}
 			inputStream = new BufferedInputStream(zipFile.getInputStream(zipEntry));
-			SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+			SAXParser saxParser = XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 			final DecodeCodeFormatterPreferences preferences = new DecodeCodeFormatterPreferences(profileName);
 			saxParser.parse(inputStream, preferences);
 			return preferences.getEntries();
--- a/eclipse.jdt.ui/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/JUnitModel.java	2024-03-19 10:01:55.446428735 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/JUnitModel.java	2024-03-19 14:27:33.606659565 +0100
@@ -33,7 +33,6 @@
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.TransformerFactoryConfigurationError;
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stream.StreamResult;
@@ -65,6 +64,7 @@
 import org.eclipse.jdt.internal.junit.Messages;
 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
 import org.eclipse.jdt.internal.junit.model.TestElement.Status;
+import org.eclipse.jdt.internal.junit.util.XmlProcessorFactoryJdtJunit;
 import org.eclipse.jdt.junit.ITestRunListener;
 
 /**
@@ -386,7 +386,7 @@
 	 */
 	public static TestRunSession importTestRunSession(File file) throws CoreException {
 		try {
-			SAXParserFactory parserFactory= SAXParserFactory.newInstance();
+			SAXParserFactory parserFactory= XmlProcessorFactoryJdtJunit.createSAXFactoryWithErrorOnDOCTYPE();
 //			parserFactory.setValidating(true); // TODO: add DTD and debug flag
 			SAXParser parser= parserFactory.newSAXParser();
 			TestRunHandler handler= new TestRunHandler();
@@ -429,7 +429,7 @@
 			@Override
 			public void run() {
 				try {
-					SAXParserFactory parserFactory= SAXParserFactory.newInstance();
+					SAXParserFactory parserFactory= XmlProcessorFactoryJdtJunit.createSAXFactoryWithErrorOnDOCTYPE();
 //					parserFactory.setValidating(true); // TODO: add DTD and debug flag
 					SAXParser parser= parserFactory.newSAXParser();
 					parser.parse(trimmedUrl, handler);
@@ -477,7 +477,7 @@
 
 	public static void importIntoTestRunSession(File swapFile, TestRunSession testRunSession) throws CoreException {
 		try {
-			SAXParserFactory parserFactory= SAXParserFactory.newInstance();
+			SAXParserFactory parserFactory= XmlProcessorFactoryJdtJunit.createSAXFactoryWithErrorOnDOCTYPE();
 //			parserFactory.setValidating(true); // TODO: add DTD and debug flag
 			SAXParser parser= parserFactory.newSAXParser();
 			TestRunHandler handler= new TestRunHandler(testRunSession);
@@ -527,7 +527,7 @@
 	public static void exportTestRunSession(TestRunSession testRunSession, OutputStream out)
 			throws TransformerFactoryConfigurationError, TransformerException {
 
-		Transformer transformer= TransformerFactory.newInstance().newTransformer();
+		Transformer transformer= XmlProcessorFactoryJdtJunit.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 		InputSource inputSource= new InputSource();
 		SAXSource source= new SAXSource(new TestRunSessionSerializer(testRunSession), inputSource);
 		StreamResult result= new StreamResult(out);
--- a/eclipse.jdt.ui/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/util/XmlProcessorFactoryJdtJunit.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/util/XmlProcessorFactoryJdtJunit.java	2024-03-19 14:26:46.589900854 +0100
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.junit.util;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+public class XmlProcessorFactoryJdtJunit {
+	private XmlProcessorFactoryJdtJunit() {
+		// static Utility only
+	}
+
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE = createSAXFactoryWithErrorOnDOCTYPE(false);
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE(true);
+	private static final SAXParserFactory SAX_FACTORY_IGNORING_DOCTYPE = createSAXFactoryIgnoringDOCTYPE();
+
+	/**
+	 * Creates TransformerFactory which throws TransformerException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.transform.TransformerFactory
+	 */
+	public static TransformerFactory createTransformerFactoryWithErrorOnDOCTYPE() {
+		TransformerFactory factory = TransformerFactory.newInstance();
+		// prohibit the use of all protocols by external entities:
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); //$NON-NLS-1$
+		return factory;
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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 DocumentBuilder which throws SAXParseException when detecting
+	 * external entities. The builder is not thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		f.setNamespaceAware(awareness);
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryIgnoringDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// ignore DOCTYPE:
+			f.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
+			f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
+			f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return createSAXParserWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @param namespaceAware
+	 *            parameter for SAXParserFactory
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+		if (namespaceAware) {
+			return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+		}
+		return SAX_FACTORY_ERROR_ON_DOCTYPE.newSAXParser();
+	}
+
+	/**
+	 * Creates SAXParser which does not throw Exception when detecting external
+	 * entities but ignores them.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserIgnoringDOCTYPE()
+			throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException {
+		SAXParser parser = SAX_FACTORY_IGNORING_DOCTYPE.newSAXParser();
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+}
\ No newline at end of file
--- "a/eclipse.jdt.ui/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/template/java/TemplateSet.java"	2024-03-19 10:01:55.476428800 +0100
+++ "b/eclipse.jdt.ui/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/template/java/TemplateSet.java"	2024-03-19 14:26:46.589900854 +0100
@@ -29,7 +29,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -53,6 +52,8 @@
 import org.eclipse.jface.text.templates.TemplateContextType;
 import org.eclipse.jface.text.templates.TemplateException;
 
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
+
 /**
  * <code>TemplateSet</code> manages a collection of templates and makes them
  * persistent.
@@ -121,7 +122,7 @@
 	 */
 	public void addFromStream(InputStream stream, boolean allowDuplicates) throws CoreException {
 		try {
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			DocumentBuilder parser= factory.newDocumentBuilder();
 			parser.setErrorHandler(new DefaultHandler());
 			Document document= parser.parse(new InputSource(stream));
@@ -230,7 +231,7 @@
 	 */
 	public void saveToStream(OutputStream stream) throws CoreException {
 		try {
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			DocumentBuilder builder= factory.newDocumentBuilder();
 			Document document= builder.newDocument();
 
@@ -262,7 +263,7 @@
 			}
 
 
-			Transformer transformer=TransformerFactory.newInstance().newTransformer();
+			Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 			DOMSource source = new DOMSource(document);
--- "a/eclipse.jdt.ui/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/History.java"	2024-03-19 10:01:55.476428800 +0100
+++ "b/eclipse.jdt.ui/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/History.java"	2024-03-19 14:28:39.276788126 +0100
@@ -32,7 +32,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.TransformerFactoryConfigurationError;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
@@ -55,6 +54,7 @@
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.JavaUIException;
 import org.eclipse.jdt.internal.ui.JavaUIStatus;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 
 /**
@@ -257,7 +257,7 @@
 	private void load(InputSource inputSource) throws CoreException {
 		Element root;
 		try {
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder parser = XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder();
 			parser.setErrorHandler(new DefaultHandler());
 			root = parser.parse(inputSource).getDocumentElement();
 		} catch (SAXException e) {
@@ -291,7 +291,7 @@
 
 	private void save(OutputStream stream) throws CoreException {
 		try {
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			DocumentBuilder builder= factory.newDocumentBuilder();
 			Document document= builder.newDocument();
 
@@ -306,7 +306,7 @@
 				rootElement.appendChild(element);
 			}
 
-			Transformer transformer=TransformerFactory.newInstance().newTransformer();
+			Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackager/JarPackageReader.java	2024-03-19 10:01:55.509762205 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackager/JarPackageReader.java	2024-03-19 14:26:46.593234194 +0100
@@ -69,6 +69,7 @@
 
 import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
 import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 
 /**
  * Reads data from an InputStream and returns a JarPackage
@@ -120,7 +121,7 @@
 	}
 
 	public JarPackageData readXML(JarPackageData jarPackage) throws IOException, SAXException {
-	  	DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+	  	DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
     	factory.setValidating(false);
 		DocumentBuilder parser= null;
 
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackager/JarPackageWriter.java	2024-03-19 10:01:55.509762205 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackager/JarPackageWriter.java	2024-03-19 14:26:46.593234194 +0100
@@ -27,7 +27,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -56,6 +55,7 @@
 
 import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
 import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 
 /**
  * Writes a JarPackage to an underlying OutputStream
@@ -97,7 +97,7 @@
 	public void writeXML(JarPackageData jarPackage) throws IOException {
 		Assert.isNotNull(jarPackage);
 		DocumentBuilder docBuilder= null;
-		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+		DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 		factory.setValidating(false);
 		try {
 	    	docBuilder= factory.newDocumentBuilder();
@@ -119,7 +119,7 @@
 
 		try {
 			// Write the document to the stream
-			Transformer transformer=TransformerFactory.newInstance().newTransformer();
+			Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, fEncoding);
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/FatJarRsrcUrlAntExporter.java	2024-03-19 10:01:55.486428821 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/FatJarRsrcUrlAntExporter.java	2024-03-19 14:26:46.593234194 +0100
@@ -31,7 +31,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -44,6 +43,7 @@
 import org.eclipse.debug.core.ILaunchConfiguration;
 
 import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 
 /**
  * Create an ANT script for a runnable JAR with class loader export. The script is generated based
@@ -82,7 +82,7 @@
 		String absJarname= absJarfile.toString();
 
 		DocumentBuilder docBuilder= null;
-		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+		DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 		factory.setValidating(false);
 		try {
 			docBuilder= factory.newDocumentBuilder();
@@ -164,7 +164,7 @@
 
 		try {
 			// Write the document to the stream
-			Transformer transformer= TransformerFactory.newInstance().newTransformer();
+			Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/UnpackFatJarAntExporter.java	2024-03-19 10:01:55.486428821 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/UnpackFatJarAntExporter.java	2024-03-19 14:26:46.593234194 +0100
@@ -27,7 +27,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -39,6 +38,8 @@
 
 import org.eclipse.debug.core.ILaunchConfiguration;
 
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
+
 /**
  * @since 3.5
  */
@@ -54,7 +55,7 @@
 			String absJarname= absJarfile.toString();
 
 			DocumentBuilder docBuilder= null;
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			factory.setValidating(false);
 			try {
 				docBuilder= factory.newDocumentBuilder();
@@ -114,7 +115,7 @@
 
 			try {
 				// Write the document to the stream
-				Transformer transformer= TransformerFactory.newInstance().newTransformer();
+				Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/UnpackJarAntExporter.java	2024-03-19 10:01:55.486428821 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/jarpackagerfat/UnpackJarAntExporter.java	2024-03-19 14:26:46.593234194 +0100
@@ -28,7 +28,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -40,6 +39,8 @@
 
 import org.eclipse.debug.core.ILaunchConfiguration;
 
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
+
 /**
  * Create an ANT script for a runnable JAR wit libraries in a sub-folder. The script is generated
  * based on the classpath of the selected launch-configuration.
@@ -60,7 +61,7 @@
 			String absSubfolder= absJarfile.removeLastSegments(1).append(subfolder).toString();
 
 			DocumentBuilder docBuilder= null;
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			factory.setValidating(false);
 			try {
 				docBuilder= factory.newDocumentBuilder();
@@ -147,7 +148,7 @@
 
 			try {
 				// Write the document to the stream
-				Transformer transformer= TransformerFactory.newInstance().newTransformer();
+				Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocReader.java	2024-03-19 10:01:55.516428886 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocReader.java	2024-03-19 14:26:46.593234194 +0100
@@ -31,6 +31,8 @@
 
 import org.eclipse.core.runtime.Assert;
 
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
+
 
 /**
  * Reads data from an InputStream and returns a JarPackage
@@ -62,7 +64,7 @@
 
 	public Element readXML() throws IOException, SAXException {
 
-		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+		DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 		factory.setValidating(false);
 		DocumentBuilder parser= null;
 		try {
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocWriter.java	2024-03-19 10:01:55.513095546 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocWriter.java	2024-03-19 14:32:20.630554782 +0100
@@ -26,7 +26,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -45,6 +44,8 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
+
 public class JavadocWriter {
 
 	private static final char PATH_SEPARATOR= '/'; // use forward slash for all platforms
@@ -66,7 +67,7 @@
 	public Element createXML(JavadocOptionsManager store) throws ParserConfigurationException {
 
 		DocumentBuilder docBuilder= null;
-		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+		DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 		factory.setValidating(false);
 		docBuilder= factory.newDocumentBuilder();
 		Document document= docBuilder.newDocument();
@@ -103,7 +104,7 @@
 	public static void writeDocument(Element javadocElement, String encoding, OutputStream outputStream) throws TransformerException {
 
 		// Write the document to the stream
-		Transformer transformer=TransformerFactory.newInstance().newTransformer();
+		Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 		transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 		transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
 		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileStore.java	2024-03-19 10:01:55.486428821 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileStore.java	2024-03-19 14:26:46.593234194 +0100
@@ -38,7 +38,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -62,6 +61,7 @@
 import org.eclipse.jdt.internal.ui.JavaUIStatus;
 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.CustomProfile;
 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.Profile;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 
 
 /**
@@ -238,7 +238,7 @@
 
 		final ProfileDefaultHandler handler= new ProfileDefaultHandler();
 		try {
-		    final SAXParserFactory factory= SAXParserFactory.newInstance();
+		    final SAXParserFactory factory= XmlProcessorFactoryJdtUi.createSAXFactoryWithErrorOnDOCTYPE();
 			final SAXParser parser= factory.newSAXParser();
 			parser.parse(inputSource, handler);
 		} catch (SAXException | IOException | ParserConfigurationException e) {
@@ -278,7 +278,7 @@
 	public static void writeProfilesToStream(Collection<Profile> profiles, OutputStream stream, String encoding, IProfileVersioner profileVersioner) throws CoreException {
 
 		try {
-			final DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+			final DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 			final DocumentBuilder builder= factory.newDocumentBuilder();
 			final Document document= builder.newDocument();
 
@@ -295,7 +295,7 @@
 				}
 			}
 
-			Transformer transformer=TransformerFactory.newInstance().newTransformer();
+			Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java	2024-03-19 10:01:55.489762162 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java	2024-03-19 14:30:24.676994457 +0100
@@ -35,7 +35,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -117,6 +116,7 @@
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
 import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 import org.eclipse.jdt.internal.ui.wizards.buildpaths.AccessRulesDialog;
 import org.eclipse.jdt.internal.ui.wizards.buildpaths.ArchiveFileFilter;
 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport;
@@ -567,7 +567,7 @@
 			OutputStream stream= new FileOutputStream(file);
 			try {
 				DocumentBuilder docBuilder= null;
-				DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+				DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 				factory.setValidating(false);
 				docBuilder= factory.newDocumentBuilder();
 				Document document= docBuilder.newDocument();
@@ -622,7 +622,7 @@
 				}
 
 				// Write the document to the stream
-				Transformer transformer=TransformerFactory.newInstance().newTransformer();
+				Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
 				transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
@@ -649,7 +649,7 @@
 			InputStream stream= new FileInputStream(file);
 			Element cpElement;
 			try {
-				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+				DocumentBuilder parser = XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder();
 				parser.setErrorHandler(new DefaultHandler());
 				cpElement = parser.parse(new InputSource(stream)).getDocumentElement();
 			} catch (SAXException | ParserConfigurationException e) {
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistHistory.java	2024-03-19 10:01:55.496428843 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistHistory.java	2024-03-19 14:26:46.593234194 +0100
@@ -34,7 +34,6 @@
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -62,6 +61,7 @@
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.JavaUIException;
 import org.eclipse.jdt.internal.ui.JavaUIStatus;
+import org.eclipse.jdt.internal.ui.util.XmlProcessorFactoryJdtUi;
 
 /**
  * An LRU cache for code assist.
@@ -85,7 +85,7 @@
 
 		public void store(ContentAssistHistory history, StreamResult result) throws CoreException {
 			try {
-				DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+				DocumentBuilderFactory factory= XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 				DocumentBuilder builder= factory.newDocumentBuilder();
 				Document document= builder.newDocument();
 
@@ -106,7 +106,7 @@
 					}
 				}
 
-				Transformer transformer=TransformerFactory.newInstance().newTransformer();
+				Transformer transformer= XmlProcessorFactoryJdtUi.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
 				transformer.setOutputProperty(OutputKeys.INDENT, "no"); //$NON-NLS-1$
@@ -121,7 +121,7 @@
 		public ContentAssistHistory load(InputSource source) throws CoreException {
 			Element root;
 			try {
-				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+				DocumentBuilder parser = XmlProcessorFactoryJdtUi.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder();
 				parser.setErrorHandler(new DefaultHandler());
 				root = parser.parse(source).getDocumentElement();
 			} catch (SAXException | ParserConfigurationException | IOException e) {
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/XmlProcessorFactoryJdtUi.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/XmlProcessorFactoryJdtUi.java	2024-03-19 14:26:46.593234194 +0100
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.util;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+public class XmlProcessorFactoryJdtUi {
+	private XmlProcessorFactoryJdtUi() {
+		// static Utility only
+	}
+
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE = createSAXFactoryWithErrorOnDOCTYPE(false);
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE(true);
+	private static final SAXParserFactory SAX_FACTORY_IGNORING_DOCTYPE = createSAXFactoryIgnoringDOCTYPE();
+
+	/**
+	 * Creates TransformerFactory which throws TransformerException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.transform.TransformerFactory
+	 */
+	public static TransformerFactory createTransformerFactoryWithErrorOnDOCTYPE() {
+		TransformerFactory factory = TransformerFactory.newInstance();
+		// prohibit the use of all protocols by external entities:
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); //$NON-NLS-1$
+		return factory;
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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 DocumentBuilder which throws SAXParseException when detecting
+	 * external entities. The builder is not thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		f.setNamespaceAware(awareness);
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryIgnoringDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// ignore DOCTYPE:
+			f.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
+			f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
+			f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return createSAXParserWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @param namespaceAware
+	 *            parameter for SAXParserFactory
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+		if (namespaceAware) {
+			return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+		}
+		return SAX_FACTORY_ERROR_ON_DOCTYPE.newSAXParser();
+	}
+
+	/**
+	 * Creates SAXParser which does not throw Exception when detecting external
+	 * entities but ignores them.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserIgnoringDOCTYPE()
+			throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException {
+		SAXParser parser = SAX_FACTORY_IGNORING_DOCTYPE.newSAXParser();
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+}
\ No newline at end of file
--- a/eclipse.jdt.ui/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/jarexport/FatJarExportTests.java	2024-03-19 10:01:55.436428713 +0100
+++ b/eclipse.jdt.ui/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/jarexport/FatJarExportTests.java	2024-03-19 14:26:46.589900854 +0100
@@ -28,7 +28,6 @@
 import java.util.zip.ZipFile;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -73,6 +72,7 @@
 import org.eclipse.jdt.core.JavaCore;
 
 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.junit.util.XmlProcessorFactoryJdtJunit;
 
 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jdt.launching.IVMInstall;
@@ -664,7 +664,7 @@
 	 */
 	private static Element readXML(IPath xmlFilePath) throws Exception {
 		try (InputStream in = new FileInputStream(xmlFilePath.toFile())) {
-			DocumentBuilder parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder parser= XmlProcessorFactoryJdtJunit.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder();
 			parser.setErrorHandler(new DefaultHandler());
 			Element root= parser.parse(new InputSource(in)).getDocumentElement();
 			in.close();
--- a/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/history/RefactoringHistoryManager.java	2024-03-19 10:01:55.423095351 +0100
+++ b/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/history/RefactoringHistoryManager.java	2024-03-19 14:26:46.593234194 +0100
@@ -39,7 +39,6 @@
 import java.util.TimeZone;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.xml.sax.InputSource;
@@ -84,6 +83,7 @@
 import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin;
 import org.eclipse.ltk.internal.core.refactoring.RefactoringSessionReader;
 import org.eclipse.ltk.internal.core.refactoring.RefactoringSessionTransformer;
+import org.eclipse.ltk.internal.core.refactoring.XmlProcessorFactoryLtk;
 
 /**
  * Manager for persistable refactoring histories.
@@ -906,7 +906,7 @@
 	private Document getCachedDocument(final IPath path, final InputStream input) throws SAXException, IOException, ParserConfigurationException {
 		if (path.equals(fCachedPath) && fCachedDocument != null)
 			return fCachedDocument;
-		DocumentBuilder parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder parser= XmlProcessorFactoryLtk.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder();
 		parser.setErrorHandler(new DefaultHandler());
 		final Document document= parser.parse(new InputSource(input));
 		fCachedDocument= document;
--- a/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/RefactoringSessionReader.java	2024-03-19 10:01:55.423095351 +0100
+++ b/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/RefactoringSessionReader.java	2024-03-19 14:26:46.593234194 +0100
@@ -136,7 +136,7 @@
 		fSessionFound= false;
 		try {
 			source.setSystemId("/"); //$NON-NLS-1$
-			createParser(SAXParserFactory.newInstance()).parse(source, this);
+			createParser(XmlProcessorFactoryLtk.createSAXFactoryWithErrorOnDOCTYPE()).parse(source, this);
 			if (!fSessionFound)
 				throw new CoreException(new Status(IStatus.ERROR, RefactoringCorePlugin.getPluginId(), IRefactoringCoreStatusCodes.REFACTORING_HISTORY_FORMAT_ERROR, RefactoringCoreMessages.RefactoringSessionReader_no_session, null));
 			if (fRefactoringDescriptors != null) {
--- a/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/RefactoringSessionTransformer.java	2024-03-19 10:01:55.423095351 +0100
+++ b/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/RefactoringSessionTransformer.java	2024-03-19 14:26:46.593234194 +0100
@@ -19,7 +19,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 
@@ -138,7 +137,7 @@
 		Assert.isTrue(flags >= RefactoringDescriptor.NONE);
 		try {
 			if (fDocument == null)
-				fDocument= DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+				fDocument= XmlProcessorFactoryLtk.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder().newDocument();
 		} catch (ParserConfigurationException | FactoryConfigurationError exception) {
 			throw new CoreException(new Status(IStatus.ERROR, RefactoringCorePlugin.getPluginId(), IRefactoringCoreStatusCodes.REFACTORING_HISTORY_IO_ERROR, exception.getLocalizedMessage(), null));
 		}
@@ -203,7 +202,7 @@
 	public void beginSession(final String comment, final String version) throws CoreException {
 		if (fDocument == null) {
 			try {
-				fDocument= DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+				fDocument= XmlProcessorFactoryLtk.createDocumentBuilderFactoryWithErrorOnDOCTYPE().newDocumentBuilder().newDocument();
 				fSession= fDocument.createElement(IRefactoringSerializationConstants.ELEMENT_SESSION);
 				fSessionArguments= new ArrayList<>(2);
 				Attr attribute= fDocument.createAttribute(IRefactoringSerializationConstants.ATTRIBUTE_VERSION);
--- a/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/XmlProcessorFactoryLtk.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.jdt.ui/org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/XmlProcessorFactoryLtk.java	2024-03-19 14:26:46.593234194 +0100
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.ltk.internal.core.refactoring;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+public class XmlProcessorFactoryLtk {
+	private XmlProcessorFactoryLtk() {
+		// static Utility only
+	}
+
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE = createSAXFactoryWithErrorOnDOCTYPE(false);
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE(true);
+	private static final SAXParserFactory SAX_FACTORY_IGNORING_DOCTYPE = createSAXFactoryIgnoringDOCTYPE();
+
+	/**
+	 * Creates TransformerFactory which throws TransformerException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.transform.TransformerFactory
+	 */
+	public static TransformerFactory createTransformerFactoryWithErrorOnDOCTYPE() {
+		TransformerFactory factory = TransformerFactory.newInstance();
+		// prohibit the use of all protocols by external entities:
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); //$NON-NLS-1$
+		return factory;
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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 DocumentBuilder which throws SAXParseException when detecting
+	 * external entities. The builder is not thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		f.setNamespaceAware(awareness);
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryIgnoringDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// ignore DOCTYPE:
+			f.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
+			f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
+			f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return createSAXParserWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @param namespaceAware
+	 *            parameter for SAXParserFactory
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+		if (namespaceAware) {
+			return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+		}
+		return SAX_FACTORY_ERROR_ON_DOCTYPE.newSAXParser();
+	}
+
+	/**
+	 * Creates SAXParser which does not throw Exception when detecting external
+	 * entities but ignores them.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserIgnoringDOCTYPE()
+			throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException {
+		SAXParser parser = SAX_FACTORY_IGNORING_DOCTYPE.newSAXParser();
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+}
\ No newline at end of file
--- a/eclipse.pde.build/org.eclipse.pde.build/src_ant/org/eclipse/pde/internal/build/tasks/JNLPGenerator.java	2024-03-19 10:01:54.569760179 +0100
+++ b/eclipse.pde.build/org.eclipse.pde.build/src_ant/org/eclipse/pde/internal/build/tasks/JNLPGenerator.java	2024-03-19 12:46:16.971563577 +0100
@@ -46,7 +46,6 @@
 	 * feature.includes = extension
 	 * feature.plugin = jar
 	 */
-	private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
 	private PrintWriter out;
 	private String destination;
 	private String provider;
@@ -89,8 +88,7 @@
 		this.locale = locale;
 		this.generateOfflineAllowed = generateOfflineAllowed;
 		try {
-			parserFactory.setNamespaceAware(true);
-			parser = parserFactory.newSAXParser();
+			parser = XmlParserFactory.createNsAwareSAXParserWithErrorOnDOCTYPE();;
 		} catch (ParserConfigurationException e) {
 			System.out.println(e);
 		} catch (SAXException e) {
--- a/eclipse.pde.build/org.eclipse.pde.build/src_ant/org/eclipse/pde/internal/build/tasks/XmlParserFactory.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.pde.build/org.eclipse.pde.build/src_ant/org/eclipse/pde/internal/build/tasks/XmlParserFactory.java	2024-03-19 12:44:11.157984851 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.pde.internal.build.tasks;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+
+public class XmlParserFactory {
+	private XmlParserFactory() {
+		// static Utility only
+	}
+
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE();
+
+	private static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		f.setNamespaceAware(true);
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	public static SAXParser createNsAwareSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+	}
+
+}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java	2024-03-19 10:01:54.273092873 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java	2024-03-20 09:29:06.196226859 +0100
@@ -31,7 +31,6 @@
 import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 
@@ -61,6 +60,7 @@
 import org.eclipse.pde.core.plugin.ModelEntry;
 import org.eclipse.pde.core.plugin.PluginRegistry;
 import org.eclipse.pde.internal.core.DependencyManager;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -426,7 +426,7 @@
 		long start = System.currentTimeMillis();
 		DocumentBuilder parser = null;
 		try {
-			parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			parser.setErrorHandler(new DefaultHandler());
 		} catch (ParserConfigurationException | FactoryConfigurationError e) {
 			abort("Error restoring API baseline", e); //$NON-NLS-1$
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/APIFileGenerator.java	2024-03-19 10:01:54.273092873 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/APIFileGenerator.java	2024-03-19 13:23:43.742521888 +0100
@@ -32,10 +32,8 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jdt.core.JavaCore;
@@ -48,6 +46,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeContainer;
 import org.eclipse.pde.api.tools.internal.provisional.scanner.TagScanner;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.xml.sax.Attributes;
@@ -459,15 +458,9 @@
 	 * @return true if it contains a source extension point, false otherwise
 	 */
 	private boolean containsAPIToolsNature(String pluginXMLContents) {
-		SAXParserFactory factory = null;
-		try {
-			factory = SAXParserFactory.newInstance();
-		} catch (FactoryConfigurationError e) {
-			return false;
-		}
 		SAXParser saxParser = null;
 		try {
-			saxParser = factory.newSAXParser();
+			saxParser = PDEXmlProcessorFactory.createSAXParserIgnoringDOCTYPE();
 		} catch (ParserConfigurationException | SAXException e) {
 			// ignore
 		}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java	2024-03-19 10:01:54.273092873 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java	2024-03-20 08:58:08.409268636 +0100
@@ -36,10 +36,8 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
@@ -80,6 +78,7 @@
 import org.eclipse.pde.api.tools.internal.util.Util;
 import org.eclipse.pde.internal.core.TargetWeaver;
 import org.eclipse.pde.internal.core.util.ManifestUtils;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
@@ -1057,15 +1056,9 @@
 	 * @return true if it contains a source extension point, false otherwise
 	 */
 	private boolean containsSourceExtensionPoint(String pluginXMLContents) {
-		SAXParserFactory factory = null;
-		try {
-			factory = SAXParserFactory.newInstance();
-		} catch (FactoryConfigurationError e) {
-			return false;
-		}
 		SAXParser saxParser = null;
 		try {
-			saxParser = factory.newSAXParser();
+			saxParser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		} catch (ParserConfigurationException | SAXException e) {
 			// ignore
 		}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseReportConverter.java	2024-03-19 10:01:54.276426214 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseReportConverter.java	2024-03-20 10:16:44.000012562 +0100
@@ -38,7 +38,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -67,6 +66,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.search.IMetadata;
 import org.eclipse.pde.api.tools.internal.util.Signatures;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.Version;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
@@ -778,9 +778,8 @@
 	 */
 	SAXParser getParser() throws Exception {
 		if (this.parser == null) {
-			SAXParserFactory factory = SAXParserFactory.newInstance();
 			try {
-				this.parser = factory.newSAXParser();
+				this.parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 			} catch (ParserConfigurationException pce) {
 				throw new Exception(SearchMessages.UseReportConverter_pce_error_getting_parser, pce);
 			} catch (SAXException se) {
@@ -858,7 +857,7 @@
 	protected void applyXSLT(Source xslt, File xmlfile, File htmlfile) throws TransformerException {
 		Source xml = new StreamSource(xmlfile);
 		Result html = new StreamResult(htmlfile);
-		TransformerFactory factory = TransformerFactory.newInstance();
+		TransformerFactory factory = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
 		Transformer former = factory.newTransformer(xslt);
 		former.transform(xml, html);
 	}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseScanParser.java	2024-03-19 10:01:54.276426214 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseScanParser.java	2024-03-20 08:58:08.412601975 +0100
@@ -24,7 +24,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.SubMonitor;
@@ -36,6 +35,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor;
 import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -311,9 +311,9 @@
 	 *             builds
 	 */
 	SAXParser getParser() throws Exception {
-		SAXParserFactory factory = SAXParserFactory.newInstance();
 		try {
-			return factory.newSAXParser();
+			return PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
+
 		} catch (ParserConfigurationException pce) {
 			throw new Exception(SearchMessages.UseReportConverter_pce_error_getting_parser, pce);
 		} catch (SAXException se) {
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/XmlReferenceDescriptorWriter.java	2024-03-19 10:01:54.276426214 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/XmlReferenceDescriptorWriter.java	2024-03-20 10:19:14.850323527 +0100
@@ -27,7 +27,6 @@
 import java.util.Map.Entry;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 
@@ -46,6 +45,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember;
 import org.eclipse.pde.api.tools.internal.util.Signatures;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -86,7 +86,7 @@
 	public XmlReferenceDescriptorWriter(String location) {
 		fLocation = location;
 		try {
-			parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			parser.setErrorHandler(new DefaultHandler());
 		} catch (FactoryConfigurationError | ParserConfigurationException pce) {
 			ApiPlugin.log(pce);
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/XmlSearchReporter.java	2024-03-19 10:01:54.276426214 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/XmlSearchReporter.java	2024-03-20 10:21:07.123888283 +0100
@@ -24,7 +24,6 @@
 import java.util.List;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 
@@ -40,6 +39,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.search.IApiSearchReporter;
 import org.eclipse.pde.api.tools.internal.provisional.search.IMetadata;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.helpers.DefaultHandler;
@@ -69,7 +69,7 @@
 		fLocation = location;
 		this.debug = debug;
 		try {
-			parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			parser.setErrorHandler(new DefaultHandler());
 		} catch (FactoryConfigurationError | ParserConfigurationException pce) {
 			ApiPlugin.log(pce);
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/util/Util.java	2024-03-19 10:01:54.273092873 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/util/Util.java	2024-03-20 13:27:46.155319267 +0100
@@ -61,7 +61,6 @@
 import java.util.zip.ZipInputStream;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
@@ -141,6 +140,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
 import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes;
 import org.eclipse.pde.api.tools.internal.search.SkippedComponent;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.objectweb.asm.Opcodes;
 import org.osgi.framework.Version;
 import org.w3c.dom.Document;
@@ -1875,10 +1875,9 @@
 	 * @throws CoreException if unable to create a new document
 	 */
 	public static Document newDocument() throws CoreException {
-		DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 		DocumentBuilder docBuilder = null;
 		try {
-			docBuilder = dfactory.newDocumentBuilder();
+			docBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		} catch (ParserConfigurationException e) {
 			abort("Unable to create new XML document.", e); //$NON-NLS-1$
 		}
@@ -1898,7 +1897,7 @@
 		Element root = null;
 		InputStream stream = null;
 		try {
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			parser.setErrorHandler(new DefaultHandler());
 			stream = new ByteArrayInputStream(document.getBytes(StandardCharsets.UTF_8));
 			root = parser.parse(stream).getDocumentElement();
@@ -1989,7 +1988,7 @@
 	public static String serializeDocument(Document document) throws CoreException {
 		try {
 			ByteArrayOutputStream s = new ByteArrayOutputStream();
-			TransformerFactory factory = TransformerFactory.newInstance();
+			TransformerFactory factory = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
 			Transformer transformer = factory.newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/AnalysisReportConversionTask.java	2024-03-19 10:01:54.269759533 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/AnalysisReportConversionTask.java	2024-03-20 08:58:08.415935315 +0100
@@ -26,7 +26,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -34,6 +33,7 @@
 import org.eclipse.pde.api.tools.internal.IApiXmlConstants;
 import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -444,10 +444,9 @@
 		if (!this.reportsRoot.exists() || !this.reportsRoot.isDirectory()) {
 			throw new BuildException(NLS.bind(Messages.invalid_directory_name, this.xmlReportsLocation));
 		}
-		SAXParserFactory factory = SAXParserFactory.newInstance();
 		SAXParser parser = null;
 		try {
-			parser = factory.newSAXParser();
+			parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		} catch (ParserConfigurationException | SAXException e) {
 			e.printStackTrace();
 		}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIDeprecationReportConversionTask.java	2024-03-19 10:01:54.269759533 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIDeprecationReportConversionTask.java	2024-03-20 08:58:08.415935315 +0100
@@ -25,7 +25,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -34,6 +33,7 @@
 import org.eclipse.pde.api.tools.internal.IApiXmlConstants;
 import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -303,10 +303,9 @@
 			System.out.println("xmlFileLocation : " + this.xmlFileLocation); //$NON-NLS-1$
 			System.out.println("htmlFileLocation : " + this.htmlFileLocation); //$NON-NLS-1$
 		}
-		SAXParserFactory factory = SAXParserFactory.newInstance();
 		SAXParser parser = null;
 		try {
-			parser = factory.newSAXParser();
+			parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		} catch (ParserConfigurationException | SAXException e) {
 			e.printStackTrace();
 		}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIFreezeReportConversionTask.java	2024-03-19 10:01:54.269759533 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIFreezeReportConversionTask.java	2024-03-20 08:58:08.415935315 +0100
@@ -25,7 +25,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -34,6 +33,7 @@
 import org.eclipse.pde.api.tools.internal.IApiXmlConstants;
 import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
 import org.eclipse.pde.api.tools.internal.util.Util;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -481,10 +481,9 @@
 				}
 			}
 		}
-		SAXParserFactory factory = SAXParserFactory.newInstance();
 		SAXParser parser = null;
 		try {
-			parser = factory.newSAXParser();
+			parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		} catch (ParserConfigurationException | SAXException e) {
 			e.printStackTrace();
 		}
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingApiFreezeAntTaskTests.java	2024-03-19 10:01:54.363093068 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingApiFreezeAntTaskTests.java	2024-03-20 10:27:19.504655851 +0100
@@ -22,12 +22,12 @@
 import java.util.Properties;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
@@ -62,7 +62,7 @@
 		IFile reportFile = buildFolder.getFile("report.xml"); //$NON-NLS-1$
 		assertTrue("report.xml must exist", reportFile.exists()); //$NON-NLS-1$
 		InputSource is = new InputSource(reportFile.getContents());
-		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder db = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		Document doc = db.parse(is);
 		NodeList elems = doc.getElementsByTagName("delta"); //$NON-NLS-1$
 		boolean found = false;
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingApiuseAntTaskTests.java	2024-03-19 10:01:54.363093068 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingApiuseAntTaskTests.java	2024-03-20 10:29:56.584979643 +0100
@@ -22,12 +22,12 @@
 import java.util.Properties;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
@@ -65,7 +65,7 @@
 	public void test1() throws Exception {
 		IFolder reportFolder = runTaskAndVerify("test1"); //$NON-NLS-1$
 		InputSource is = new InputSource(reportFolder.getFile("not_searched.xml").getContents()); //$NON-NLS-1$
-		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder db = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		Document doc = db.parse(is);
 
 		NodeList elems = doc.getElementsByTagName("component"); //$NON-NLS-1$
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingCompareAntTaskTests.java	2024-03-19 10:01:54.363093068 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/anttasks/tests/ApiToolingCompareAntTaskTests.java	2024-03-20 10:31:29.578504669 +0100
@@ -20,11 +20,11 @@
 import java.util.Properties;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
@@ -59,7 +59,7 @@
 		assertTrue("report folder must exist", folder.exists()); //$NON-NLS-1$
 		assertTrue("report xml must exist", folder.getFile("compare.xml").exists()); //$NON-NLS-1$ //$NON-NLS-2$
 		InputSource is = new InputSource(folder.getFile("compare.xml").getContents()); //$NON-NLS-1$
-		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder db = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		Document doc = db.parse(is);
 		NodeList elems = doc.getElementsByTagName("delta"); //$NON-NLS-1$
 		boolean found = false;
--- a/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.ui/src/org/eclipse/pde/api/tools/ui/internal/actions/ExportSessionAction.java	2024-03-19 10:01:54.286426235 +0100
+++ b/eclipse.pde.ui/apitools/org.eclipse.pde.api.tools.ui/src/org/eclipse/pde/api/tools/ui/internal/actions/ExportSessionAction.java	2024-03-20 10:35:34.392341472 +0100
@@ -45,6 +45,7 @@
 import org.eclipse.pde.api.tools.ui.internal.ApiUIPlugin;
 import org.eclipse.pde.api.tools.ui.internal.IApiToolsConstants;
 import org.eclipse.pde.api.tools.ui.internal.views.APIToolingView;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 
 /**
  * Drop-down action to select the active session.
@@ -155,8 +156,8 @@
 							writer = new BufferedWriter(new FileWriter(reportFile));
 							Result result = new StreamResult(writer);
 							// create an instance of TransformerFactory
-							TransformerFactory transFact = TransformerFactory.newInstance();
-							Transformer trans = transFact.newTransformer(xsltSource);
+							TransformerFactory f = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
+							Transformer trans = f.newTransformer(xsltSource);
 							trans.transform(xmlSource, result);
 						} catch (TransformerException | IOException e) {
 							ApiUIPlugin.log(e);
--- a/eclipse.pde.ui/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/builders/XMLErrorReporter.java	2024-03-19 10:01:54.256426171 +0100
+++ b/eclipse.pde.ui/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/builders/XMLErrorReporter.java	2024-03-20 10:25:38.027780020 +0100
@@ -18,7 +18,6 @@
 import java.util.HashMap;
 import java.util.Stack;
 
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.filebuffers.FileBuffers;
@@ -36,6 +35,7 @@
 import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.Position;
 import org.eclipse.pde.internal.core.builders.CompilerFlags;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Element;
 import org.w3c.dom.Text;
 import org.xml.sax.Attributes;
@@ -168,10 +168,9 @@
 
 	@Override
 	public void startDocument() throws SAXException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		try {
 			// TODO we should be using a dom level 2 impl
-			fXMLDocument = factory.newDocumentBuilder().newDocument();
+			PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		} catch (ParserConfigurationException e) {
 		}
 	}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/AbstractModel.java	2024-03-19 10:01:54.553093477 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/AbstractModel.java	2024-03-20 08:58:08.415935315 +0100
@@ -21,7 +21,6 @@
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 import org.eclipse.core.filebuffers.FileBuffers;
 import org.eclipse.core.filebuffers.ITextFileBuffer;
 import org.eclipse.core.filebuffers.ITextFileBufferManager;
@@ -38,6 +37,7 @@
 import org.eclipse.pde.core.IModelChangedEvent;
 import org.eclipse.pde.core.IModelChangedListener;
 import org.eclipse.pde.core.ModelChangedEvent;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.xml.sax.SAXException;
 
 public abstract class AbstractModel extends PlatformObject implements IModel, IModelChangeProviderExtension, Serializable {
@@ -195,7 +195,7 @@
 	}
 
 	protected SAXParser getSaxParser() throws ParserConfigurationException, SAXException, FactoryConfigurationError {
-		return SAXParserFactory.newInstance().newSAXParser();
+		return PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 	}
 
 	@Override
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java	2024-03-19 10:01:54.549760137 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java	2024-03-20 09:19:54.608431509 +0100
@@ -28,7 +28,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
@@ -70,6 +69,7 @@
 import org.eclipse.pde.internal.core.text.build.BuildModel;
 import org.eclipse.pde.internal.core.util.CoreUtility;
 import org.eclipse.pde.internal.core.util.PatternConstructor;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.Constants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
@@ -668,7 +668,7 @@
 	// if we're defining fragments, make sure they have entries in plugin.xml
 	private void validateFragmentContributions(IBuildEntry binIncludes) {
 		try {
-			DocumentBuilder newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder newDocumentBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			newDocumentBuilder.setErrorHandler(new PDEErrorHandler());
 			Document doc = newDocumentBuilder.parse(PDEProject.getPluginXml(fProject).getContents());
 			XPath xpath = XPathFactory.newInstance().newXPath();
@@ -684,7 +684,7 @@
 	// if we're defining an application, make sure it has entries in plugin.xml
 	private void validateApplicationContributions(IBuildEntry binIncludes) {
 		try {
-			DocumentBuilder newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder newDocumentBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			newDocumentBuilder.setErrorHandler(new PDEErrorHandler());
 			Document doc = newDocumentBuilder.parse(PDEProject.getPluginXml(fProject).getContents());
 			XPath xpath = XPathFactory.newInstance().newXPath();
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/XMLErrorReporter.java	2024-03-19 10:01:54.549760137 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/XMLErrorReporter.java	2024-03-20 09:21:51.335321249 +0100
@@ -18,7 +18,6 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Stack;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import org.eclipse.core.filebuffers.FileBuffers;
 import org.eclipse.core.filebuffers.ITextFileBufferManager;
@@ -37,6 +36,7 @@
 import org.eclipse.pde.internal.core.PDECoreMessages;
 import org.eclipse.pde.internal.core.TargetPlatformHelper;
 import org.eclipse.pde.internal.core.builders.IncrementalErrorReporter.VirtualMarker;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -196,9 +196,8 @@
 
 	@Override
 	public void startDocument() throws SAXException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		try {
-			fXMLDocument = factory.newDocumentBuilder().newDocument();
+			fXMLDocument = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		} catch (ParserConfigurationException e) {
 		}
 	}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/exports/FeatureExportOperation.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/exports/FeatureExportOperation.java	2024-03-20 11:01:51.585498405 +0100
@@ -37,7 +37,6 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import org.eclipse.ant.core.AntCorePlugin;
@@ -96,6 +95,7 @@
 import org.eclipse.pde.internal.core.project.PDEProject;
 import org.eclipse.pde.internal.core.target.TargetMetadataCollector;
 import org.eclipse.pde.internal.core.util.CoreUtility;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.InvalidSyntaxException;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
@@ -205,8 +205,7 @@
 		try {
 			scriptFile = createScriptFile("append.xml"); //$NON-NLS-1$
 
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 
 			Element root = doc.createElement("project"); //$NON-NLS-1$
 			root.setAttribute("name", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -870,8 +869,7 @@
 		File scriptFile = null;
 		try {
 			scriptFile = createScriptFile("zip.xml"); //$NON-NLS-1$
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 
 			Element root = doc.createElement("project"); //$NON-NLS-1$
 			root.setAttribute("name", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -942,8 +940,7 @@
 	private void createFeature(String featureID, String featureLocation, Object[] featuresExported, Document doc, Element root, Properties prop) throws IOException {
 		try {
 			if (doc == null) {
-				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-				doc = factory.newDocumentBuilder().newDocument();
+				doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 				root = doc.createElement("feature"); //$NON-NLS-1$
 				root.setAttribute("id", featureID); //$NON-NLS-1$
 				root.setAttribute("version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -1048,8 +1045,7 @@
 		}
 
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 			Element root = doc.createElement("feature"); //$NON-NLS-1$
 			root.setAttribute("id", featureID); //$NON-NLS-1$
 			root.setAttribute("version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDEAuxiliaryState.java	2024-03-19 10:01:54.543093455 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDEAuxiliaryState.java	2024-03-20 10:58:55.251809821 +0100
@@ -20,7 +20,6 @@
 import java.util.Iterator;
 import java.util.Map;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import org.eclipse.osgi.service.resolver.BundleDescription;
@@ -31,6 +30,7 @@
 import org.eclipse.pde.core.plugin.IPluginModelBase;
 import org.eclipse.pde.internal.core.ibundle.IBundleModel;
 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.w3c.dom.Document;
@@ -194,8 +194,7 @@
 	 */
 	protected void savePluginInfo(File dir) {
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 			Element root = doc.createElement(ELEMENT_ROOT);
 
 			Iterator<String> iter = fPluginInfos.keySet().iterator();
@@ -254,8 +253,7 @@
 		File file = new File(dir, CACHE_EXTENSION);
 		if (file.exists() && file.isFile()) {
 			try {
-				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-				DocumentBuilder documentBuilder = factory.newDocumentBuilder();
+				DocumentBuilder documentBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 				documentBuilder.setErrorHandler(new DefaultHandler());
 				Document doc = documentBuilder.parse(file);
 				Element root = doc.getDocumentElement();
@@ -294,7 +292,7 @@
 	 */
 	public static void writePluginInfo(IPluginModelBase[] models, File destination) {
 		try {
-			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder builder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			Document doc = builder.newDocument();
 
 			Element root = doc.createElement(ELEMENT_ROOT);
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/AbstractExtensions.java	2024-03-19 10:01:54.549760137 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/AbstractExtensions.java	2024-03-20 08:58:08.419268655 +0100
@@ -22,7 +22,6 @@
 import java.util.Collections;
 import java.util.List;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParserFactory;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.pde.core.IModelChangedEvent;
@@ -34,6 +33,7 @@
 import org.eclipse.pde.core.plugin.ISharedPluginModel;
 import org.eclipse.pde.internal.core.PDECore;
 import org.eclipse.pde.internal.core.PDECoreMessages;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
@@ -197,7 +197,7 @@
 					try {
 						InputStream stream = new BufferedInputStream(((IFile) res).getContents(true));
 						PluginHandler handler = new PluginHandler(true);
-						SAXParserFactory.newInstance().newSAXParser().parse(stream, handler);
+						PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE().parse(stream, handler);
 						return handler.getSchemaVersion();
 					} catch (CoreException | SAXException | IOException | ParserConfigurationException e) {
 					}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginBase.java	2024-03-19 10:01:54.549760137 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginBase.java	2024-03-20 08:58:08.419268655 +0100
@@ -19,7 +19,6 @@
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.osgi.service.resolver.BundleDescription;
 import org.eclipse.osgi.service.resolver.BundleSpecification;
@@ -34,6 +33,7 @@
 import org.eclipse.pde.internal.core.PDECoreMessages;
 import org.eclipse.pde.internal.core.PDEState;
 import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.osgi.framework.Version;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -400,7 +400,8 @@
 	}
 
 	protected SAXParser getSaxParser() throws ParserConfigurationException, SAXException, FactoryConfigurationError {
-		return SAXParserFactory.newInstance().newSAXParser();
+		return PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
+
 	}
 
 	public static int getMatchRule(VersionRange versionRange) {
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginHandler.java	2024-03-19 10:01:54.549760137 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginHandler.java	2024-03-20 11:03:25.495687610 +0100
@@ -17,10 +17,10 @@
 import java.util.Stack;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import org.eclipse.pde.internal.core.TargetPlatformHelper;
 import org.eclipse.pde.internal.core.util.IdUtil;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -97,9 +97,8 @@
 
 	@Override
 	public void startDocument() throws SAXException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		try {
-			fDocument = factory.newDocumentBuilder().newDocument();
+			fDocument = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		} catch (ParserConfigurationException e) {
 		}
 	}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java	2024-03-20 10:44:30.320077119 +0100
@@ -66,6 +66,7 @@
 import org.eclipse.pde.core.target.TargetBundle;
 import org.eclipse.pde.core.target.TargetFeature;
 import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -696,7 +697,7 @@
 		Element containerElement;
 		Document document;
 		try {
-			DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder docBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			document = docBuilder.newDocument();
 		} catch (Exception e) {
 			PDECore.log(e);
@@ -729,7 +730,8 @@
 		try {
 			document.appendChild(containerElement);
 			StreamResult result = new StreamResult(new StringWriter());
-			Transformer transformer = TransformerFactory.newInstance().newTransformer();
+			TransformerFactory f = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
+			Transformer transformer = f.newTransformer();
 			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
 			transformer.transform(new DOMSource(document), result);
 			return result.getWriter().toString();
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IULocationFactory.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IULocationFactory.java	2024-03-20 09:23:38.478859337 +0100
@@ -27,6 +27,7 @@
 import org.eclipse.pde.core.target.ITargetLocation;
 import org.eclipse.pde.core.target.ITargetLocationFactory;
 import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -45,7 +46,7 @@
 
 		Element location;
 		try {
-			DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			DocumentBuilder docBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			Document document = docBuilder
 					.parse(new ByteArrayInputStream(serializedXML.getBytes(StandardCharsets.UTF_8)));
 			location = document.getDocumentElement();
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetDefinition.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetDefinition.java	2024-03-20 10:48:11.437184806 +0100
@@ -32,7 +32,6 @@
 import java.util.Map.Entry;
 import java.util.Set;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerException;
 import org.eclipse.core.runtime.CoreException;
@@ -60,6 +59,7 @@
 import org.eclipse.pde.internal.core.ICoreConstants;
 import org.eclipse.pde.internal.core.PDECore;
 import org.eclipse.pde.internal.core.TargetPlatformHelper;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -133,8 +133,7 @@
 
 	private static Document createNewDocument() {
 		try {
-			DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
-			DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+			DocumentBuilder docBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			Document doc = docBuilder.newDocument();
 			ProcessingInstruction instruction = doc.createProcessingInstruction(
 					TargetDefinitionPersistenceHelper.PDE_INSTRUCTION,
@@ -1238,8 +1237,7 @@
 		List<Element> oldIUContainers = new ArrayList<>();
 		List<Element> oldGenericContainers = new ArrayList<>();
 
-		DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
-		DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+		DocumentBuilder docBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		for (ITargetLocation targetLocation : targetLocations) {
 			String type = targetLocation.getType();
 			if (targetLocation instanceof DirectoryBundleContainer) {
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetDefinitionPersistenceHelper.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetDefinitionPersistenceHelper.java	2024-03-20 10:38:02.182636244 +0100
@@ -22,7 +22,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -37,6 +36,7 @@
 import org.eclipse.pde.core.target.ITargetPlatformService;
 import org.eclipse.pde.internal.core.ICoreConstants;
 import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -122,7 +122,7 @@
 			return;
 		}
 		StreamResult outputTarget = new StreamResult(output);
-		TransformerFactory factory = TransformerFactory.newInstance();
+		TransformerFactory factory = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
 		Transformer transformer = factory.newTransformer();
 		transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
@@ -151,7 +151,7 @@
 	 */
 	public static void initFromXML(ITargetDefinition definition, InputStream input)
 			throws CoreException, ParserConfigurationException, SAXException, IOException {
-		DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		parser.setErrorHandler(new DefaultHandler());
 		Document doc = parser.parse(new InputSource(input));
 
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetPersistence38Helper.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/TargetPersistence38Helper.java	2024-03-20 10:40:10.876226264 +0100
@@ -35,6 +35,7 @@
 import org.eclipse.pde.core.target.ITargetLocationFactory;
 import org.eclipse.pde.core.target.NameVersionDescriptor;
 import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -246,7 +247,8 @@
 					throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.TargetPersistence38Helper_NoTargetLocationExtension, type)));
 				}
 				StreamResult result = new StreamResult(new StringWriter());
-				Transformer transformer = TransformerFactory.newInstance().newTransformer();
+				TransformerFactory factory = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
+				Transformer transformer = factory.newTransformer();
 				transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
 				transformer.transform(new DOMSource(location), result);
 				container = locFactory.getTargetLocation(type, result.getWriter().toString());
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/PDEXMLHelper.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/PDEXMLHelper.java	2024-03-20 10:55:12.231360549 +0100
@@ -13,14 +13,7 @@
  *******************************************************************************/
 package org.eclipse.pde.internal.core.util;
 
-import java.lang.ref.SoftReference;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import org.xml.sax.SAXException;
@@ -31,56 +24,16 @@
  */
 public class PDEXMLHelper {
 
-	protected static SAXParserFactory fSAXFactory;
 	protected static PDEXMLHelper fPinstance;
-	protected static DocumentBuilderFactory fDOMFactory;
-	protected static List<SoftReference<SAXParser>> fSAXParserQueue;
-	protected static List<SoftReference<DocumentBuilder>> fDOMParserQueue;
 	protected static int fSAXPoolLimit;
 	protected static int fDOMPoolLimit;
 	protected static final int FMAXPOOLLIMIT = 1;
 
 	protected PDEXMLHelper() throws FactoryConfigurationError {
-		fSAXFactory = SAXParserFactory.newInstance();
-		fDOMFactory = DocumentBuilderFactory.newInstance();
-		fSAXParserQueue = Collections.synchronizedList(new LinkedList<SoftReference<SAXParser>>());
-		fDOMParserQueue = Collections.synchronizedList(new LinkedList<SoftReference<DocumentBuilder>>());
 		fSAXPoolLimit = FMAXPOOLLIMIT;
 		fDOMPoolLimit = FMAXPOOLLIMIT;
 	}
 
-	public synchronized SAXParser getDefaultSAXParser() throws ParserConfigurationException, SAXException {
-
-		SAXParser parser = null;
-		if (fSAXParserQueue.isEmpty()) {
-			parser = fSAXFactory.newSAXParser();
-		} else {
-			SoftReference<?> reference = fSAXParserQueue.remove(0);
-			if (reference.get() != null) {
-				parser = (SAXParser) reference.get();
-			} else {
-				parser = fSAXFactory.newSAXParser();
-			}
-		}
-		return parser;
-	}
-
-	public synchronized DocumentBuilder getDefaultDOMParser() throws ParserConfigurationException {
-
-		DocumentBuilder parser = null;
-		if (fDOMParserQueue.isEmpty()) {
-			parser = fDOMFactory.newDocumentBuilder();
-		} else {
-			SoftReference<?> reference = fDOMParserQueue.remove(0);
-			if (reference.get() != null) {
-				parser = (DocumentBuilder) reference.get();
-			} else {
-				parser = fDOMFactory.newDocumentBuilder();
-			}
-		}
-		return parser;
-	}
-
 	public static PDEXMLHelper Instance() throws FactoryConfigurationError {
 		if (fPinstance == null) {
 			fPinstance = new PDEXMLHelper();
@@ -88,20 +41,6 @@
 		return fPinstance;
 	}
 
-	public synchronized void recycleSAXParser(SAXParser parser) {
-		if (fSAXParserQueue.size() < fSAXPoolLimit) {
-			SoftReference<SAXParser> reference = new SoftReference<>(parser);
-			fSAXParserQueue.add(reference);
-		}
-	}
-
-	public synchronized void recycleDOMParser(DocumentBuilder parser) {
-		if (fDOMParserQueue.size() < fDOMPoolLimit) {
-			SoftReference<DocumentBuilder> reference = new SoftReference<>(parser);
-			fDOMParserQueue.add(reference);
-		}
-	}
-
 	public static String getWritableString(String source) {
 		if (source == null) {
 			return ""; //$NON-NLS-1$
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/PDEXmlProcessorFactory.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/PDEXmlProcessorFactory.java	2024-03-20 08:58:08.422601994 +0100
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.pde.internal.core.util;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+public class PDEXmlProcessorFactory {
+	private PDEXmlProcessorFactory() {
+		// static Utility only
+	}
+
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_IGNORING_DOCTYPE = createDocumentBuilderFactoryIgnoringDOCTYPE();
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE = createSAXFactoryWithErrorOnDOCTYPE(false);
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE(true);
+	private static final SAXParserFactory SAX_FACTORY_IGNORING_DOCTYPE = createSAXFactoryIgnoringDOCTYPE();
+
+	/**
+	 * Creates TransformerFactory which throws TransformerException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.transform.TransformerFactory
+	 */
+	public static TransformerFactory createTransformerFactoryWithErrorOnDOCTYPE() {
+		TransformerFactory factory = TransformerFactory.newInstance();
+		// prohibit the use of all protocols by external entities:
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); //$NON-NLS-1$
+		return factory;
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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. It's
+	 * magnitudes faster to call
+	 * {@link #createDocumentBuilderIgnoringDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	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
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilder which ignores external entities. The builder is
+	 * not thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderIgnoringDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_IGNORING_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when
+	 * detecting external entities.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		f.setNamespaceAware(awareness);
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryIgnoringDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// ignore DOCTYPE:
+			f.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
+			f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
+			f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return createSAXParserWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @param namespaceAware
+	 *            parameter for SAXParserFactory
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+		if (namespaceAware) {
+			return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+		}
+		return SAX_FACTORY_ERROR_ON_DOCTYPE.newSAXParser();
+	}
+
+	/**
+	 * Creates SAXParser which does not throw Exception when detecting external
+	 * entities but ignores them.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static SAXParser createSAXParserIgnoringDOCTYPE()
+			throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException {
+		SAXParser parser = SAX_FACTORY_IGNORING_DOCTYPE.newSAXParser();
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+}
\ No newline at end of file
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/SAXParserWrapper.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/util/SAXParserWrapper.java	2024-03-20 12:49:41.184414763 +0100
@@ -30,45 +31,25 @@
  */
 public class SAXParserWrapper {
 
-	protected SAXParser fParser;
-	protected boolean isdisposed;
-
-	/**
-	 *
-	 */
-	public SAXParserWrapper() throws ParserConfigurationException, SAXException, FactoryConfigurationError {
-		fParser = PDEXMLHelper.Instance().getDefaultSAXParser();
-		isdisposed = false;
+	public SAXParserWrapper() {
 	}
 
-	// Explicit disposal
-	public void dispose() {
-		if (isdisposed == false) {
-			PDEXMLHelper.Instance().recycleSAXParser(fParser);
-			isdisposed = true;
-		}
-	}
-
-	public void parse(File f, DefaultHandler dh) throws SAXException, IOException {
+	public void parse(File f, DefaultHandler dh)
+			throws SAXException, IOException, ParserConfigurationException, FactoryConfigurationError {
+		SAXParser fParser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		fParser.parse(f, dh);
 	}
 
-	public void parse(InputStream is, DefaultHandler dh) throws SAXException, IOException {
+	public void parse(InputStream is, DefaultHandler dh)
+			throws SAXException, IOException, ParserConfigurationException, FactoryConfigurationError {
+		SAXParser fParser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		fParser.parse(is, dh);
 	}
 
-	public void parse(InputSource is, DefaultHandler dh) throws SAXException, IOException {
+	public void parse(InputSource is, DefaultHandler dh)
+			throws SAXException, IOException, ParserConfigurationException, FactoryConfigurationError {
+		SAXParser fParser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
 		fParser.parse(is, dh);
 	}
 
-	// NOTE:  If other parser method calls are required, the corresponding
-	// wrapper method needs to be added here
-
-	// Implicit disposal
-	@Override
-	protected void finalize() throws Throwable {
-		super.finalize();
-		dispose();
-	}
-
 }
--- a/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/XMLDefaultHandler.java	2024-03-19 10:01:54.546426796 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/XMLDefaultHandler.java	2024-03-20 11:05:15.339242277 +0100
@@ -15,8 +15,8 @@
 
 import java.io.StringReader;
 import java.util.Stack;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.Text;
@@ -72,9 +72,8 @@
 
 	@Override
 	public void startDocument() throws SAXException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		try {
-			fDocument = factory.newDocumentBuilder().newDocument();
+			fDocument = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 		} catch (ParserConfigurationException e) {
 		}
 	}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/exports/FeatureExportWizard.java	2024-03-19 10:01:54.506426709 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/exports/FeatureExportWizard.java	2024-03-20 09:03:57.656602733 +0100
@@ -25,6 +25,7 @@
 import org.eclipse.pde.internal.core.exports.FeatureExportInfo;
 import org.eclipse.pde.internal.core.exports.FeatureExportOperation;
 import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.eclipse.pde.internal.ui.PDEPluginImages;
 import org.eclipse.pde.internal.ui.PDEUIMessages;
 import org.eclipse.pde.internal.ui.build.RuntimeInstallJob;
@@ -127,8 +128,7 @@
 	@Override
 	protected Document generateAntTask() {
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 			Element root = doc.createElement("project"); //$NON-NLS-1$
 			root.setAttribute("name", "build"); //$NON-NLS-1$ //$NON-NLS-2$
 			root.setAttribute("default", "feature_export"); //$NON-NLS-1$ //$NON-NLS-2$
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/exports/PluginExportWizard.java	2024-03-19 10:01:54.506426709 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/exports/PluginExportWizard.java	2024-03-20 09:06:09.673521693 +0100
@@ -21,6 +21,7 @@
 import org.eclipse.pde.core.plugin.IPluginModelBase;
 import org.eclipse.pde.internal.core.exports.FeatureExportInfo;
 import org.eclipse.pde.internal.core.exports.PluginExportOperation;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.eclipse.pde.internal.ui.PDEPluginImages;
 import org.eclipse.pde.internal.ui.PDEUIMessages;
 import org.eclipse.pde.internal.ui.build.RuntimeInstallJob;
@@ -97,8 +98,7 @@
 	@Override
 	protected Document generateAntTask() {
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			Document doc = factory.newDocumentBuilder().newDocument();
+			Document doc = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
 			Element root = doc.createElement("project"); //$NON-NLS-1$
 			root.setAttribute("name", "build"); //$NON-NLS-1$ //$NON-NLS-2$
 			root.setAttribute("default", "plugin_export"); //$NON-NLS-1$ //$NON-NLS-2$
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.templates/templates_3.1/extensibleEditor/java/ValidatorDocumentSetupParticipant.java	2024-03-19 10:01:54.563093498 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.templates/templates_3.1/extensibleEditor/java/ValidatorDocumentSetupParticipant.java	2024-03-20 08:58:08.422601994 +0100
@@ -4,6 +4,7 @@
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
 import org.eclipse.core.filebuffers.IDocumentSetupParticipantExtension;
@@ -40,7 +41,14 @@
 				this.marker = null;
 			}
 			try (StringReader reader = new StringReader(event.getDocument().get());) {
-				DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+				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);
+				}
+				DocumentBuilder documentBuilder = factory.newDocumentBuilder();
 				documentBuilder.parse(new InputSource(reader));
 			} catch (Exception ex) {
 				try {
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/feature/FeatureDataTestCase.java	2024-03-19 10:01:54.469759964 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/feature/FeatureDataTestCase.java	2024-03-20 09:09:09.847199348 +0100
@@ -23,6 +23,7 @@
 import org.eclipse.pde.internal.core.feature.FeatureData;
 import org.eclipse.pde.internal.core.feature.WorkspaceFeatureModel;
 import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.junit.Test;
 import org.w3c.dom.*;
 import org.xml.sax.InputSource;
@@ -85,8 +86,7 @@
 	}
 
 	public static FeatureData fromXml(String xml) throws Exception {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-		DocumentBuilder builder = factory.newDocumentBuilder();
+		DocumentBuilder builder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		InputSource is = new InputSource(new StringReader(xml));
 		Document doc = builder.parse(is);
 
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/PDEXmlProcessorFactoryTest.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/PDEXmlProcessorFactoryTest.java	2024-03-20 08:58:08.422601994 +0100
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.pde.core.tests.internal;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.function.IntFunction;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class PDEXmlProcessorFactoryTest {
+
+	@Rule
+	public TemporaryFolder tempFolder = new TemporaryFolder();
+
+	@Test
+	public void testParseXmlWithExternalEntity() throws Exception {
+		SAXParser parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
+		try {
+			testParseXmlWithExternalEntity(parser, this::createMalciousXml);
+			assertTrue("SAXParseException expected", false);
+		} catch (SAXParseException e) {
+			String message = e.getMessage();
+			assertTrue(message, message.contains("DOCTYPE"));
+			assertTrue(message, message.contains("http://apache.org/xml/features/disallow-doctype-decl"));
+		}
+	}
+
+	@Test
+	public void testParseXmlWithoutExternalEntity() throws Exception {
+		SAXParser parser = PDEXmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
+		testParseXmlWithExternalEntity(parser, this::createNormalXml);
+	}
+
+	@Test
+	public void testParseXmlWithIgnoredExternalEntity() throws Exception {
+		SAXParser parser = PDEXmlProcessorFactory.createSAXParserIgnoringDOCTYPE();
+		testParseXmlWithExternalEntity(parser, this::createMalciousXml);
+	}
+
+	@Test
+	public void testParseXmlWithoutIgnoredExternalEntity() throws Exception {
+		SAXParser parser = PDEXmlProcessorFactory.createSAXParserIgnoringDOCTYPE();
+		testParseXmlWithExternalEntity(parser, this::createNormalXml);
+	}
+
+	public void testParseXmlWithExternalEntity(SAXParser parser, IntFunction<InputStream> xmlSupplier)
+			throws Exception {
+		try (Server httpServerThread = new Server()) {
+			List<String> elements = new ArrayList<>();
+			DefaultHandler handler = new DefaultHandler() {
+				@Override
+				public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes)
+						throws org.xml.sax.SAXException {
+					elements.add(qName);
+				}
+
+				@Override
+				public void characters(char ch[], int start, int length) throws SAXException {
+					String content = new String(ch, start, length);
+					assertFalse("Secret was injected into xml: " + content, content.contains("secret")); // var4
+				}
+
+				@Override
+				public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
+					// implementation that would do any remote call:
+					try {
+						return new InputSource(URI.create(systemId).toURL().openStream());
+					} catch (IOException exception) {
+						throw new SAXException(exception);
+					}
+					// Also the default impl injects files:
+					// return null;
+
+					// Does also prevent access to external files:
+					// return new InputSource(new StringReader(""));
+				}
+
+			};
+			try (InputStream xmlStream = xmlSupplier.apply(httpServerThread.getLocalPort())) {
+				parser.parse(xmlStream, handler);
+			}
+			assertEquals(List.of("Body"), elements);
+		}
+	}
+
+	@Test
+	public void testDocumentBuilderXmlWithExternalEntity() throws Exception {
+		DocumentBuilder documentBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
+		try {
+			testParseXmlWithExternalEntity(documentBuilder, this::createMalciousXml);
+			assertTrue("SAXParseException expected", false);
+		} catch (SAXParseException e) {
+			String message = e.getMessage();
+			assertTrue(message, message.contains("DOCTYPE"));
+		}
+	}
+
+	@Test
+	public void testDocumentBuilderFactoryWithoutExternalEntity() throws Exception {
+		DocumentBuilderFactory documentBuilderFactory = PDEXmlProcessorFactory
+				.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+		testParseXmlWithExternalEntity(documentBuilderFactory.newDocumentBuilder(), this::createNormalXml);
+	}
+
+	@Test
+	public void testDocumentBuilderWithoutExternalEntity() throws Exception {
+		DocumentBuilder documentBuilder = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
+		testParseXmlWithExternalEntity(documentBuilder, this::createNormalXml);
+	}
+
+	@Test
+	public void testDocumentBuilderFactoryIgnoringDoctypeNormal() throws Exception {
+		DocumentBuilderFactory documentBuilderFactory = PDEXmlProcessorFactory
+				.createDocumentBuilderFactoryIgnoringDOCTYPE();
+		testParseXmlWithExternalEntity(documentBuilderFactory.newDocumentBuilder(), this::createNormalXml);
+	}
+
+	@Test
+	public void testDocumentBuilderFactoryIgnoringDoctypeMalcious() throws Exception {
+		DocumentBuilderFactory documentBuilderFactory = PDEXmlProcessorFactory
+				.createDocumentBuilderFactoryIgnoringDOCTYPE();
+		testParseXmlWithExternalEntity(documentBuilderFactory.newDocumentBuilder(), this::createMalciousXml);
+	}
+
+	@Test
+	public void testDocumentBuilderIgnoringDoctypeNormal() throws Exception {
+		testParseXmlWithExternalEntity(PDEXmlProcessorFactory.createDocumentBuilderIgnoringDOCTYPE(),
+				this::createNormalXml);
+	}
+
+	@Test
+	public void testDocumentBuilderIgnoringDoctypeMalcious() throws Exception {
+		testParseXmlWithExternalEntity(PDEXmlProcessorFactory.createDocumentBuilderIgnoringDOCTYPE(),
+				this::createMalciousXml);
+	}
+
+	public void testParseXmlWithExternalEntity(DocumentBuilder builder, IntFunction<InputStream> xmlSupplier)
+			throws Exception {
+		try (Server httpServerThread = new Server()) {
+			Document document;
+
+			try (InputStream xmlStream = xmlSupplier.apply(httpServerThread.getLocalPort())) {
+				document = builder.parse(xmlStream);
+			}
+			Element root = document.getDocumentElement();
+
+			assertEquals("Body", root.getTagName());
+			if (root.getChildNodes().getLength() > 0) {
+				String value = root.getChildNodes().item(0).getNodeValue();
+				assertFalse("Parser injected secret: " + value, value.contains("secret"));
+			}
+		}
+	}
+
+	@Test
+	public void testTransformXmlWithExternalEntity() throws Exception {
+		TransformerFactory transformerFactory = PDEXmlProcessorFactory
+				.createTransformerFactoryWithErrorOnDOCTYPE();
+		try {
+			testParseXmlWithExternalEntity(transformerFactory, this::createMalciousXml);
+			assertTrue("TransformerException expected", false);
+		} catch (TransformerException e) {
+			String message = e.getMessage();
+			assertTrue(message, message.contains("DTD"));
+		}
+	}
+
+	@Test
+	public void testTransformXmlWithoutExternalEntity() throws Exception {
+		TransformerFactory transformerFactory = PDEXmlProcessorFactory
+				.createTransformerFactoryWithErrorOnDOCTYPE();
+		testParseXmlWithExternalEntity(transformerFactory, this::createNormalXml);
+	}
+
+	public void testParseXmlWithExternalEntity(TransformerFactory transformerFactory,
+			IntFunction<InputStream> xmlSupplier) throws Exception {
+		try (Server httpServerThread = new Server()) {
+			String formatted;
+
+			try (InputStream xmlStream = xmlSupplier.apply(httpServerThread.getLocalPort())) {
+				Transformer xformer = transformerFactory.newTransformer();
+				Source source = new StreamSource(xmlStream);
+				try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+					Result result = new StreamResult(outputStream);
+					xformer.transform(source, result);
+					formatted = outputStream.toString(StandardCharsets.UTF_8);
+				}
+			}
+			assertTrue(formatted, formatted.contains("<Body>"));
+			assertFalse("Formatter injected secret: " + formatted, formatted.contains("secret"));
+		}
+	}
+
+	private InputStream createMalciousXml(int localPort) {
+		try {
+			Path tempSecret = tempFolder.newFile("test.txt").toPath();
+			Files.writeString(tempSecret, "secret");
+			Path tempDtd = tempFolder.newFile("test.dtd").toPath();
+			URL secretURL = tempSecret.toUri().toURL();
+			String dtdContent = "<!ENTITY % var1 SYSTEM \"" + secretURL + "\">\n" //
+					+ "<!ENTITY var4 SYSTEM \"" + secretURL + "\">\n" //
+					+ "<!ENTITY % var2 \"<!ENTITY var3 SYSTEM 'http://localhost:" + localPort + "/?%var1;'>\">\n" //
+					+ "%var2;\n";
+			Files.writeString(tempDtd, dtdContent);
+			URL dtdURL = tempDtd.toUri().toURL();
+			String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" //
+					+ "<!DOCTYPE var1 SYSTEM \"" + dtdURL + "\">\n" //
+					+ "<Body>&var3;&var4;</Body>";
+			return new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private InputStream createNormalXml(int localPort) {
+		String xml = """
+				<?xml version="1.0" encoding="UTF-8"?>
+				<Body>hello</Body>""";
+		return new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
+	}
+
+	public static final class Server implements AutoCloseable {
+		private final ServerSocket serverSocket;
+		private final Thread httpServerThread;
+		private final Collection<Throwable> exceptionsInOtherThreads = new ConcurrentLinkedQueue<>();
+
+		private Server() throws IOException {
+			serverSocket = new ServerSocket(0);
+			httpServerThread = new Thread("httpServerThread") {
+				@Override
+				public void run() {
+					try (Socket socket = serverSocket.accept()) {
+						try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
+							String firstLine = in.readLine();
+							System.out.println(socket.getInetAddress() + ": " + firstLine);
+							try (OutputStream outputStream = socket.getOutputStream()) {
+								outputStream.write("HTTP/1.1 200 OK\r\n".getBytes(StandardCharsets.UTF_8));
+							}
+							assertThat(firstLine, startsWith("GET"));
+							assertThat(firstLine, not(containsString("secret")));
+							fail("Server was contacted");
+						}
+					} catch (SocketException closed) {
+						// expected
+					} catch (Throwable e) {
+						exceptionsInOtherThreads.add(e);
+					}
+				}
+			};
+
+			httpServerThread.start();
+		}
+
+		@Override
+		public void close() throws Exception {
+			serverSocket.close(); // -> SocketException in httpServerThread
+			httpServerThread.join(5000);
+			assertFalse(httpServerThread.isAlive());
+			for (Throwable e : exceptionsInOtherThreads) {
+				throw new AssertionError(e.getMessage(), e);
+			}
+		}
+
+		public int getLocalPort() {
+			return serverSocket.getLocalPort();
+		}
+
+		/** Example Server that will log and quit when contacted **/
+		public static void main(String[] args) throws Exception {
+			@SuppressWarnings("resource")
+			Server server = new Server();
+			System.out.println("Server startet on port: " + server.getLocalPort());
+			server.httpServerThread.join();
+			server.close();
+		}
+	}
+
+	static volatile Object sink;
+
+	/**
+	 * Simple performance demonstration: It's slow to create Factory but 100
+	 * times faster to create a Parser.
+	 **/
+	public static void main(String[] args) throws Exception {
+		for (int i = 1; i < 1000; i++) {
+			long n0 = System.nanoTime();
+			sink = PDEXmlProcessorFactory.createSAXParserIgnoringDOCTYPE();
+			long n1 = System.nanoTime();
+			System.out.println("createSAXParserIgnoringDOCTYPE run " + i + ": " + (n1 - n0) + "ns");
+			// ~ run 999: 60000ns =0,06ms
+
+			n0 = System.nanoTime();
+			sink = PDEXmlProcessorFactory.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+			n1 = System.nanoTime();
+			System.out.println("createDocumentBuilderFactoryWithErrorOnDOCTYPE run " + i + ": " + (n1 - n0) + "ns");
+			// ~ run 999: 5000000ns =5ms
+
+			n0 = System.nanoTime();
+			sink = PDEXmlProcessorFactory.createDocumentBuilderIgnoringDOCTYPE();
+			n1 = System.nanoTime();
+			System.out.println("createDocumentBuilderIgnoringDOCTYPE run " + i + ": " + (n1 - n0) + "ns");
+			// ~ run 999: 40000ns =0,04ms
+
+			n0 = System.nanoTime();
+			sink = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
+			n1 = System.nanoTime();
+			System.out.println("createDocumentBuilderWithErrorOnDOCTYPE run " + i + ": " + (n1 - n0) + "ns");
+			// ~ run 999: 30000ns =0,03ms
+
+			n0 = System.nanoTime();
+			sink = PDEXmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE();
+			n1 = System.nanoTime();
+			System.out.println("createTransformerFactoryWithErrorOnDOCTYPE run " + i + ": " + (n1 - n0) + "ns");
+			// ~ run 999: 5000000ns =5ms
+		}
+	}
+}
\ No newline at end of file
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/target/IUBundleContainerTests.java	2024-03-19 10:01:54.469759964 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/target/IUBundleContainerTests.java	2024-03-20 09:11:38.940817604 +0100
@@ -36,6 +36,7 @@
 import org.eclipse.pde.core.plugin.IPluginModelBase;
 import org.eclipse.pde.core.target.*;
 import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.util.PDEXmlProcessorFactory;
 import org.eclipse.pde.internal.core.target.*;
 import org.eclipse.pde.ui.tests.PDETestsPlugin;
 import org.junit.Test;
@@ -540,7 +541,7 @@
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		TargetDefinitionPersistenceHelper.persistXML(td, out);
 		String xml = new String(out.toByteArray());
-		DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		DocumentBuilder parser = PDEXmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 		parser.setErrorHandler(new DefaultHandler());
 		Document doc = parser.parse(new InputSource(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))));
 
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/util/DOMParserWrapper.java	2024-03-19 10:01:54.469759964 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/util/DOMParserWrapper.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 IBM Corporation 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:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.pde.ui.tests.util;
-
-import java.io.File;
-import java.io.IOException;
-import javax.xml.parsers.*;
-import org.eclipse.pde.internal.core.util.PDEXMLHelper;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-public class DOMParserWrapper implements AutoCloseable {
-
-	protected DocumentBuilder fParser;
-	protected boolean isdisposed;
-
-	public DOMParserWrapper() throws ParserConfigurationException, FactoryConfigurationError {
-		fParser = PDEXMLHelper.Instance().getDefaultDOMParser();
-		isdisposed = false;
-	}
-
-	// Explicit disposal
-	public void dispose() {
-		if (isdisposed == false) {
-			PDEXMLHelper.Instance().recycleDOMParser(fParser);
-			isdisposed = true;
-		}
-	}
-
-	public Document parse(File f) throws SAXException, IOException {
-		return fParser.parse(f);
-	}
-
-	public Document newDocument() {
-		return fParser.newDocument();
-	}
-
-	// NOTE:  If other parser method calls are required, the corresponding
-	// wrapper method needs to be added here
-
-	@Override
-	public void close() {
-		dispose();
-	}
-
-}
--- a/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/util/xml/ParserWrapperTestCase.java	2024-03-19 10:01:54.469759964 +0100
+++ b/eclipse.pde.ui/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/util/xml/ParserWrapperTestCase.java	2024-03-20 09:13:14.884334289 +0100
@@ -25,7 +25,6 @@
 import org.eclipse.pde.internal.core.XMLDefaultHandler;
 import org.eclipse.pde.internal.core.util.SAXParserWrapper;
 import org.eclipse.pde.ui.tests.PDETestsPlugin;
-import org.eclipse.pde.ui.tests.util.DOMParserWrapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.osgi.framework.Bundle;
@@ -73,23 +72,6 @@
 
 	}
 
-	@Test
-	public void testDOMParserWrapperConcurrency() throws Exception {
-
-		ParserThread[] threads = new ParserThread[FTHREADCOUNT];
-
-		for (int x = 0; x < FTHREADCOUNT; x++) {
-			threads[x] = new ParserThread(FDOM, fXMLFile);
-			threads[x].start();
-		}
-
-		for (int x = 0; x < FTHREADCOUNT; x++) {
-			threads[x].join();
-			assertFalse(threads[x].getError());
-		}
-
-	}
-
 	public class ParserThread extends Thread {
 
 		protected final int FITERATIONS = 100;
@@ -108,10 +90,7 @@
 
 			if (fParserType == ParserWrapperTestCase.FSAX) {
 				runSAX();
-			} else {
-				runDOM();
 			}
-
 		}
 
 		public void runSAX() {
@@ -136,23 +115,6 @@
 
 		}
 
-		public void runDOM() {
-
-			for (int x = 0; x < FITERATIONS; x++) {
-
-				try (DOMParserWrapper parser = new DOMParserWrapper()) {
-					parser.parse(fParserXMLFile);
-				} catch (ParserConfigurationException | SAXException | FactoryConfigurationError | IOException e) {
-					e.printStackTrace();
-					fError = true;
-				}
-				// If an error was encountered abort the thread
-				// Any type of exception experienced is bad
-				if (fError)
-					return;
-
-			}
-		}
 
 		public boolean getError() {
 			return fError;
--- a/eclipse.platform/update/org.eclipse.update.configurator/META-INF/MANIFEST.MF	2024-03-19 10:01:56.373097399 +0100
+++ b/eclipse.platform/update/org.eclipse.update.configurator/META-INF/MANIFEST.MF	2024-03-20 12:27:53.028756091 +0100
@@ -11,7 +11,8 @@
  org.eclipse.update.internal.configurator.branding;x-friends:="org.eclipse.update.core"
 Eclipse-LazyStart: true
 Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.osgi;bundle-version="[3.2.0,4.0.0)"
+ org.eclipse.osgi;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.11.0,4.0.0)"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.xml.parsers,
  org.w3c.dom,
--- a/eclipse.platform/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/ConfigurationParser.java	2024-03-19 10:01:56.373097399 +0100
+++ b/eclipse.platform/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/ConfigurationParser.java	2024-03-20 12:22:25.604833946 +0100
@@ -25,7 +25,6 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.URIUtil;
@@ -43,8 +42,6 @@
 	
 	private static final String URL_PROPERTY = "org.eclipse.update.resolution_url"; //$NON-NLS-1$
 	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
-	private final static SAXParserFactory parserFactory =
-		SAXParserFactory.newInstance();
 	private SAXParser parser;
 	
 	private URL currentSiteURL;
@@ -59,8 +56,7 @@
 	public ConfigurationParser() throws InvocationTargetException {
 
 		try {
-			parserFactory.setNamespaceAware(true);
-			this.parser = parserFactory.newSAXParser();
+			this.parser = org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE(true);
 		} catch (ParserConfigurationException e) {
 			Utils.log(Utils.newStatus("ConfigurationParser", e)); //$NON-NLS-1$
 			throw new InvocationTargetException(e);
--- a/eclipse.platform/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/FeatureParser.java	2024-03-19 10:01:56.373097399 +0100
+++ b/eclipse.platform/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/FeatureParser.java	2024-03-20 12:22:44.744868356 +0100
@@ -35,17 +35,13 @@
 	private FeatureEntry feature;
 	private URL url;
 
-	private final static SAXParserFactory parserFactory =
-		SAXParserFactory.newInstance();
-
 	/**
 	 * Constructs a feature parser.
 	 */
 	public FeatureParser() {
 		super();
 		try {
-			parserFactory.setNamespaceAware(true);
-			this.parser = parserFactory.newSAXParser();
+			this.parser = org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE(true);
 		} catch (ParserConfigurationException e) {
 			System.out.println(e);
 		} catch (SAXException e) {
--- a/eclipse.platform.runtime/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/XmlProcessorFactory.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.platform.runtime/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/XmlProcessorFactory.java	2024-03-20 12:07:18.269833676 +0100
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.core.internal.runtime;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+public class XmlProcessorFactory {
+	private XmlProcessorFactory() {
+		// 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();
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE = createSAXFactoryWithErrorOnDOCTYPE(false);
+	private static final SAXParserFactory SAX_FACTORY_ERROR_ON_DOCTYPE_NS = createSAXFactoryWithErrorOnDOCTYPE(true);
+	private static final SAXParserFactory SAX_FACTORY_IGNORING_DOCTYPE = createSAXFactoryIgnoringDOCTYPE();
+	private static final SAXParserFactory SAX_FACTORY_PURE = createSAXFactory(false);
+	private static final SAXParserFactory SAX_FACTORY_PURE_NS = createSAXFactory(true);
+
+	/**
+	 * Creates TransformerFactory which throws TransformerException when detecting
+	 * external entities.
+	 *
+	 * @return javax.xml.transform.TransformerFactory
+	 */
+	public static TransformerFactory createTransformerFactoryWithErrorOnDOCTYPE() {
+		TransformerFactory factory = TransformerFactory.newInstance();
+		// prohibit the use of all protocols by external entities:
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); //$NON-NLS-1$
+		return factory;
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when detecting
+	 * external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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. It's
+	 * magnitudes faster to call {@link #createDocumentBuilderIgnoringDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	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
+	 * @throws ParserConfigurationException
+	 */
+	public static synchronized DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE()
+			throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilder which ignores external entities. The builder is not
+	 * thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static synchronized DocumentBuilder createDocumentBuilderIgnoringDOCTYPE()
+			throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_IGNORING_DOCTYPE.newDocumentBuilder();
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when detecting
+	 * external entities.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE() {
+		return createSAXFactoryWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when detecting
+	 * external entities.
+	 *
+	 * @param awareness true if the parser produced by this code will provide
+	 *                  support for XML namespaces; false otherwise.
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public static synchronized SAXParserFactory createSAXFactoryWithErrorOnDOCTYPE(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		if (awareness) {
+			f.setNamespaceAware(true);
+		}
+		try {
+			// force org.xml.sax.SAXParseException for any DOCTYPE:
+			f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactoryIgnoringDOCTYPE() {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		try {
+			// ignore DOCTYPE:
+			f.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
+			f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
+			f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return f;
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+
+	public static SAXParser createSAXParserWithErrorOnDOCTYPE() throws ParserConfigurationException, SAXException {
+		return createSAXParserWithErrorOnDOCTYPE(false);
+	}
+
+	/**
+	 * Creates SAXParser which throws SAXParseException when detecting external
+	 * entities.
+	 *
+	 * @param namespaceAware parameter for SAXParserFactory
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static synchronized SAXParser createSAXParserWithErrorOnDOCTYPE(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+		if (namespaceAware) {
+			return SAX_FACTORY_ERROR_ON_DOCTYPE_NS.newSAXParser();
+		}
+		return SAX_FACTORY_ERROR_ON_DOCTYPE.newSAXParser();
+	}
+
+	/**
+	 * Creates SAXParser which does not throw Exception when detecting external
+	 * entities but ignores them.
+	 *
+	 * @return javax.xml.parsers.SAXParser
+	 */
+	public static synchronized SAXParser createSAXParserIgnoringDOCTYPE()
+			throws ParserConfigurationException, SAXException {
+		SAXParser parser = SAX_FACTORY_IGNORING_DOCTYPE.newSAXParser();
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+
+	private static synchronized SAXParserFactory createSAXFactory(boolean awareness) {
+		SAXParserFactory f = SAXParserFactory.newInstance();
+		if (awareness) {
+			f.setNamespaceAware(true);
+		}
+		return f;
+	}
+
+	public static synchronized SAXParser createSAXParserNoExternal(boolean namespaceAware)
+			throws ParserConfigurationException, SAXException {
+
+		SAXParser parser = namespaceAware ? SAX_FACTORY_PURE_NS.newSAXParser() : SAX_FACTORY_PURE.newSAXParser();
+		// prohibit the use of all protocols by external entities:
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); //$NON-NLS-1$
+		parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); //$NON-NLS-1$
+		return parser;
+	}
+
+	public static synchronized SAXParser createSAXParserNoExternal() throws ParserConfigurationException, SAXException {
+		return createSAXParserNoExternal(false);
+	}
+
+	/**
+	 * Parse the content of the given input source as an XML document and return a
+	 * new DOM {@link Document} object.
+	 *
+	 * @see javax.xml.parsers.DocumentBuilder#parse(InputSource)
+	 */
+	public static Document parseWithErrorOnDOCTYPE(InputSource is)
+			throws SAXException, IOException, ParserConfigurationException {
+		return createDocumentBuilderWithErrorOnDOCTYPE().parse(is);
+	}
+
+	/**
+	 * Parse the content of the given input source as an XML document and return a
+	 * new DOM {@link Document} object.
+	 *
+	 * @see javax.xml.parsers.DocumentBuilder#parse(InputStream)
+	 */
+	public static Document parseWithErrorOnDOCTYPE(InputStream is)
+			throws SAXException, IOException, ParserConfigurationException {
+		return createDocumentBuilderWithErrorOnDOCTYPE().parse(is);
+	}
+
+	/**
+	 * Parse the content of the given input source as an XML document and return a
+	 * new DOM {@link Document} object.
+	 *
+	 * @see javax.xml.parsers.DocumentBuilder#parse(File)
+	 */
+	public static Document parseWithErrorOnDOCTYPE(File file)
+			throws SAXException, IOException, ParserConfigurationException {
+		return createDocumentBuilderWithErrorOnDOCTYPE().parse(file);
+	}
+
+	/**
+	 * Obtain a new instance of a DOM {@link Document} object to build a DOM tree
+	 * with.
+	 *
+	 * @return A new instance of a DOM Document object.
+	 * @see javax.xml.parsers.DocumentBuilder#newDocument()
+	 */
+	public static Document newDocumentWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return createDocumentBuilderWithErrorOnDOCTYPE().newDocument();
+	}
+
+}
\ No newline at end of file
--- "a/eclipse.platform.swt/bundles/org.eclipse.swt.tools/Mac Generation/org/eclipse/swt/tools/internal/MacGenerator.java"	2024-03-19 10:01:56.149763584 +0100
+++ "b/eclipse.platform.swt/bundles/org.eclipse.swt.tools/Mac Generation/org/eclipse/swt/tools/internal/MacGenerator.java"	2024-03-19 14:04:31.634036279 +0100
@@ -17,8 +17,6 @@
 import java.util.*;
 import java.util.Map.*;
 
-import javax.xml.parsers.*;
-
 import org.w3c.dom.*;
 import org.xml.sax.*;
 
@@ -950,7 +948,11 @@
 		InputStream is = null;
 		if (xmlPath.indexOf(File.separatorChar) == -1) is = getClass().getResourceAsStream(xmlPath);
 		if (is == null) is = new BufferedInputStream(new FileInputStream(xmlPath));
-		if (is != null) return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(is));
+		if (is != null) {
+			@SuppressWarnings("restriction")
+			Document d = org.eclipse.core.internal.runtime.XmlProcessorFactory.parseWithErrorOnDOCTYPE(new InputSource(is));
+			return d;
+		}
 	} catch (Exception e) {
 //		e.printStackTrace();
 	}
--- a/eclipse.platform.text/org.eclipse.text/.settings/org.eclipse.jdt.core.prefs	2024-03-19 10:01:56.493097657 +0100
+++ b/eclipse.platform.text/org.eclipse.text/.settings/org.eclipse.jdt.core.prefs	2024-03-19 11:39:19.100332806 +0100
@@ -1,4 +1,5 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled
 org.eclipse.jdt.core.builder.cleanOutputFolder=clean
 org.eclipse.jdt.core.builder.duplicateResourceTask=warning
 org.eclipse.jdt.core.builder.invalidClasspath=abort
@@ -21,8 +22,11 @@
 org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
 org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
 org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
 org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
@@ -34,6 +38,8 @@
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.doc.comment.support=enabled
 org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.autoboxing=info
@@ -42,7 +48,7 @@
 org.eclipse.jdt.core.compiler.problem.deprecation=warning
 org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
 org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=error
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
 org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
@@ -84,12 +90,14 @@
 org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
 org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
 org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
 org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
 org.eclipse.jdt.core.compiler.problem.nullReference=error
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=info
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=info
@@ -104,17 +112,23 @@
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
 org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
 org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
 org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
 org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
 org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
 org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
 org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
 org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=info
 org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
 org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
 org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
 org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
--- a/eclipse.platform.text/org.eclipse.text/src/org/eclipse/text/templates/TemplateReaderWriter.java	2024-03-19 10:01:56.489764316 +0100
+++ b/eclipse.platform.text/org.eclipse.text/src/org/eclipse/text/templates/TemplateReaderWriter.java	2024-03-19 11:39:19.100332806 +0100
@@ -27,12 +27,10 @@
 import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -157,8 +155,8 @@
 			Collection<TemplatePersistenceData> templates= new ArrayList<>();
 			Set<String> ids= new HashSet<>();
 
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
-			DocumentBuilder parser= factory.newDocumentBuilder();
+			@SuppressWarnings("restriction")
+			DocumentBuilder parser= org.eclipse.core.internal.runtime.XmlProcessorFactory.createDocumentBuilderWithErrorOnDOCTYPE();
 			parser.setErrorHandler(new DefaultHandler());
 			Document document= parser.parse(source);
 
@@ -263,10 +261,8 @@
 	 */
 	private void save(TemplatePersistenceData[] templates, StreamResult result) throws IOException {
 		try {
-			DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
-			DocumentBuilder builder= factory.newDocumentBuilder();
-			Document document= builder.newDocument();
-
+			@SuppressWarnings("restriction")
+			Document document= org.eclipse.core.internal.runtime.XmlProcessorFactory.newDocumentWithErrorOnDOCTYPE();
 			Node root= document.createElement(TEMPLATE_ROOT);
 			document.appendChild(root);
 
@@ -322,9 +318,8 @@
 					node.appendChild(pattern);
 				}
 			}
-
-
-			Transformer transformer=TransformerFactory.newInstance().newTransformer();
+			@SuppressWarnings("restriction")
+			Transformer transformer= org.eclipse.core.internal.runtime.XmlProcessorFactory.createTransformerFactoryWithErrorOnDOCTYPE().newTransformer();
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
 			DOMSource source = new DOMSource(document);
--- a/eclipse.platform.ui/bundles/org.eclipse.jface/src/org/eclipse/jface/dialogs/DialogSettings.java	2024-03-19 10:01:54.889760869 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.jface/src/org/eclipse/jface/dialogs/DialogSettings.java	2024-03-19 11:39:19.100332806 +0100
@@ -36,9 +36,9 @@
 import java.util.Map.Entry;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.eclipse.jface.internal.XmlProcessorFactoryJFace;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -260,8 +260,7 @@
 	public void load(Reader r) {
 		Document document = null;
 		try {
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance()
-					.newDocumentBuilder();
+			DocumentBuilder parser = XmlProcessorFactoryJFace.createDocumentBuilderWithErrorOnDOCTYPE();
 			//		parser.setProcessNamespace(true);
 			document = parser.parse(new InputSource(r));
 
--- a/eclipse.platform.ui/bundles/org.eclipse.jface/src/org/eclipse/jface/internal/XmlProcessorFactoryJFace.java	1970-01-01 01:00:00.000000000 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.jface/src/org/eclipse/jface/internal/XmlProcessorFactoryJFace.java	2024-03-19 11:39:19.100332806 +0100
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ *  Copyright (c) 2023 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
+ *******************************************************************************/
+package org.eclipse.jface.internal;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+/**
+ * XML processing which prohibits external entities.
+ *
+ * @see <a href="https://rules.sonarsource.com/java/RSPEC-2755/">RSPEC-2755</a>
+ */
+/* A copy of org.eclipse.core.internal.runtime.XmlProcessorFactory for jface. */
+public class XmlProcessorFactoryJFace {
+	private XmlProcessorFactoryJFace() {
+		// static Utility only
+	}
+
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE = createDocumentBuilderFactoryWithErrorOnDOCTYPE();
+
+	/**
+	 * Creates DocumentBuilderFactory which throws SAXParseException when detecting
+	 * external entities. It's magnitudes faster to call
+	 * {@link #createDocumentBuilderWithErrorOnDOCTYPE()}.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilderFactory
+	 */
+	public 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 DocumentBuilder which throws SAXParseException when detecting
+	 * external entities. The builder is not thread safe.
+	 *
+	 * @return javax.xml.parsers.DocumentBuilder
+	 * @throws ParserConfigurationException
+	 */
+	public static DocumentBuilder createDocumentBuilderWithErrorOnDOCTYPE() throws ParserConfigurationException {
+		return DOCUMENT_BUILDER_FACTORY_ERROR_ON_DOCTYPE.newDocumentBuilder();
+	}
+
+}
\ No newline at end of file
--- a/eclipse.platform.ui/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/internal/forms/widgets/FormTextModel.java	2024-03-19 10:01:54.983094403 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/internal/forms/widgets/FormTextModel.java	2024-03-19 11:39:19.100332806 +0100
@@ -56,8 +56,9 @@
 		}
 	}
 
-	private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
-			.newInstance();
+	@SuppressWarnings("restriction")
+	private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = org.eclipse.core.internal.runtime.XmlProcessorFactory
+			.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 
 	private boolean whitespaceNormalized = true;
 
@@ -132,13 +133,12 @@
 
 	public void parseInputStream(InputStream is, boolean expandURLs) {
 
-		documentBuilderFactory.setNamespaceAware(true);
-		documentBuilderFactory.setIgnoringComments(true);
+		DOCUMENT_BUILDER_FACTORY.setNamespaceAware(true);
+		DOCUMENT_BUILDER_FACTORY.setIgnoringComments(true);
 
 		reset();
 		try {
-			DocumentBuilder parser = documentBuilderFactory
-					.newDocumentBuilder();
+			DocumentBuilder parser = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
 			parser.setErrorHandler(new ParseErrorHandler());
 			InputSource source = new InputSource(is);
 			Document doc = parser.parse(source);
--- a/eclipse.platform.ui/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/WelcomeEditor.java	2024-03-19 10:01:54.916427593 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/WelcomeEditor.java	2024-03-19 11:39:19.100332806 +0100
@@ -19,8 +19,6 @@
 import java.net.URL;
 import java.util.ArrayList;
 
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -63,7 +61,6 @@
 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
 import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
 import org.eclipse.ui.part.EditorPart;
-import org.xml.sax.SAXException;
 
 /**
  * A "fake" editor to show a welcome page
@@ -853,7 +850,7 @@
 	 *
 	 * @see IEditorPart
 	 */
-	public void gotoMarker(IMarker marker) {
+	public void gotoMarker(@SuppressWarnings({ "unused", "javadoc" }) IMarker marker) {
 		// do nothing
 	}
 
@@ -920,7 +917,7 @@
 	public void read(InputStream is) throws IOException {
 		try {
 			parser = new WelcomeParser();
-		} catch (ParserConfigurationException | SAXException e) {
+		} catch (Exception e) {
 			throw (IOException) (new IOException().initCause(e));
 		}
 		parser.parse(is);
--- a/eclipse.platform.ui/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/WelcomeParser.java	2024-03-19 10:01:54.916427593 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/WelcomeParser.java	2024-03-19 11:39:19.100332806 +0100
@@ -21,7 +21,6 @@
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
@@ -333,14 +332,15 @@
 
 	/**
 	 * Creates a new welcome parser.
+	 *
+	 * @throws ParserConfigurationException
+	 * @throws SAXException
+	 * @throws FactoryConfigurationError
 	 */
-	public WelcomeParser() throws ParserConfigurationException, SAXException,
-			FactoryConfigurationError {
-		super();
-		SAXParserFactory factory = SAXParserFactory.newInstance();
-		factory.setFeature("http://xml.org/sax/features/namespaces", true); //$NON-NLS-1$
-		parser = factory.newSAXParser();
-
+	public WelcomeParser() throws ParserConfigurationException, SAXException, FactoryConfigurationError {
+		@SuppressWarnings("restriction")
+		SAXParser p = org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE(true);
+		parser = p;
 		parser.getXMLReader().setContentHandler(this);
 		parser.getXMLReader().setDTDHandler(this);
 		parser.getXMLReader().setEntityResolver(this);
--- "a/eclipse.platform.ui/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/XMLMemento.java"	2024-03-19 10:01:54.933094295 +0100
+++ "b/eclipse.platform.ui/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/XMLMemento.java"	2024-03-19 11:46:51.181307067 +0100
@@ -51,6 +51,8 @@
 
 	private Element element;
 
+	private static String FILE_STRING = "file"; //$NON-NLS-1$
+
 	/**
 	 * Creates a <code>Document</code> from the <code>Reader</code> and returns a
 	 * memento on the first <code>Element</code> for reading the document.
@@ -84,8 +86,9 @@
 		Exception exception = null;
 
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			DocumentBuilder parser = factory.newDocumentBuilder();
+			@SuppressWarnings("restriction")
+			DocumentBuilder parser = org.eclipse.core.internal.runtime.XmlProcessorFactory
+					.createDocumentBuilderWithErrorOnDOCTYPE();
 			InputSource source = new InputSource(reader);
 			if (baseDir != null) {
 				source.setSystemId(baseDir);
@@ -146,14 +149,13 @@
 	 *                      type
 	 */
 	public static XMLMemento createWriteRoot(String type) throws DOMException {
-		Document document;
 		try {
-			document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+			@SuppressWarnings("restriction")
+			Document document = org.eclipse.core.internal.runtime.XmlProcessorFactory.newDocumentWithErrorOnDOCTYPE();
 			Element element = document.createElement(type);
 			document.appendChild(element);
 			return new XMLMemento(document, element);
 		} catch (ParserConfigurationException e) {
-//            throw new Error(e);
 			throw new Error(e.getMessage());
 		}
 	}
--- a/eclipse.platform.ui/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/PlistFileWriter.java	2024-03-19 10:01:54.876427507 +0100
+++ b/eclipse.platform.ui/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/PlistFileWriter.java	2024-03-20 13:59:52.205700452 +0100
@@ -19,8 +19,6 @@
 import java.io.Reader;
 import java.io.Writer;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
@@ -206,7 +204,10 @@
 	private void transformDocument(Writer writer) {
 		try {
 			DOMSource source = new DOMSource(this.document);
-			TransformerFactory.newInstance().newTransformer().transform(source, new StreamResult(writer));
+			@SuppressWarnings("restriction")
+			TransformerFactory f = org.eclipse.core.internal.runtime.XmlProcessorFactory
+			.createTransformerFactoryWithErrorOnDOCTYPE();
+			f.newTransformer().transform(source, new StreamResult(writer));
 		} catch (TransformerException e) {
 			throw new IllegalStateException(e);
 		} finally {
@@ -214,11 +215,11 @@
 		}
 	}
 
+	@SuppressWarnings("restriction")
 	private Document getDom(Reader reader) {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		try {
-			DocumentBuilder builder = factory.newDocumentBuilder();
-			return builder.parse(new InputSource(reader));
+			return org.eclipse.core.internal.runtime.XmlProcessorFactory
+					.parseWithErrorOnDOCTYPE(new InputSource(reader));
 		} catch (ParserConfigurationException | IOException | SAXException e) {
 			throw new IllegalArgumentException(e);
 		} finally {
--- a/eclipse.platform.ui/tests/org.eclipse.ui.tests.pluginchecks/src/org/eclipse/ui/tests/pluginchecks/PluginWalkerTest.java	2024-03-19 10:01:55.063094576 +0100
+++ b/eclipse.platform.ui/tests/org.eclipse.ui.tests.pluginchecks/src/org/eclipse/ui/tests/pluginchecks/PluginWalkerTest.java	2024-03-19 11:39:19.103666147 +0100
@@ -32,6 +32,7 @@
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.eclipse.core.internal.runtime.XmlProcessorFactory;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtension;
 import org.eclipse.core.runtime.IExtensionPoint;
@@ -61,6 +62,7 @@
  * be accessed
  *
  */
+@SuppressWarnings("restriction")
 public class PluginWalkerTest {
 
 	private BundleContext bundleContext;
@@ -188,7 +190,7 @@
 	}
 
 	private static DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
-		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilderFactory factory = XmlProcessorFactory.createDocumentBuilderFactoryWithErrorOnDOCTYPE();
 		factory.setNamespaceAware(true);
 		return factory.newDocumentBuilder();
 	}
--- a/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/tabs/DocUtil.java	2024-03-19 10:01:56.529764403 +0100
+++ b/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/tabs/DocUtil.java	2024-03-19 11:39:19.103666147 +0100
@@ -14,8 +14,8 @@
 
 package org.eclipse.e4.tools.emf.ui.internal.common.component.tabs;
 
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -25,6 +25,7 @@
  * @author Steven Spungin
  *
  */
+@SuppressWarnings("restriction")
 public class DocUtil {
 
 	public static Element createChild(Element parent, String name) {
@@ -34,7 +35,7 @@
 	}
 
 	public static Document createDocument(String name) throws ParserConfigurationException {
-		Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+		Document doc = org.eclipse.core.internal.runtime.XmlProcessorFactory.newDocumentWithErrorOnDOCTYPE();
 		doc.appendChild(doc.createElement(name));
 		return doc;
 	}
--- a/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/tabs/ListTab.java	2024-03-19 10:01:56.529764403 +0100
+++ b/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/tabs/ListTab.java	2024-03-19 11:39:19.103666147 +0100
@@ -30,7 +30,6 @@
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -251,8 +250,9 @@
 		final String xml = pref.get("list-tab-xml", ""); //$NON-NLS-1$ //$NON-NLS-2$
 		if (E.notEmpty(xml)) {
 			try {
-				final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
-						.parse(new InputSource(new StringReader(xml)));
+				@SuppressWarnings("restriction")
+				final Document doc = org.eclipse.core.internal.runtime.XmlProcessorFactory
+						.parseWithErrorOnDOCTYPE(new InputSource(new StringReader(xml)));
 				final XPath xpath = XPathFactory.newInstance().newXPath();
 				NodeList list;
 				if (restoreColumns) {
@@ -324,7 +324,9 @@
 
 	// @Refactor
 	static private String docToString(Document doc) throws TransformerException {
-		final TransformerFactory tf = TransformerFactory.newInstance();
+		@SuppressWarnings("restriction")
+		final TransformerFactory tf = org.eclipse.core.internal.runtime.XmlProcessorFactory
+				.createTransformerFactoryWithErrorOnDOCTYPE();
 		final Transformer transformer = tf.newTransformer();
 		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
 		final StringWriter writer = new StringWriter();
--- a/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java	2024-03-19 10:01:56.533097743 +0100
+++ b/eclipse.platform.ui.tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java	2024-03-19 11:39:19.103666147 +0100
@@ -36,11 +36,11 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 
+import org.eclipse.core.internal.runtime.XmlProcessorFactory;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.runtime.IPath;
@@ -86,6 +86,7 @@
  * @author Steven Spungin
  *
  */
+@SuppressWarnings("restriction")
 public abstract class TargetPlatformContributionCollector extends ClassContributionCollector {
 
 	CopyOnWriteArrayList<Entry> cacheEntry = new CopyOnWriteArrayList<>();
@@ -594,8 +595,8 @@
 			ret = new ArrayList<>();
 			outputDirectories.put(installLocation, ret);
 			try {
-				final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
-						.parse(new File(installLocation + File.separator + ".classpath")); //$NON-NLS-1$
+				File file = new File(installLocation + File.separator + ".classpath"); //$NON-NLS-1$
+				final Document doc = XmlProcessorFactory.parseWithErrorOnDOCTYPE(file);
 				final XPath xp = XPathFactory.newInstance().newXPath();
 				final NodeList list = (NodeList) xp.evaluate(
 						"//classpathentry[@kind='output']/@path", doc, XPathConstants.NODESET); //$NON-NLS-1$
openSUSE Build Service is sponsored by