Bug 577894 - Backport Bug 577341 from 4.22 to 4.7

Change-Id: I510aa4ec1ffb6d8b22812196ad044f99c6e31803
Reviewed-on:
https://git.eclipse.org/r/c/platform/eclipse.platform.debug/+/189162
Tested-by: Sarika Sinha <sarika.sinha@in.ibm.com>
Reviewed-by: Sarika Sinha <sarika.sinha@in.ibm.com>
(cherry picked from commit c5f1e5283d8ed285796215a1347d0b2a6b6d8ea2)
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.debug/+/189019
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/XMLMemento.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/XMLMemento.java
index d149c0f..7372a9b 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/XMLMemento.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/XMLMemento.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -19,6 +19,7 @@
 import java.io.Reader;
 import java.io.Writer;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -43,6 +44,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
@@ -60,51 +63,89 @@
         return createReadRoot(reader, null);
     }
 
-    /**
-     * Creates a <code>Document</code> from the <code>Reader</code>
-     * and returns a memento on the first <code>Element</code> for reading
-     * the document.
-     *
-     * @param reader the <code>Reader</code> used to create the memento's document
-     * @param baseDir the directory used to resolve relative file names
-     * 		in the XML document. This directory must exist and include the
-     * 		trailing separator. The directory format, including the separators,
-     * 		must be valid for the platform. Can be <code>null</code> if not
-     * 		needed.
-     * @return a memento on the first <code>Element</code> for reading the document
-     * @throws Exception if IO problems, invalid format, or no element.
-     */
+	/**
+	 * Clients who need to use the "file" protocol can override this method to
+	 * return the original attribute value
+	 *
+	 * @param attributeOldValue
+	 * @return return the new attribute value after concatenating the "file"
+	 *         protocol restriction if does not exist already
+	 */
+	private static String getAttributeNewValue(Object attributeOldValue) {
+		StringBuffer strNewValue = new StringBuffer(FILE_STRING);
+		if (attributeOldValue instanceof String && ((String) attributeOldValue).length() != 0) {
+			String strOldValue = (String) attributeOldValue;
+			boolean exists = Arrays.asList(strOldValue.split(",")).stream().anyMatch(x -> x.trim().equals(FILE_STRING)); //$NON-NLS-1$
+			if (!exists) {
+				strNewValue.append(", ").append(strOldValue); //$NON-NLS-1$
+			} else {
+				strNewValue = new StringBuffer(strOldValue);
+			}
+		}
+		return strNewValue.toString();
+	}
+
+	/**
+	 * Creates a <code>Document</code> from the <code>Reader</code> and returns
+	 * a memento on the first <code>Element</code> for reading the document.
+	 *
+	 * @param reader the <code>Reader</code> used to create the memento's
+	 *            document
+	 * @param baseDir the directory used to resolve relative file names in the
+	 *            XML document. This directory must exist and include the
+	 *            trailing separator. The directory format, including the
+	 *            separators, must be valid for the platform. Can be
+	 *            <code>null</code> if not needed.
+	 * @return a memento on the first <code>Element</code> for reading the
+	 *         document
+	 * @throws Exception if IO problems, invalid format, or no element.
+	 */
     public static XMLMemento createReadRoot(Reader reader, String baseDir)
             throws Exception {
-        String errorMessage = null;
-        Exception exception = null;
+		String errorMessage = null;
+		Exception exception = null;
+		DocumentBuilderFactory factory = null;
+		Object attributeDTDOldValue = null;
+		Object attributeSchemaOldValue = null;
+		try {
+			factory = DocumentBuilderFactory.newInstance();
+			try {
+				attributeDTDOldValue = factory.getAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD);
+				attributeSchemaOldValue = factory.getAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA);
+			} catch (NullPointerException | IllegalArgumentException e) {
+				// Attributes not defined
+			}
+			factory.setAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD, getAttributeNewValue(attributeDTDOldValue));
+			factory.setAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA, getAttributeNewValue(attributeSchemaOldValue));
 
-        try {
-            DocumentBuilderFactory factory = DocumentBuilderFactory
-                    .newInstance();
-            DocumentBuilder parser = factory.newDocumentBuilder();
-            InputSource source = new InputSource(reader);
-            if (baseDir != null) {
+			DocumentBuilder parser = factory.newDocumentBuilder();
+			InputSource source = new InputSource(reader);
+			if (baseDir != null) {
 				source.setSystemId(baseDir);
 			}
-            Document document = parser.parse(source);
-            NodeList list = document.getChildNodes();
-            for (int i = 0; i < list.getLength(); i++) {
-                Node node = list.item(i);
-                if (node instanceof Element) {
+			Document document = parser.parse(source);
+			NodeList list = document.getChildNodes();
+			for (int i = 0; i < list.getLength(); i++) {
+				Node node = list.item(i);
+				if (node instanceof Element) {
 					return new XMLMemento(document, (Element) node);
 				}
-            }
-        } catch (ParserConfigurationException e) {
-            exception = e;
-           // errorMessage = WorkbenchMessages.XMLMemento_parserConfigError;
-        } catch (IOException e) {
-            exception = e;
-           // errorMessage = WorkbenchMessages.XMLMemento_ioError;
-        } catch (SAXException e) {
-            exception = e;
-           // errorMessage = WorkbenchMessages.XMLMemento_formatError;
-        }
+			}
+		} catch (ParserConfigurationException e) {
+			exception = e;
+			// errorMessage = WorkbenchMessages.XMLMemento_parserConfigError;
+		} catch (IOException e) {
+			exception = e;
+			// errorMessage = WorkbenchMessages.XMLMemento_ioError;
+		} catch (SAXException e) {
+			exception = e;
+			// errorMessage = WorkbenchMessages.XMLMemento_formatError;
+		} finally {
+			if (factory != null) {
+				factory.setAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD, attributeDTDOldValue);
+				factory.setAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA, attributeSchemaOldValue);
+			}
+		}
 
         String problemText = null;
         if (exception != null) {