[566183] Lazily load known URIs
diff --git a/xml/bundles/org.eclipse.wst.dtd.core/contentmodel/org/eclipse/wst/dtd/core/internal/contentmodel/DTDImpl.java b/xml/bundles/org.eclipse.wst.dtd.core/contentmodel/org/eclipse/wst/dtd/core/internal/contentmodel/DTDImpl.java
index c9463d9..e6b066f 100644
--- a/xml/bundles/org.eclipse.wst.dtd.core/contentmodel/org/eclipse/wst/dtd/core/internal/contentmodel/DTDImpl.java
+++ b/xml/bundles/org.eclipse.wst.dtd.core/contentmodel/org/eclipse/wst/dtd/core/internal/contentmodel/DTDImpl.java
@@ -138,7 +138,7 @@
 			return false;
 		}
 
-		String[] activeContributors = DTDCorePlugin.KNOWN_URIS.keySet().toArray(new String[0]);
+		String[] activeContributors = DTDCorePlugin.getInstance().getKnownURIs().keySet().toArray(new String[0]);
 		/*
 		 * The last part at least must be the file name, and the first part
 		 * part of the installation location, so skip them
@@ -149,7 +149,7 @@
 				if (part.startsWith(activeContributors[j])) {
 					part = activeContributors[j];
 					String[] contributedUris = null;
-					if ((contributedUris = DTDCorePlugin.KNOWN_URIS.get(part)) != null) {
+					if ((contributedUris = DTDCorePlugin.getInstance().getKnownURIs().get(part)) != null) {
 						for (int k = 0; k < contributedUris.length; k++) {
 							if (dtdURI.endsWith(contributedUris[k])) {
 								return true;
diff --git a/xml/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/DTDCorePlugin.java b/xml/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/DTDCorePlugin.java
index 9896848..96e3617 100644
--- a/xml/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/DTDCorePlugin.java
+++ b/xml/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/DTDCorePlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2011 IBM Corporation and others.
+ * Copyright (c) 2001, 2021 IBM Corporation and others.
  * All rights reserved. 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
@@ -21,6 +21,8 @@
 
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IRegistryChangeEvent;
+import org.eclipse.core.runtime.IRegistryChangeListener;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Plugin;
 import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
@@ -29,7 +31,20 @@
 public class DTDCorePlugin extends Plugin {
 	private static DTDCorePlugin instance;
 
-	public static Map<String, String[]> KNOWN_URIS;
+	static final String ORG_ECLIPSE_WST_XML_CORE = "org.eclipse.wst.xml.core"; //$NON-NLS-1$
+	static final String CATALOG_CONTRIBUTIONS = "catalogContributions"; //$NON-NLS-1$
+
+	class RegistryChangeListener implements IRegistryChangeListener {
+		@Override
+		public void registryChanged(IRegistryChangeEvent event) {
+			if (event.getExtensionDeltas(ORG_ECLIPSE_WST_XML_CORE, CATALOG_CONTRIBUTIONS).length > 0) {
+				resetKnownURIs();
+			}
+		}
+	}
+
+	private Map<String, String[]> fKnownURIs;
+	private IRegistryChangeListener registryChangeListener;
 
 	public synchronized static DTDCorePlugin getInstance() {
 		return instance;
@@ -42,27 +57,8 @@
 	@Override
 	public void start(BundleContext context) throws Exception {
 		super.start(context);
-
-		KNOWN_URIS = new HashMap<>();
-		IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(XMLCorePlugin.getDefault().getBundle().getSymbolicName(), "catalogContributions");
-		IConfigurationElement[] configurationElements = extension.getConfigurationElements();
-		Map<String, List<String>> known = new HashMap<>();
-		for (int i = 0; i < configurationElements.length; i++) {
-			String contributor = configurationElements[i].getNamespaceIdentifier();
-			if (!known.containsKey(contributor)) {
-				known.put(contributor, new ArrayList<>());
-			}
-			IConfigurationElement[] elements = configurationElements[i].getChildren();
-			for (int j = 0; j < elements.length; j++) {
-				String uri = elements[j].getAttribute("uri");
-				if (uri != null && uri.length() > 0) {
-					known.get(contributor).add(uri);
-				}
-			}
-		}
-		known.forEach((contributor, uris) -> {
-			KNOWN_URIS.put(contributor, uris.toArray(new String[uris.size()]));
-		});
+		registryChangeListener = new RegistryChangeListener();
+		Platform.getExtensionRegistry().addRegistryChangeListener(registryChangeListener, ORG_ECLIPSE_WST_XML_CORE);
 	}
 
 	public DTDCorePlugin() {
@@ -70,4 +66,39 @@
 		instance = this;
 	}
 
+	public void resetKnownURIs() {
+		fKnownURIs = null;
+	}
+
+	public Map<String, String[]> getKnownURIs() {
+		if (fKnownURIs == null) {
+			fKnownURIs = new HashMap<>();
+			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(XMLCorePlugin.getDefault().getBundle().getSymbolicName(), CATALOG_CONTRIBUTIONS);
+			IConfigurationElement[] configurationElements = extension.getConfigurationElements();
+			Map<String, List<String>> known = new HashMap<>();
+			for (int i = 0; i < configurationElements.length; i++) {
+				String contributor = configurationElements[i].getNamespaceIdentifier();
+				if (!known.containsKey(contributor)) {
+					known.put(contributor, new ArrayList<>());
+				}
+				IConfigurationElement[] elements = configurationElements[i].getChildren();
+				for (int j = 0; j < elements.length; j++) {
+					String uri = elements[j].getAttribute("uri");
+					if (uri != null && uri.length() > 0) {
+						known.get(contributor).add(uri);
+					}
+				}
+			}
+			known.forEach((contributor, uris) -> {
+				fKnownURIs.put(contributor, uris.toArray(new String[uris.size()]));
+			});
+		}
+		return fKnownURIs;
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		Platform.getExtensionRegistry().removeRegistryChangeListener(registryChangeListener);
+		super.stop(context);
+	}
 }