Bug 567046: allow disable HCR via launch attribute

https://bugs.eclipse.org/bugs/show_bug.cgi?id=567046

Amended: Add javadoc to launch attribute constant.
Amended: Move launch attribute into public api (JDIDebugModel).
Amended: Version bump to 3.17. Add @since tag.
Amended: Add plugin id as prefix of launch attribute name.

Change-Id: I8bc078e611125f2e04b7eb427e5dbc81b678a76b
Signed-off-by: Kris De Volder <kdevolder@pivotal.io>
diff --git a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
index 65ac95b..f4eb3af 100644
--- a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.debug; singleton:=true
-Bundle-Version: 3.16.100.qualifier
+Bundle-Version: 3.17.0.qualifier
 Bundle-ClassPath: jdimodel.jar,
  tools.jar
 Bundle-Activator: org.eclipse.jdt.internal.debug.core.JDIDebugPlugin
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
index a5fc75d..09b5390 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
@@ -143,6 +143,13 @@
 	public static final String PREF_SUSPEND_ON_RECURRENCE_STRATEGY = getPluginIdentifier() + ".PREF_SUSPEND_ON_RECURRENCE_STRATEGY"; //$NON-NLS-1$
 
 	/**
+	 * Launch attribute, use ILaunch.setAttribute to set it to "true", to disable hot code replace for an individual launch.
+	 *
+	 * @since 3.17
+	 */
+	public static final String DISABLE_HCR_LAUNCH_ATTRIBUTE = getPluginIdentifier() + ".disable.hcr"; //$NON-NLS-1$
+
+	/**
 	 * Not to be instantiated.
 	 */
 	private JDIDebugModel() {
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
index 4fa9a29..42c3f70 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
@@ -425,6 +425,9 @@
 				deregisterTarget(target);
 				continue;
 			}
+			if (!isHCREnabled(target)) {
+				continue;
+			}
 			// Make a local copy of the resources/names to swap so we can filter
 			// unloaded types on a per-target basis.
 			List<IResource> resourcesToReplace = new ArrayList<>(resources);
@@ -508,6 +511,15 @@
 		fDeltaCache.clear();
 	}
 
+	private boolean isHCREnabled(JDIDebugTarget target) {
+		ILaunch l = target.getLaunch();
+		if (l != null) {
+			boolean disabledByLaunch = "true".equals(l.getAttribute(JDIDebugModel.DISABLE_HCR_LAUNCH_ATTRIBUTE)); //$NON-NLS-1$
+			return !disabledByLaunch;
+		}
+		return false;
+	}
+
 	/**
 	 * Returns whether the given exception, which occurred during HCR, should be
 	 * logged. We anticipate that we can get IncompatibleThreadStateExceptions
diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml
index 19974f3..bd907ba 100644
--- a/org.eclipse.jdt.debug/pom.xml
+++ b/org.eclipse.jdt.debug/pom.xml
@@ -18,6 +18,6 @@
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug</artifactId>
-  <version>3.16.100-SNAPSHOT</version>
+  <version>3.17.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>