Bug 483383 - (opt-out) option in UI to add check against current EE

This adds a preference to trigger an additional check against currently
running execution environment when using the ProvisioningWizard family
(install, uninstall, update...)

Checking against current JRE happens by checking whether a plan is valid
from the current operation + uninstall all a.jre.javase + exclude all
a.jre.javase + add a "volatile" installable unit describing the current
EE.
This alternative plan isn't intended to be applied to the profile, it
should only be used for testing.

Change-Id: If51489d216d403a833f9df2f7eb5cfab1a145fb4
Signed-off-by: Mickael Istria <mistria@redhat.com>
diff --git a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
index e23b1e4..3aad470 100644
--- a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.equinox.p2.director;singleton:=true
-Bundle-Version: 2.4.600.qualifier
+Bundle-Version: 2.4.700.qualifier
 Bundle-ClassPath: .
 Bundle-Activator: org.eclipse.equinox.internal.p2.director.DirectorActivator
 Bundle-Vendor: %providerName
diff --git a/bundles/org.eclipse.equinox.p2.director/pom.xml b/bundles/org.eclipse.equinox.p2.director/pom.xml
index 4364d9a..253af68 100644
--- a/bundles/org.eclipse.equinox.p2.director/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.director/pom.xml
@@ -9,6 +9,6 @@
   </parent>
   <groupId>org.eclipse.equinox</groupId>
   <artifactId>org.eclipse.equinox.p2.director</artifactId>
-  <version>2.4.600-SNAPSHOT</version>
+  <version>2.4.700-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/ProfileChangeRequest.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/ProfileChangeRequest.java
index 8b4c33b..0c92c1a 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/ProfileChangeRequest.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/ProfileChangeRequest.java
@@ -208,7 +208,7 @@
 
 	@Override
 	@SuppressWarnings("unchecked")
-	public Object clone() {
+	public ProfileChangeRequest clone() {
 		ProfileChangeRequest result = new ProfileChangeRequest(profile);
 		result.iusToRemove = iusToRemove == null ? null : (ArrayList<IInstallableUnit>) iusToRemove.clone();
 		result.iusToAdd = iusToAdd == null ? null : (ArrayList<IInstallableUnit>) iusToAdd.clone();
diff --git a/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
index 5305010..d30efa0 100644
--- a/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
@@ -2,10 +2,10 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.equinox.p2.operations;singleton:=true
-Bundle-Version: 2.5.700.qualifier
+Bundle-Version: 2.5.800.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
-Export-Package: org.eclipse.equinox.internal.p2.operations;x-friends:="org.eclipse.pde.ui",
+Export-Package: org.eclipse.equinox.internal.p2.operations;x-friends:="org.eclipse.pde.ui,org.eclipse.equinox.p2.ui",
  org.eclipse.equinox.p2.operations;version="2.0.0"
 Require-Bundle: org.eclipse.equinox.common;bundle-version="3.6.0",
  org.eclipse.core.jobs;bundle-version="3.5.0"
diff --git a/bundles/org.eclipse.equinox.p2.operations/pom.xml b/bundles/org.eclipse.equinox.p2.operations/pom.xml
index 2939caf..19e9526 100644
--- a/bundles/org.eclipse.equinox.p2.operations/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.operations/pom.xml
@@ -19,6 +19,6 @@
   </parent>
   <groupId>org.eclipse.equinox</groupId>
   <artifactId>org.eclipse.equinox.p2.operations</artifactId>
-  <version>2.5.700-SNAPSHOT</version>
+  <version>2.5.800-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
index d78261b..9ea6c17 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %bundleName
 Bundle-SymbolicName: org.eclipse.equinox.p2.ui.sdk;singleton:=true
-Bundle-Version: 1.1.500.qualifier
+Bundle-Version: 1.1.600.qualifier
 Bundle-Activator: org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKUIActivator
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -10,7 +10,7 @@
  org.eclipse.equinox.internal.p2.ui.sdk.prefs;x-internal:=true
 Require-Bundle: org.eclipse.ui;bundle-version="3.6.0",
  org.eclipse.core.runtime,
- org.eclipse.equinox.p2.ui
+ org.eclipse.equinox.p2.ui;bundle-version="2.6.0"
 Import-Package: javax.xml.parsers,
  org.eclipse.compare;resolution:=optional,
  org.eclipse.compare.structuremergeviewer;resolution:=optional,
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml b/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
index 0ffac0a..be96dc1 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
@@ -9,6 +9,6 @@
 	</parent>
 	<groupId>org.eclipse.equinox</groupId>
 	<artifactId>org.eclipse.equinox.p2.ui.sdk</artifactId>
-	<version>1.1.500-SNAPSHOT</version>
+	<version>1.1.600-SNAPSHOT</version>
 	<packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
index 5dc6f78..e985ebb 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
@@ -17,8 +17,8 @@
 import org.eclipse.osgi.util.NLS;
 
 /**
- * Message class for provisioning UI messages.  
- * 
+ * Message class for provisioning UI messages.
+ *
  * @since 3.4
  */
 public class ProvSDKMessages extends NLS {
@@ -39,6 +39,7 @@
 	public static String ProvisioningPreferencePage_OpenWizardIfInvalid;
 	public static String ProvisioningPreferencePage_PromptToOpenWizard;
 	public static String ProvisioningPreferencePage_UninstallUpdateLink;
+	public static String ProvisioningPreferencePage_checkCompatibleWithCurrentJRE;
 	public static String ProvSDKUIActivator_ErrorSavingPrefs;
 	public static String ProvSDKUIActivator_NoSelfProfile;
 	public static String ProvSDKUIActivator_OpenWizardAnyway;
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKUIActivator.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKUIActivator.java
index 8d04881..7fa681f 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKUIActivator.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKUIActivator.java
@@ -54,7 +54,7 @@
 
 	/**
 	 * Returns the singleton plugin instance
-	 * 
+	 *
 	 * @return the instance
 	 */
 	public static ProvSDKUIActivator getDefault() {
@@ -64,7 +64,7 @@
 	/**
 	 * Returns an image descriptor for the image file at the given plug-in
 	 * relative path
-	 * 
+	 *
 	 * @param path
 	 *            the path
 	 * @return the image descriptor
@@ -135,6 +135,10 @@
 		value = store.getString(PreferenceConstants.PREF_GROUP_BY_CATEGORY);
 		policy.setGroupByCategory(!IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value) ? store.getBoolean(PreferenceConstants.PREF_GROUP_BY_CATEGORY) : policy.getGroupByCategory());
 
+		value = store.getString(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE);
+		policy.setCheckAgainstCurrentExecutionEnvironment(!IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value)
+				? store.getBoolean(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE)
+				: policy.getCheckAgainstCurrentExecutionEnvironment());
 	}
 
 	/*
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
index 0fd03e6..febaa9e 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
@@ -28,6 +28,7 @@
 ProvisioningPreferencePage_OpenWizardIfInvalid=When software selected for an install wizard may not be compatible
 ProvisioningPreferencePage_PromptToOpenWizard=As&k me what to do when it happens
 ProvisioningPreferencePage_UninstallUpdateLink=<a>Uninstall or update</a> software that is already installed
+ProvisioningPreferencePage_checkCompatibleWithCurrentJRE=Verify provisioning operation is compatible with current running &JRE
 SDKPolicy_PrefPageName=Available Software Sites
 UpdateHandler_NoSitesMessage=There are no update sites to search.  Do you wish to open the "Available Software Sites" preferences?
 UpdateHandler_NoSitesTitle=No Updates Found
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceConstants.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceConstants.java
index 8da529d..54c0c0b 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceConstants.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceConstants.java
@@ -7,7 +7,7 @@
  *  https://www.eclipse.org/legal/epl-2.0/
  *
  *  SPDX-License-Identifier: EPL-2.0
- * 
+ *
  *  Contributors:
  *     IBM Corporation - initial API and implementation
  *     Ericsson AB (Hamdan Msheik) - Bug 396420 - Control Install dialog through preference customization
@@ -27,4 +27,5 @@
 	public static final String PREF_HIDE_INSTALLED = "hideAlreadyInstalled"; //$NON-NLS-1$
 	public static final String PREF_OPEN_WIZARD_ON_ERROR_PLAN = "allowNonOKPlan"; //$NON-NLS-1$
 	public static final String PREF_LICENSE_DIGESTS = "licenseDigestList"; //$NON-NLS-1$
+	public static final String PREF_CHECK_AGAINST_CURRENT_JRE = "checkAgainstCurrentJRE"; //$NON-NLS-1$
 }
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceInitializer.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceInitializer.java
index a5b61cd..9a1aeb9 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceInitializer.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/PreferenceInitializer.java
@@ -7,7 +7,7 @@
  *  https://www.eclipse.org/legal/epl-2.0/
  *
  *  SPDX-License-Identifier: EPL-2.0
- * 
+ *
  *  Contributors:
  *     IBM Corporation - initial API and implementation
  *     Ericsson AB (Hamdan Msheik) - Bug 396420 - Control Install dialog through preference customization
@@ -62,6 +62,7 @@
 		// default values
 		node.putBoolean(PreferenceConstants.PREF_SHOW_LATEST_VERSION, true);
 		node.put(PreferenceConstants.PREF_OPEN_WIZARD_ON_ERROR_PLAN, MessageDialogWithToggle.PROMPT);
+		node.putBoolean(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE, true);
 	}
 
 	private static IAgentLocation getDefaultAgentLocation() {
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/ProvisioningPreferencePage.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/ProvisioningPreferencePage.java
index 5f76933..4f1bd7c 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/ProvisioningPreferencePage.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/prefs/ProvisioningPreferencePage.java
@@ -7,7 +7,7 @@
  *  https://www.eclipse.org/legal/epl-2.0/
  *
  *  SPDX-License-Identifier: EPL-2.0
- * 
+ *
  *  Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -29,7 +29,7 @@
 
 /**
  * Preference page for general provisioning preferences.
- * 
+ *
  * @since 3.4
  */
 
@@ -38,6 +38,7 @@
 	private Group browsingGroup, validateGroup;
 	private Button showLatestRadio, showAllRadio;
 	private Button alwaysShowFailedPlan, neverShowFailedPlan, promptOnFailedPlan;
+	private Button checkAgainstCurrentCheckbox;
 
 	@Override
 	protected Control createContents(Composite parent) {
@@ -96,6 +97,9 @@
 		gd.horizontalSpan = 3;
 		promptOnFailedPlan.setLayoutData(gd);
 
+		checkAgainstCurrentCheckbox = new Button(container, SWT.CHECK);
+		checkAgainstCurrentCheckbox.setText(ProvSDKMessages.ProvisioningPreferencePage_checkCompatibleWithCurrentJRE);
+
 		//Link to installed software page
 		//See https://bugs.eclipse.org/bugs/show_bug.cgi?id=313242
 		Link link = new Link(container, SWT.PUSH);
@@ -117,6 +121,7 @@
 		alwaysShowFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.ALWAYS));
 		neverShowFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.NEVER));
 		promptOnFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.PROMPT));
+		checkAgainstCurrentCheckbox.setSelection(pref.getBoolean(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE));
 	}
 
 	@Override
@@ -129,6 +134,8 @@
 		alwaysShowFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.ALWAYS));
 		neverShowFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.NEVER));
 		promptOnFailedPlan.setSelection(openWizard.equals(MessageDialogWithToggle.PROMPT));
+		checkAgainstCurrentCheckbox
+				.setSelection(pref.getBoolean(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE, false));
 	}
 
 	@Override
@@ -141,7 +148,7 @@
 			pref.setValue(PreferenceConstants.PREF_OPEN_WIZARD_ON_ERROR_PLAN, MessageDialogWithToggle.NEVER);
 		else
 			pref.setValue(PreferenceConstants.PREF_OPEN_WIZARD_ON_ERROR_PLAN, MessageDialogWithToggle.PROMPT);
-
+		pref.setValue(PreferenceConstants.PREF_CHECK_AGAINST_CURRENT_JRE, checkAgainstCurrentCheckbox.getSelection());
 		ProvSDKUIActivator.getDefault().savePreferences();
 		return true;
 	}
diff --git a/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
index f358cfa..719b024 100644
--- a/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %bundleName
 Bundle-SymbolicName: org.eclipse.equinox.p2.ui;singleton:=true
-Bundle-Version: 2.5.900.qualifier
+Bundle-Version: 2.6.0.qualifier
 Bundle-Activator: org.eclipse.equinox.internal.p2.ui.ProvUIActivator
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -30,7 +30,7 @@
    org.eclipse.equinox.p2.ui.importexport",
  org.eclipse.equinox.internal.p2.ui.query;x-friends:="org.eclipse.equinox.internal.p2.ui.analysis,org.eclipse.equinox.p2.ui.admin",
  org.eclipse.equinox.internal.p2.ui.viewers;x-friends:="org.eclipse.equinox.p2.ui.admin,org.eclipse.equinox.p2.ui.sdk.scheduler,org.eclipse.equinox.p2.ui.importexport",
- org.eclipse.equinox.p2.ui;version="2.0.0"
+ org.eclipse.equinox.p2.ui;version="2.6.0"
 Require-Bundle: org.eclipse.ui;bundle-version="3.107.0",
  org.eclipse.core.runtime;bundle-version="[3.11.0,4.0.0)",
  org.eclipse.core.expressions,
@@ -43,6 +43,7 @@
  org.eclipse.equinox.internal.p2.director,
  org.eclipse.equinox.internal.p2.metadata,
  org.eclipse.equinox.internal.p2.metadata.repository,
+ org.eclipse.equinox.internal.p2.operations,
  org.eclipse.equinox.internal.p2.repository.helpers,
  org.eclipse.equinox.internal.provisional.configurator,
  org.eclipse.equinox.internal.provisional.p2.core.eventbus,
diff --git a/bundles/org.eclipse.equinox.p2.ui/pom.xml b/bundles/org.eclipse.equinox.p2.ui/pom.xml
index 116bfab..7abae4e 100644
--- a/bundles/org.eclipse.equinox.p2.ui/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.ui/pom.xml
@@ -19,6 +19,6 @@
   </parent>
   <groupId>org.eclipse.equinox</groupId>
   <artifactId>org.eclipse.equinox.p2.ui</artifactId>
-  <version>2.5.900-SNAPSHOT</version>
+  <version>2.6.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java
index 7b122b2..b59853e 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java
@@ -17,17 +17,24 @@
 
 package org.eclipse.equinox.internal.p2.ui;
 
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.eclipse.core.commands.*;
 import org.eclipse.core.commands.common.NotDefinedException;
 import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability;
 import org.eclipse.equinox.internal.p2.ui.dialogs.ILayoutConstants;
 import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext;
 import org.eclipse.equinox.internal.p2.ui.viewers.IUColumnConfig;
 import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
 import org.eclipse.equinox.p2.engine.*;
-import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.ProvisioningSession;
-import org.eclipse.equinox.p2.operations.UpdateOperation;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.equinox.p2.operations.*;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
 import org.eclipse.equinox.p2.query.QueryUtil;
 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
@@ -35,6 +42,7 @@
 import org.eclipse.equinox.p2.ui.ProvisioningUI;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.ManifestElement;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Shell;
@@ -42,6 +50,8 @@
 import org.eclipse.ui.commands.ICommandService;
 import org.eclipse.ui.handlers.IHandlerService;
 import org.eclipse.ui.statushandlers.StatusManager;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
 
 /**
  * Generic provisioning UI utility and policy methods.
@@ -309,4 +319,109 @@
 		return session.getProvisioningAgent().getService(IProvisioningEventBus.class);
 	}
 
+	public static IProvisioningPlan toCompabilityWithCurrentJREProvisioningPlan(
+			ProfileChangeOperation referenceOperation, IProgressMonitor monitor) {
+		IInstallableUnit currentJREUnit = createCurrentJavaSEUnit();
+		IProfileChangeRequest compatibilityWithCurrentRequest = toCurrentJREOperation(referenceOperation,
+				currentJREUnit);
+		IPlanner planner = referenceOperation.getProvisioningPlan().getProfile().getProvisioningAgent()
+				.getService(IPlanner.class);
+		IProvisioningPlan res = planner.getProvisioningPlan(compatibilityWithCurrentRequest,
+				referenceOperation.getProvisioningContext(), monitor);
+		return res;
+	}
+
+	private static IProfileChangeRequest toCurrentJREOperation(ProfileChangeOperation operation,
+			IInstallableUnit currnetJREUnit) {
+		IProfileChangeRequest initialRequest = operation.getProfileChangeRequest();
+		if (initialRequest == null) {
+			throw new IllegalStateException("operation plan must be resolved"); //$NON-NLS-1$
+		}
+		IProfileChangeRequest res = ((ProfileChangeRequest) initialRequest).clone();
+		res.addExtraRequirements(Collections.singleton(MetadataFactory
+				.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "a.jre.javase", null, null, 0, 0, false))); //$NON-NLS-1$
+		operation.getProvisioningPlan().getProfile().query(QueryUtil.createIUQuery("a.jre.javase"), null) //$NON-NLS-1$
+				.forEach(res::remove);
+		res.add(currnetJREUnit);
+		return res;
+	}
+
+	private static IInstallableUnit createCurrentJavaSEUnit() {
+		InstallableUnitDescription desc = new InstallableUnitDescription();
+		desc.setId("currently-running-execution-environement-do-not-actually-install"); //$NON-NLS-1$
+		Version eeVersion = getCurrentJavaSEVersion();
+		desc.setVersion(eeVersion);
+		desc.addProvidedCapabilities(Collections
+				.singletonList(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, desc.getId(), eeVersion)));
+		desc.addProvidedCapabilities(parseSystemCapabilities(Constants.FRAMEWORK_SYSTEMCAPABILITIES));
+		desc.addProvidedCapabilities(parseSystemCapabilities(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA));
+		desc.addProvidedCapabilities(toJavaPackageCapabilities(Constants.FRAMEWORK_SYSTEMPACKAGES));
+		desc.addProvidedCapabilities(toJavaPackageCapabilities(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA));
+		return MetadataFactory.createInstallableUnit(desc);
+	}
+
+	private static List<IProvidedCapability> toJavaPackageCapabilities(String systemPropertyName) {
+		String packages = System.getProperty(systemPropertyName);
+		if (packages != null && !packages.trim().isEmpty()) {
+			try {
+				return Arrays.stream(ManifestElement.parseHeader(systemPropertyName, packages)) //
+						.map(jrePackage -> {
+							String packageName = jrePackage.getValue();
+							Version packageVersion = Version.create(jrePackage.getAttribute("version")); //$NON-NLS-1$
+							return MetadataFactory.createProvidedCapability("java.package", packageName, //$NON-NLS-1$
+									packageVersion);
+						}).collect(Collectors.toList());
+			} catch (BundleException e) {
+				ProvUIActivator.getDefault().getLog()
+						.log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e));
+			}
+		}
+		return Collections.emptyList();
+	}
+
+	private static Version getCurrentJavaSEVersion() {
+		String[] segments = System.getProperty("java.version").split("\\."); //$NON-NLS-1$ //$NON-NLS-2$
+		if ("1".equals(segments[0])) { //$NON-NLS-1$
+			return Version.create(segments[0] + '.' + segments[1] + ".0"); //$NON-NLS-1$
+		}
+		return Version.create(segments[0] + ".0.0"); //$NON-NLS-1$
+	}
+
+	static Collection<IProvidedCapability> parseSystemCapabilities(String systemProperty) {
+		String systemCapabilities = System.getProperty(systemProperty);
+		if (systemCapabilities == null || systemCapabilities.trim().isEmpty()) {
+			return Collections.emptyList();
+		}
+		try {
+			return Arrays.stream(ManifestElement.parseHeader(systemProperty, systemCapabilities)) //
+					.flatMap(eeCapability -> {
+						String eeName = eeCapability.getAttribute("osgi.ee"); //$NON-NLS-1$
+						if (eeName == null) {
+							return Stream.empty();
+						}
+						return parseEECapabilityVersion(eeCapability) //
+								.map(version -> MetadataFactory.createProvidedCapability("osgi.ee", eeName, version)); //$NON-NLS-1$
+					}).collect(Collectors.toList());
+		} catch (BundleException e) {
+			ProvUIActivator.getDefault().getLog()
+					.log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e));
+			return Collections.emptyList();
+		}
+	}
+
+	private static Stream<Version> parseEECapabilityVersion(ManifestElement eeCapability) {
+		String singleVersion = eeCapability.getAttribute("version:Version"); //$NON-NLS-1$
+		String[] multipleVersions = ManifestElement
+				.getArrayFromList(eeCapability.getAttribute("version:List<Version>")); //$NON-NLS-1$
+
+		if (singleVersion == null && multipleVersions == null) {
+			return Stream.empty();
+		} else if (singleVersion == null) {
+			return Arrays.stream(multipleVersions).map(Version::parseVersion);
+		} else if (multipleVersions == null) {
+			return Stream.of(singleVersion).map(Version::parseVersion);
+		}
+		return Stream.empty();
+	}
+
 }
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
index be50b76..dbeb62b 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
@@ -35,8 +35,8 @@
 import org.eclipse.ui.PlatformUI;
 
 /**
- * An install wizard that allows the users to browse all of the repositories
- * and search/select for items to install.
+ * An install wizard that allows the users to browse all of the repositories and
+ * search/select for items to install.
  *
  * @since 3.6
  */
@@ -46,7 +46,8 @@
 	boolean ignoreSelectionChanges = false;
 	IStatus installHandlerStatus;
 
-	public InstallWizard(ProvisioningUI ui, InstallOperation operation, Collection<IInstallableUnit> initialSelections, LoadMetadataRepositoryJob preloadJob) {
+	public InstallWizard(ProvisioningUI ui, InstallOperation operation, Collection<IInstallableUnit> initialSelections,
+			LoadMetadataRepositoryJob preloadJob) {
 		super(ui, operation, initialSelections == null ? null : initialSelections.toArray(), preloadJob);
 		setWindowTitle(ProvUIMessages.InstallIUOperationLabel);
 		setDefaultPageImageDescriptor(ProvUIImages.getImageDescriptor(ProvUIImages.WIZARD_BANNER_INSTALL));
@@ -72,7 +73,8 @@
 			return;
 		root = new IUElementListRoot(ui);
 		if (operation instanceof RemediationOperation) {
-			AvailableIUElement[] elements = ElementUtils.requestToElement(((RemediationOperation) operation).getCurrentRemedy(), true);
+			AvailableIUElement[] elements = ElementUtils
+					.requestToElement(((RemediationOperation) operation).getCurrentRemedy(), true);
 			root.setChildren(elements);
 			planSelections = elements;
 		} else {
@@ -81,7 +83,8 @@
 			for (Object selectedElement : selectedElements) {
 				IInstallableUnit iu = ElementUtils.getIU(selectedElement);
 				if (iu != null) {
-					AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), shouldShowProvisioningPlanChildren());
+					AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(),
+							shouldShowProvisioningPlanChildren());
 					list.add(element);
 					selections.add(element);
 				}
@@ -92,8 +95,7 @@
 	}
 
 	/*
-	 * Overridden to dynamically determine which page to get
-	 * selections from.
+	 * Overridden to dynamically determine which page to get selections from.
 	 */
 	@Override
 	protected Object[] getOperationSelections() {
@@ -101,10 +103,9 @@
 	}
 
 	/*
-	 * Get the page that is driving operation selections.  This is
-	 * usually the main page, but it could be error page if there
-	 * was a resolution error and the user decides to change selections
-	 * and try again without going back.
+	 * Get the page that is driving operation selections. This is usually the main
+	 * page, but it could be error page if there was a resolution error and the user
+	 * decides to change selections and try again without going back.
 	 */
 	protected ISelectableIUsPage getOperationSelectionsPage() {
 		IWizardPage page = getContainer().getCurrentPage();
@@ -141,14 +142,14 @@
 	protected ProfileChangeOperation getProfileChangeOperation(Object[] elements) {
 		InstallOperation op = new InstallOperation(ui.getSession(), ElementUtils.elementsToIUs(elements));
 		op.setProfileId(getProfileId());
-		//		op.setRootMarkerKey(getRootMarkerKey());
+		// op.setRootMarkerKey(getRootMarkerKey());
 		return op;
 	}
 
 	@Override
 	protected boolean shouldUpdateErrorPageModelOnPlanChange() {
 		// We don't want the root of the error page to change unless we are on the
-		// main page.  For example, if we are on the error page, change checkmarks, and
+		// main page. For example, if we are on the error page, change checkmarks, and
 		// resolve again with an error, we wouldn't want the root items to change in the
 		// error page.
 		return getContainer().getCurrentPage() == mainPage && super.shouldUpdateErrorPageModelOnPlanChange();
@@ -161,8 +162,8 @@
 	}
 
 	/*
-	 * overridden to ensure that the main page selections stay in synch
-	 * with changes to the error page.
+	 * overridden to ensure that the main page selections stay in synch with changes
+	 * to the error page.
 	 */
 	@Override
 	public void operationSelectionsChanged(ISelectableIUsPage page) {
@@ -171,9 +172,11 @@
 		super.operationSelectionsChanged(page);
 		// If we are on the error page, resolution has failed.
 		// Our ability to move on depends on whether the selections have changed.
-		// If they are the same selections, then we are not complete until selections are changed.
+		// If they are the same selections, then we are not complete until selections
+		// are changed.
 		if (getOperationSelectionsPage() == errorPage)
-			((WizardPage) errorPage).setPageComplete(pageSelectionsHaveChanged(errorPage) && errorPage.getCheckedIUElements().length > 0);
+			((WizardPage) errorPage).setPageComplete(
+					pageSelectionsHaveChanged(errorPage) && errorPage.getCheckedIUElements().length > 0);
 		synchSelections(page);
 	}
 
@@ -192,32 +195,39 @@
 	}
 
 	/*
-	 * Overridden to check whether there are UpdateManager install handlers in the item
-	 * to be installed.  Operations don't know about this compatibility issue.
+	 * Overridden to check whether there are UpdateManager install handlers in the
+	 * item to be installed. Operations don't know about this compatibility issue.
 	 */
 	@Override
 	public IStatus getCurrentStatus() {
 		IStatus originalStatus = super.getCurrentStatus();
 		int sev = originalStatus.getSeverity();
-		// Use the previously computed status if the user cancelled or if we were already in error.
-		// If we don't have an operation or a plan, we can't check this condition either, so just
+		// Use the previously computed status if the user cancelled or if we were
+		// already in error.
+		// If we don't have an operation or a plan, we can't check this condition
+		// either, so just
 		// use the normal status.
-		if (sev == IStatus.CANCEL || sev == IStatus.ERROR || operation == null || operation.getProvisioningPlan() == null) {
+		if (sev == IStatus.CANCEL || sev == IStatus.ERROR || operation == null
+				|| operation.getProvisioningPlan() == null) {
 			return originalStatus;
 		}
 		// Does the plan require install handler support?
 		installHandlerStatus = UpdateManagerCompatibility.getInstallHandlerStatus(operation.getProvisioningPlan());
 		if (!installHandlerStatus.isOK()) {
-			// Set the status into the wizard.  This ensures future calls to this method won't
+			// Set the status into the wizard. This ensures future calls to this method
+			// won't
 			// repeat the work (and prompting).
 			couldNotResolveStatus = installHandlerStatus;
 
-			// Is the update manager installer present?  If so, offer to open it.
+			// Is the update manager installer present? If so, offer to open it.
 			// In either case, the failure will be reported in this wizard.
 			if (ProvUI.isUpdateManagerInstallerPresent()) {
 				PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
 					Shell shell = ProvUI.getDefaultParentShell();
-					MessageDialog dialog = new MessageDialog(shell, ProvUIMessages.Policy_RequiresUpdateManagerTitle, null, ProvUIMessages.Policy_RequiresUpdateManagerMessage, MessageDialog.WARNING, new String[] {ProvUIMessages.LaunchUpdateManagerButton, IDialogConstants.CANCEL_LABEL}, 0);
+					MessageDialog dialog = new MessageDialog(shell, ProvUIMessages.Policy_RequiresUpdateManagerTitle,
+							null, ProvUIMessages.Policy_RequiresUpdateManagerMessage, MessageDialog.WARNING,
+							new String[] { ProvUIMessages.LaunchUpdateManagerButton, IDialogConstants.CANCEL_LABEL },
+							0);
 					if (dialog.open() == 0)
 						BusyIndicator.showWhile(shell.getDisplay(), () -> UpdateManagerCompatibility.openInstaller());
 				});
@@ -228,14 +238,16 @@
 	}
 
 	/*
-	 * When we've found an install handler, that status trumps anything that the operation might have
-	 * determined.  We are relying here on the knowledge that the wizard's couldNotResolveStatus is
-	 * reset on every new resolution, so that status only holds the installHandler status when it is
-	 * the current status.  The installHandlerStatus must be non-OK for it to matter at all.
+	 * When we've found an install handler, that status trumps anything that the
+	 * operation might have determined. We are relying here on the knowledge that
+	 * the wizard's couldNotResolveStatus is reset on every new resolution, so that
+	 * status only holds the installHandler status when it is the current status.
+	 * The installHandlerStatus must be non-OK for it to matter at all.
 	 *
 	 */
 	@Override
 	public boolean statusOverridesOperation() {
-		return installHandlerStatus != null && !installHandlerStatus.isOK() && couldNotResolveStatus == installHandlerStatus;
+		return super.statusOverridesOperation() || (installHandlerStatus != null && !installHandlerStatus.isOK()
+				&& couldNotResolveStatus == installHandlerStatus);
 	}
 }
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
index ea24c8e..cc2c367 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
@@ -23,6 +23,7 @@
 import org.eclipse.equinox.internal.p2.ui.*;
 import org.eclipse.equinox.internal.p2.ui.model.ElementUtils;
 import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot;
+import org.eclipse.equinox.p2.engine.IProvisioningPlan;
 import org.eclipse.equinox.p2.engine.ProvisioningContext;
 import org.eclipse.equinox.p2.metadata.IInstallableUnit;
 import org.eclipse.equinox.p2.operations.*;
@@ -55,6 +56,7 @@
 	boolean resolveWithRelaxedConstraints = false;
 	boolean waitingForOtherJobs = false;
 	protected RemediationOperation remediationOperation;
+	private IProvisioningPlan localJRECheckPlan;
 
 	public ProvisioningOperationWizard(ProvisioningUI ui, ProfileChangeOperation operation, Object[] initialSelections,
 			LoadMetadataRepositoryJob job) {
@@ -67,6 +69,12 @@
 		setNeedsProgressMonitor(true);
 		if (operation != null) {
 			provisioningContext = operation.getProvisioningContext();
+			if (operation.hasResolved() && getPolicy().getCheckAgainstCurrentExecutionEnvironment()) {
+				this.localJRECheckPlan = ProvUI.toCompabilityWithCurrentJREProvisioningPlan(operation, null);
+				if (!localJRECheckPlan.getStatus().isOK()) {
+					couldNotResolveStatus = localJRECheckPlan.getStatus();
+				}
+			}
 		}
 	}
 
@@ -152,6 +160,10 @@
 				initializeResolutionModelElements(planSelections);
 			}
 			IStatus status = operation.getResolutionResult();
+			if (status.getSeverity() != IStatus.ERROR && localJRECheckPlan != null
+					&& !localJRECheckPlan.getStatus().isOK()) {
+				return errorPage;
+			}
 			if (status == null || status.getSeverity() == IStatus.ERROR) {
 				if (page == mainPage) {
 					if (remediationOperation != null && remediationOperation.getResolutionResult() == Status.OK_STATUS
@@ -275,6 +287,7 @@
 		couldNotResolveStatus = Status.OK_STATUS;
 		provisioningContext = getProvisioningContext();
 		operation = null;
+		localJRECheckPlan = null;
 		remediationOperation = null;
 		initializeResolutionModelElements(getOperationSelections());
 		if (planSelections.length == 0) {
@@ -285,6 +298,12 @@
 			try {
 				runnableContext.run(true, true, monitor -> {
 					operation.resolveModal(monitor);
+					if (getPolicy().getCheckAgainstCurrentExecutionEnvironment()) {
+						this.localJRECheckPlan = ProvUI.toCompabilityWithCurrentJREProvisioningPlan(operation, monitor);
+						if (!localJRECheckPlan.getStatus().isOK()) {
+							couldNotResolveStatus = localJRECheckPlan.getStatus();
+						}
+					}
 					if (withRemediation) {
 						IStatus status = operation.getResolutionResult();
 						if (remediationPage != null && shouldRemediate(status)) {
@@ -303,11 +322,7 @@
 	}
 
 	public boolean shouldRemediate(IStatus status) {
-		if (status == null)
-			return true;
-		if (status.getSeverity() != IStatus.ERROR)
-			return false;
-		return true;
+		return status == null || status.getSeverity() == IStatus.ERROR;
 	}
 
 	/*
@@ -332,8 +347,14 @@
 	public IStatus getCurrentStatus() {
 		if (statusOverridesOperation())
 			return couldNotResolveStatus;
-		if (operation != null && operation.getResolutionResult() != null)
-			return operation.getResolutionResult();
+		if (operation != null && operation.getResolutionResult() != null) {
+			if (!operation.getResolutionResult().isOK() || localJRECheckPlan == null
+					|| localJRECheckPlan.getStatus().isOK()) {
+				return operation.getResolutionResult();
+			} else if (localJRECheckPlan != null) {
+				return localJRECheckPlan.getStatus();
+			}
+		}
 		return couldNotResolveStatus;
 	}
 
@@ -404,10 +425,12 @@
 					// job is waiting, sleeping, running, report failures when
 					// it's done
 					repoPreloadJob.addJobChangeListener(new JobChangeAdapter() {
+
 						@Override
 						public void done(IJobChangeEvent e) {
 							asyncReportLoadFailures();
 						}
+
 					});
 				}
 
@@ -435,7 +458,9 @@
 	 * override any detail reported by the operation.
 	 */
 	public boolean statusOverridesOperation() {
-		return false;
+		return operation != null && operation.getResolutionResult() != null
+				&& operation.getResolutionResult().getSeverity() < IStatus.ERROR
+				&& (localJRECheckPlan != null && !localJRECheckPlan.getStatus().isOK());
 	}
 
 	public void setRelaxedResolution(boolean value) {
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionStatusPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionStatusPage.java
index 5e1d621..8596da4 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionStatusPage.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionStatusPage.java
@@ -16,6 +16,7 @@
 package org.eclipse.equinox.internal.p2.ui.dialogs;
 
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.internal.p2.operations.ResolutionResult;
 import org.eclipse.equinox.internal.p2.ui.*;
 import org.eclipse.equinox.internal.p2.ui.model.*;
 import org.eclipse.equinox.internal.p2.ui.viewers.IUColumnConfig;
@@ -29,8 +30,8 @@
 import org.eclipse.ui.statushandlers.StatusManager;
 
 /**
- * A wizard page that presents a check box list of IUs and allows the user
- * to select and deselect them.  Typically the first page in a provisioning
+ * A wizard page that presents a check box list of IUs and allows the user to
+ * select and deselect them. Typically the first page in a provisioning
  * operation wizard, and usually it is the page used to report resolution errors
  * before advancing to resolution detail.
  *
@@ -54,7 +55,9 @@
 
 	/**
 	 * Update the caches associated with this page.
-	 * @param root the new root, or <code>null</code> if the root should not be updated.
+	 *
+	 * @param root              the new root, or <code>null</code> if the root
+	 *                          should not be updated.
 	 * @param resolvedOperation the new operation
 	 */
 	protected abstract void updateCaches(IUElementListRoot root, ProfileChangeOperation resolvedOperation);
@@ -70,10 +73,11 @@
 	/**
 	 * Update the status area of the wizard to report the results of the operation.
 	 *
-	 * @param newRoot the root that describes the root IUs involved in creating the plan.
-	 * 		This can be <code>null</code> if the root should not be updated.
+	 * @param newRoot the root that describes the root IUs involved in creating the
+	 *                plan. This can be <code>null</code> if the root should not be
+	 *                updated.
 	 *
-	 * @param op the ProfileChangeOperation that describes the operation
+	 * @param op      the ProfileChangeOperation that describes the operation
 	 */
 	public void updateStatus(IUElementListRoot newRoot, ProfileChangeOperation op) {
 		IStatus currentStatus = getProvisioningWizard().getCurrentStatus();
@@ -157,11 +161,14 @@
 
 		// We either haven't resolved, or we failed to resolve and reported some error
 		// while doing so.
-		if (resolvedOperation == null || !resolvedOperation.hasResolved() || getProvisioningWizard().statusOverridesOperation()) {
+		if (resolvedOperation == null || !resolvedOperation.hasResolved()
+				|| getProvisioningWizard().statusOverridesOperation()) {
 			// See if the wizard status knows something more about it.
 			IStatus currentStatus = getProvisioningWizard().getCurrentStatus();
 			if (!currentStatus.isOK()) {
-				detail = currentStatus.getMessage();
+				ResolutionResult result = new ResolutionResult();
+				result.addSummaryStatus(currentStatus);
+				detail = result.getSummaryReport();
 				detailsGroup.enablePropertyLink(false);
 			} else if (selectedIU != null) {
 				detail = getIUDescription(selectedElement);
@@ -174,7 +181,8 @@
 			return;
 		}
 
-		// An IU is selected and we have resolved.  Look for information about the specific IU.
+		// An IU is selected and we have resolved. Look for information about the
+		// specific IU.
 		if (selectedIU != null) {
 			detail = resolvedOperation.getResolutionDetails(selectedIU);
 			if (detail != null) {
@@ -182,7 +190,7 @@
 				detailsGroup.setDetailText(detail);
 				return;
 			}
-			// No specific error about this IU.  Show the overall error if it is in error.
+			// No specific error about this IU. Show the overall error if it is in error.
 			if (resolvedOperation.getResolutionResult().getSeverity() == IStatus.ERROR) {
 				detail = resolvedOperation.getResolutionDetails();
 				if (detail != null) {
@@ -192,14 +200,14 @@
 				}
 			}
 
-			// The overall status is not an error, or else there was no explanatory text for an error.
+			// The overall status is not an error, or else there was no explanatory text for
+			// an error.
 			// We may as well just show info about this iu.
 			detailsGroup.enablePropertyLink(true);
 			detailsGroup.setDetailText(getIUDescription(selectedElement));
 			return;
 		}
-
-		//No IU is selected, give the overall report
+		// No IU is selected, give the overall report
 		detail = resolvedOperation.getResolutionDetails();
 		detailsGroup.enablePropertyLink(false);
 		if (detail == null)
@@ -301,11 +309,14 @@
 	protected IUColumnConfig[] getColumnConfig() {
 		// We intentionally use the IU's id as one of the columns, because
 		// resolution errors are reported by ID.
-		nameColumn = new IUColumnConfig(ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME, ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH);
-		versionColumn = new IUColumnConfig(ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION, ILayoutConstants.DEFAULT_SMALL_COLUMN_WIDTH);
-		idColumn = new IUColumnConfig(ProvUIMessages.ProvUI_IdColumnTitle, IUColumnConfig.COLUMN_ID, ILayoutConstants.DEFAULT_COLUMN_WIDTH);
+		nameColumn = new IUColumnConfig(ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME,
+				ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH);
+		versionColumn = new IUColumnConfig(ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION,
+				ILayoutConstants.DEFAULT_SMALL_COLUMN_WIDTH);
+		idColumn = new IUColumnConfig(ProvUIMessages.ProvUI_IdColumnTitle, IUColumnConfig.COLUMN_ID,
+				ILayoutConstants.DEFAULT_COLUMN_WIDTH);
 		getColumnWidthsFromSettings();
-		return new IUColumnConfig[] {nameColumn, versionColumn, idColumn};
+		return new IUColumnConfig[] { nameColumn, versionColumn, idColumn };
 	}
 
 	private boolean isLocked(AvailableIUElement elementToBeUpdated) {
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/Policy.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/Policy.java
index 6d13d15..011b146 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/Policy.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/Policy.java
@@ -28,70 +28,69 @@
 import org.eclipse.ui.statushandlers.StatusManager;
 
 /**
- * The Policy class is used to specify application specific policies that
- * should be used in the standard p2 UI class libraries.   The default policy
- * is acquired using the OSGi service model.
+ * The Policy class is used to specify application specific policies that should
+ * be used in the standard p2 UI class libraries. The default policy is acquired
+ * using the OSGi service model.
  *
- * Policy allows clients to specify things such as how repositories
- * are manipulated in the standard wizards and dialogs, and how the repositories
- * or the installation itself should be traversed when displaying content.
+ * Policy allows clients to specify things such as how repositories are
+ * manipulated in the standard wizards and dialogs, and how the repositories or
+ * the installation itself should be traversed when displaying content.
  *
- * In some cases, the Policy is used only to define a default value that can
- * be overridden by user choice and subsequently stored in dialog settings.
+ * In some cases, the Policy is used only to define a default value that can be
+ * overridden by user choice and subsequently stored in dialog settings.
  *
- * Client applications should ensure that their Policy is registered before
- * any of the p2 UI objects access the default Policy.
+ * Client applications should ensure that their Policy is registered before any
+ * of the p2 UI objects access the default Policy.
  *
  * @since 2.0
  */
 public class Policy {
 
 	/**
-	 * A constant indicating that restart should be forced (without
-	 * confirmation) immediately after completion of a provisioning operation.
+	 * A constant indicating that restart should be forced (without confirmation)
+	 * immediately after completion of a provisioning operation.
 	 *
 	 */
 	public static final int RESTART_POLICY_FORCE = 1;
 
 	/**
-	 * A constant indicating that the changes should be applied dynamically
-	 * to the profile (without confirmation) immediately after completion of
-	 * a provisioning operation.
+	 * A constant indicating that the changes should be applied dynamically to the
+	 * profile (without confirmation) immediately after completion of a provisioning
+	 * operation.
 	 */
 	public static final int RESTART_POLICY_FORCE_APPLY = 2;
 
 	/**
-	 * A constant indicating that the user should be prompted to
-	 * restart after completion of a provisioning operation.
+	 * A constant indicating that the user should be prompted to restart after
+	 * completion of a provisioning operation.
 	 */
 	public static final int RESTART_POLICY_PROMPT = 3;
 
 	/**
-	 * A constant indicating that, where possible, the user should
-	 * be given the option to restart or dynamically apply the changes
-	 * after completion of a provisioning operation.
+	 * A constant indicating that, where possible, the user should be given the
+	 * option to restart or dynamically apply the changes after completion of a
+	 * provisioning operation.
 	 */
 	public static final int RESTART_POLICY_PROMPT_RESTART_OR_APPLY = 4;
 
 	/**
-	 * A constant indicating that the user should be presented with an
-	 * update wizard that shows a list of IUs that can be updated.
-	 * Even when only one update is available, a list showing the single
-	 * update will be used.  This option is recommended when the user's view
-	 * of the system is a set of component updates and the user is expected
-	 * to have knowledge of the composition of the system.
+	 * A constant indicating that the user should be presented with an update wizard
+	 * that shows a list of IUs that can be updated. Even when only one update is
+	 * available, a list showing the single update will be used. This option is
+	 * recommended when the user's view of the system is a set of component updates
+	 * and the user is expected to have knowledge of the composition of the system.
 	 *
 	 * @since 2.1
 	 */
 	public static final int UPDATE_STYLE_MULTIPLE_IUS = 1;
 
 	/**
-	 * A constant indicating that the user should be presented with an
-	 * update wizard that shows detail about a single IU that can be
-	 * updated.  If more than one IU can be updated, the user will be shown
-	 * a list; however, this option is recommended to be used only when
-	 * the user's view of the system is a single application that can be
-	 * updated, and only one IU is expected to be available for update.
+	 * A constant indicating that the user should be presented with an update wizard
+	 * that shows detail about a single IU that can be updated. If more than one IU
+	 * can be updated, the user will be shown a list; however, this option is
+	 * recommended to be used only when the user's view of the system is a single
+	 * application that can be updated, and only one IU is expected to be available
+	 * for update.
 	 *
 	 * @since 2.1
 	 */
@@ -111,16 +110,18 @@
 	private boolean filterOnEnv = false;
 	private int updateWizardStyle = UPDATE_STYLE_MULTIPLE_IUS;
 	private Point wizardDetailsPreferredSize = null;
+	private boolean checkAgainstCurrentExecutionEnvironment;
 
 	/**
-	 * Answer a boolean indicating whether the caller should continue to work with the
-	 * specified operation.  This method is used when an operation has been resolved, but
-	 * the UI may have further restrictions on continuing with it.
+	 * Answer a boolean indicating whether the caller should continue to work with
+	 * the specified operation. This method is used when an operation has been
+	 * resolved, but the UI may have further restrictions on continuing with it.
 	 *
-	 * @param operation the operation in question.  It must already be resolved.
-	 * @param shell the shell to use for any interaction with the user
-	 * @return <code>true</code> if processing of the operation should continue, <code>false</code> if
-	 * not.  It is up to the implementor to report any errors to the user when answering <code>false</code>.
+	 * @param operation the operation in question. It must already be resolved.
+	 * @param shell     the shell to use for any interaction with the user
+	 * @return <code>true</code> if processing of the operation should continue,
+	 *         <code>false</code> if not. It is up to the implementor to report any
+	 *         errors to the user when answering <code>false</code>.
 	 */
 	public boolean continueWorkingWithOperation(ProfileChangeOperation operation, Shell shell) {
 		Assert.isTrue(operation.getResolutionResult() != null);
@@ -135,7 +136,7 @@
 			return false;
 		}
 
-		// there is no plan, so we can't continue.  Report any reason found
+		// there is no plan, so we can't continue. Report any reason found
 		if (operation.getProvisioningPlan() == null && !status.isOK()) {
 			StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.SHOW);
 			return false;
@@ -146,18 +147,19 @@
 	}
 
 	/**
-	 * Return a status that can be used to describe the failure to
-	 * retrieve a profile.
-	 * @return a status describing a failure to retrieve a profile,
-	 * or <code>null</code> if there is no such status.
+	 * Return a status that can be used to describe the failure to retrieve a
+	 * profile.
+	 *
+	 * @return a status describing a failure to retrieve a profile, or
+	 *         <code>null</code> if there is no such status.
 	 */
 	public IStatus getNoProfileChosenStatus() {
 		return null;
 	}
 
 	/**
-	 * Return a query that can be used to obtain the IInstallableUnits that
-	 * should be presented to the user from the software repositories.
+	 * Return a query that can be used to obtain the IInstallableUnits that should
+	 * be presented to the user from the software repositories.
 	 *
 	 * @return the query used to retrieve user visible available IUs
 	 */
@@ -166,8 +168,8 @@
 	}
 
 	/**
-	 * Set the query that can be used to obtain the IInstallableUnits that
-	 * should be presented to the user.
+	 * Set the query that can be used to obtain the IInstallableUnits that should be
+	 * presented to the user.
 	 *
 	 * @param query the query used to retrieve user visible available IUs
 	 */
@@ -176,8 +178,8 @@
 	}
 
 	/**
-	 * Return a query that can be used to obtain the IInstallableUnits in
-	 * the profile that should be presented to the user.
+	 * Return a query that can be used to obtain the IInstallableUnits in the
+	 * profile that should be presented to the user.
 	 *
 	 * @return the query used to retrieve user visible installed IUs
 	 */
@@ -186,8 +188,8 @@
 	}
 
 	/**
-	 * Set the query that can be used to obtain the IInstallableUnits in
-	 * the profile that should be presented to the user.
+	 * Set the query that can be used to obtain the IInstallableUnits in the profile
+	 * that should be presented to the user.
 	 *
 	 * @param query the query used to retrieve user visible installed IUs
 	 */
@@ -226,68 +228,68 @@
 	}
 
 	/**
-	 * Return a boolean indicating whether the repositories should
-	 * be visible to the user, such that the user can add, remove, and
-	 * otherwise manipulate the software site list.
+	 * Return a boolean indicating whether the repositories should be visible to the
+	 * user, such that the user can add, remove, and otherwise manipulate the
+	 * software site list.
 	 *
-	 * @return <code>true</code> if repositories are visible to the end
-	 * user, <code>false</code> if they are not.
+	 * @return <code>true</code> if repositories are visible to the end user,
+	 *         <code>false</code> if they are not.
 	 */
 	public boolean getRepositoriesVisible() {
 		return repositoriesVisible;
 	}
 
 	/**
-	 * Set a boolean indicating whether the repositories should
-	 * be visible to the user, such that the user can add, remove, and
-	 * otherwise manipulate the software site list.
+	 * Set a boolean indicating whether the repositories should be visible to the
+	 * user, such that the user can add, remove, and otherwise manipulate the
+	 * software site list.
 	 *
-	 * @param visible <code>true</code> if repositories are visible to the end
-	 * user, <code>false</code> if they are not.
+	 * @param visible <code>true</code> if repositories are visible to the end user,
+	 *                <code>false</code> if they are not.
 	 */
 	public void setRepositoriesVisible(boolean visible) {
 		this.repositoriesVisible = visible;
 	}
 
 	/**
-	 * Return a boolean indicating whether only the latest versions of
-	 * updates and available software should be shown to the user.
+	 * Return a boolean indicating whether only the latest versions of updates and
+	 * available software should be shown to the user.
 	 *
 	 * @return <code>true</code> if only the latest versions are shown,
-	 * <code>false</code> if all versions should be shown.
+	 *         <code>false</code> if all versions should be shown.
 	 */
 	public boolean getShowLatestVersionsOnly() {
 		return showLatestVersionsOnly;
 	}
 
 	/**
-	 * Set a boolean indicating whether only the latest versions of
-	 * updates and available software should be shown to the user.
+	 * Set a boolean indicating whether only the latest versions of updates and
+	 * available software should be shown to the user.
 	 *
 	 * @param showLatest <code>true</code> if only the latest versions are shown,
-	 * <code>false</code> if all versions should be shown.
+	 *                   <code>false</code> if all versions should be shown.
 	 */
 	public void setShowLatestVersionsOnly(boolean showLatest) {
 		this.showLatestVersionsOnly = showLatest;
 	}
 
 	/**
-	 * Return a boolean indicating whether the user should be allowed drill
-	 * down from a visible update or installed item into the requirements.
+	 * Return a boolean indicating whether the user should be allowed drill down
+	 * from a visible update or installed item into the requirements.
 	 *
-	 * @return <code>true</code> if drilldown is allowed,
-	 * <code>false</code> if it is not.
+	 * @return <code>true</code> if drilldown is allowed, <code>false</code> if it
+	 *         is not.
 	 */
 	public boolean getShowDrilldownRequirements() {
 		return allowDrilldown;
 	}
 
 	/**
-	 * Set a boolean indicating whether the user should be allowed drill
-	 * down from a visible update or installed item into the requirements.
+	 * Set a boolean indicating whether the user should be allowed drill down from a
+	 * visible update or installed item into the requirements.
 	 *
 	 * @param drilldown <code>true</code> if drilldown is allowed,
-	 * <code>false</code> if it is not.
+	 *                  <code>false</code> if it is not.
 	 */
 	public void setShowDrilldownRequirements(boolean drilldown) {
 		this.allowDrilldown = drilldown;
@@ -297,8 +299,8 @@
 	 * Return a boolean value indicating whether or not the list of available
 	 * software should be filtered based on the environment settings of the profile.
 	 *
-	 * @return <code>true</code> if the results should be filtered
-	 * and <code>false</code> otherwise.
+	 * @return <code>true</code> if the results should be filtered and
+	 *         <code>false</code> otherwise.
 	 * @since 2.1
 	 */
 	public boolean getFilterOnEnv() {
@@ -306,11 +308,11 @@
 	}
 
 	/**
-	 * Set a boolean value indicating whether or not the list of available
-	 * software should be filtered based on the environment settings of the profile.
+	 * Set a boolean value indicating whether or not the list of available software
+	 * should be filtered based on the environment settings of the profile.
 	 *
-	 * @param filterOnEnv <code>true</code> if the results should be filtered
-	 * and <code>false</code> otherwise.
+	 * @param filterOnEnv <code>true</code> if the results should be filtered and
+	 *                    <code>false</code> otherwise.
 	 * @since 2.1
 	 */
 	public void setFilterOnEnv(boolean filterOnEnv) {
@@ -318,44 +320,44 @@
 	}
 
 	/**
-	 * Return a boolean indicating whether available software should be
-	 * grouped by category.
+	 * Return a boolean indicating whether available software should be grouped by
+	 * category.
 	 *
 	 * @return <code>true</code> if items should be grouped by category,
-	 * <code>false</code> if categories should not be shown.
+	 *         <code>false</code> if categories should not be shown.
 	 */
 	public boolean getGroupByCategory() {
 		return groupByCategory;
 	}
 
 	/**
-	 * Set a boolean indicating whether available software should be
-	 * grouped by category.
+	 * Set a boolean indicating whether available software should be grouped by
+	 * category.
 	 *
 	 * @param group <code>true</code> if items should be grouped by category,
-	 * <code>false</code> if categories should not be shown.
+	 *              <code>false</code> if categories should not be shown.
 	 */
 	public void setGroupByCategory(boolean group) {
 		this.groupByCategory = group;
 	}
 
 	/**
-	 * Get the id of the preference page that should be used to link to the
-	 * software sites page.
+	 * Get the id of the preference page that should be used to link to the software
+	 * sites page.
 	 *
 	 * @return the preference page id, or <code>null</code> if there is no
-	 * preference page id showing the software sites.
+	 *         preference page id showing the software sites.
 	 */
 	public String getRepositoryPreferencePageId() {
 		return repoPrefPageId;
 	}
 
 	/**
-	 * Set the id of the preference page that should be used to link to the
-	 * software sites page.
+	 * Set the id of the preference page that should be used to link to the software
+	 * sites page.
 	 *
 	 * @param id the preference page id, or <code>null</code> if there is no
-	 * preference page id showing the software sites.
+	 *           preference page id showing the software sites.
 	 */
 
 	public void setRepositoryPreferencePageId(String id) {
@@ -367,7 +369,7 @@
 	 * links to the software sites page.
 	 *
 	 * @return the preference page name, or <code>null</code> if there is no
-	 * preference page.
+	 *         preference page.
 	 */
 	public String getRepositoryPreferencePageName() {
 		return repoPrefPageName;
@@ -375,11 +377,11 @@
 
 	/**
 	 * Set the localized name of the preference page that should be displayed in
-	 * links to the software sites page.  This name is ignored if no id is specified
+	 * links to the software sites page. This name is ignored if no id is specified
 	 * for the preference page.
 	 *
 	 * @param name the preference page name, or <code>null</code> if there is no
-	 * preference page.
+	 *             preference page.
 	 *
 	 * @see Policy#setRepositoryPreferencePageId(String)
 	 */
@@ -389,8 +391,8 @@
 	}
 
 	/**
-	 * Get the update wizard style that should be used to determine
-	 * what to show the user when updates are available.
+	 * Get the update wizard style that should be used to determine what to show the
+	 * user when updates are available.
 	 *
 	 * @return an integer constant describing the update wizard style
 	 *
@@ -405,10 +407,11 @@
 	}
 
 	/**
-	 * Get the update wizard style that should be used to determine
-	 * what to show the user when updates are available.
+	 * Get the update wizard style that should be used to determine what to show the
+	 * user when updates are available.
 	 *
-	 * @param updateWizardStyle an integer constant describing the update wizard style
+	 * @param updateWizardStyle an integer constant describing the update wizard
+	 *                          style
 	 *
 	 * @see #UPDATE_STYLE_SINGLE_IUS
 	 * @see #UPDATE_STYLE_MULTIPLE_IUS
@@ -421,11 +424,12 @@
 	}
 
 	/**
-	 * Get a point describing the preferred size of the details area
-	 * shown in single IU update wizards.  This value may be null, in which case
-	 * the wizard may compute a default size.
+	 * Get a point describing the preferred size of the details area shown in single
+	 * IU update wizards. This value may be null, in which case the wizard may
+	 * compute a default size.
 	 *
-	 * @return a Point describing the preferred size of the update wizard details area.
+	 * @return a Point describing the preferred size of the update wizard details
+	 *         area.
 	 *
 	 * @see #UPDATE_STYLE_SINGLE_IUS
 	 *
@@ -438,9 +442,8 @@
 
 	/**
 	 * Set the preferred size of the details area shown in update wizards which
-	 * notify the user of a single update.  Clients can use this value to ensure
-	 * that their product's branded update notifier is sized to fit the expected
-	 * content.
+	 * notify the user of a single update. Clients can use this value to ensure that
+	 * their product's branded update notifier is sized to fit the expected content.
 	 *
 	 * @param preferredSize a Point describing the preferred size
 	 *
@@ -457,7 +460,7 @@
 	 * Get a boolean value indicating whether to contact all sites.
 	 *
 	 * @return <code>true</code> true if all sites need to be contacted,
-	 * <code>false</code> otherwise.
+	 *         <code>false</code> otherwise.
 	 *
 	 * @since 2.3
 	 */
@@ -469,7 +472,7 @@
 	 * Set a boolean indicating whether all sites need to be contacted.
 	 *
 	 * @param contactAll <code>true</code> if all sites need to be contacted,
-	 * <code>false</code> otherwise.
+	 *                   <code>false</code> otherwise.
 	 *
 	 * @since 2.3
 	 */
@@ -481,7 +484,7 @@
 	 * Get a boolean value indicating whether to hide already installed units.
 	 *
 	 * @return <code>true</code> if already installed units are to be hidden,
-	 * <code>false</code> otherwise.
+	 *         <code>false</code> otherwise.
 	 *
 	 * @since 2.3
 	 */
@@ -493,11 +496,37 @@
 	 * Set a boolean indicating whether to hide already installed units.
 	 *
 	 * @param hide <code>true</code> if already installed units need to be hidden,
-	 * <code>false</code> otherwise.
+	 *             <code>false</code> otherwise.
 	 *
 	 * @since 2.3
 	 */
 	public void setHideAlreadyInstalled(boolean hide) {
 		this.hideAlreadyInstalled = hide;
 	}
+
+	/**
+	 * Get a boolean value indicating whether the provisioning operation should
+	 * check compatibility with current execution environment
+	 *
+	 * @return <code>true</code> if operation should check compatibility with
+	 *         current execution environment, <code>false</code> otherwise.
+	 *
+	 * @since 2.6
+	 */
+	public boolean getCheckAgainstCurrentExecutionEnvironment() {
+		return this.checkAgainstCurrentExecutionEnvironment;
+	}
+
+	/**
+	 * Set a boolean indicating whether the provisioning operation should check
+	 * compatibility with current execution environment.
+	 *
+	 * @param check code>true</code> if operation should check compatibility with
+	 *              current execution environment, <code>false</code> otherwise.
+	 *
+	 * @since 2.6
+	 */
+	public void setCheckAgainstCurrentExecutionEnvironment(boolean check) {
+		this.checkAgainstCurrentExecutionEnvironment = check;
+	}
 }