*** empty log message ***
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/PatchCleaner.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/PatchCleaner.java
new file mode 100644
index 0000000..2e58ed1
--- /dev/null
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/PatchCleaner.java
@@ -0,0 +1,55 @@
+package org.eclipse.update.internal.ui;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.update.configuration.*;
+import org.eclipse.update.core.*;
+
+/**
+ * This utility class attaches as a listened to the provided
+ * configured site, and for every unconfigured feature 
+ * it tests if it is a patch and cleans up its backup configuration.
+ */
+
+public class PatchCleaner {
+	private IConfiguredSite csite;
+	private IFeature root;
+	private SiteListener listener;
+	class SiteListener implements IConfiguredSiteChangedListener {
+		public void featureInstalled(IFeature feature) {
+		}
+		public void featureRemoved(IFeature feature) {
+			cleanSavedConfigs(feature);
+		}
+		public void featureConfigured(IFeature feature) {
+		}
+		public void featureUnconfigured(IFeature feature) {
+			cleanSavedConfigs(feature);
+		}
+	}
+	public PatchCleaner(IConfiguredSite csite, IFeature root) {
+		this.csite = csite;
+		listener = new SiteListener();
+		csite.addConfiguredSiteChangedListener(listener);
+	}
+
+	public void dispose() {
+		csite.removeConfiguredSiteChangedListener(listener);
+	}
+	private void cleanSavedConfigs(IFeature feature) {
+		if (UpdateUIPlugin.isPatch(feature)) {
+			IInstallConfiguration backupConfig = UpdateUIPlugin.getBackupConfigurationFor(feature);
+			if (backupConfig!=null) {
+				// clean it
+				remove(backupConfig);
+			}
+		}
+	}
+	private void remove(IInstallConfiguration config) {
+		try {
+			ILocalSite localSite = SiteManager.getLocalSite();
+			localSite.removeFromPreservedConfigurations(config);
+		}
+		catch (CoreException e) {
+		}
+	}
+}
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPlugin.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPlugin.java
index be43d80..9c79101 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPlugin.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPlugin.java
@@ -283,6 +283,23 @@
 		}

 		return false;

 	}

+	

+	public static IInstallConfiguration getBackupConfigurationFor(IFeature feature) {

+		VersionedIdentifier vid = feature.getVersionedIdentifier();

+		String key = "@"+vid.getIdentifier()+"_"+vid.getVersion();

+		try {

+			ILocalSite lsite = SiteManager.getLocalSite();

+			IInstallConfiguration [] configs = lsite.getPreservedConfigurations();

+			for (int i=0; i<configs.length; i++) {

+				IInstallConfiguration config = configs[i];

+				if (config.getLabel().startsWith(key))

+					return config;

+			}

+		}

+		catch (CoreException e) {

+		}

+		return null;

+	}

 

 	/**

 	 * Gets the database.

diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPluginResources.properties b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPluginResources.properties
index 9d8a543..e5f3c7c 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPluginResources.properties
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/UpdateUIPluginResources.properties
@@ -109,6 +109,9 @@
 FeaturePage.missing.abort = &Abort

 FeaturePage.missing.searchObjectName = Missing plug-ins of {0}

 

+FeaturePage.optionalInstall.message = Feature cannot be found using {0}.

+FeaturePage.optionalInstall.title = Optional Install

+

 ActivityConstraints.rootMessage = Requested operation cannot be performed because it would invalidate the current configuration. See details for more information.

 ActivityConstraints.rootMessageInitial = Current configuration contains errors that are not corrected by the requested operation. See details for more information.

 ActivityConstraints.platform = Resulting configuration does not contain the platform.

@@ -130,6 +133,8 @@
 ActivityConstraints.patchRegression = Included feature "{0} ({1})" is older than the currently active feature.

 ActivityConstraints.patchUnconfigure = This feature is a patch and cannot be directly disabled. Use 'Revert' to restore \

 the last configuration before the patch was installed.

+ActivityConstraints.patchUnconfigureBackup = This feature is a patch and cannot be directly disabled. Use 'Revert' to restore \

+configuration "{0}" in Saved Configurations.

 ActivityConstraints.patchMissingTarget = Older version of feature "{0} ({1})" must be present for a patch to be applied.

 ActivityConstraints.timeline = Cannot revert to "{0}" because it is not compatible with the current configuration.

 

diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/ActivityConstraints.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/ActivityConstraints.java
index 1006df7..43f26cd 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/ActivityConstraints.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/ActivityConstraints.java
@@ -41,6 +41,8 @@
 		"ActivityConstraints.patchRegression";
 	private static final String KEY_PATCH_UNCONFIGURE = 
 		"ActivityConstraints.patchUnconfigure";
+	private static final String KEY_PATCH_UNCONFIGURE_BACKUP = 
+		"ActivityConstraints.patchUnconfigureBackup";
 	private static final String KEY_PATCH_MISSING_TARGET = 
 		"ActivityConstraints.patchMissingTarget";
 	private static final String KEY_OPTIONAL_CHILD =
@@ -171,7 +173,12 @@
 		ArrayList status) {
 		try {
 			if (UpdateUIPlugin.isPatch(feature)) {
-				String msg = UpdateUIPlugin.getResourceString(KEY_PATCH_UNCONFIGURE);
+				IInstallConfiguration backup = UpdateUIPlugin.getBackupConfigurationFor(feature);
+				String msg;
+				if (backup!=null)
+					msg = UpdateUIPlugin.getFormattedMessage(KEY_PATCH_UNCONFIGURE_BACKUP, backup.getLabel());
+				else
+					msg = UpdateUIPlugin.getResourceString(KEY_PATCH_UNCONFIGURE);
 				status.add(createStatus(feature, msg));
 				return;
 			}
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/DetailsForm.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/DetailsForm.java
index 42da30e..0818152 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/DetailsForm.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/DetailsForm.java
@@ -85,6 +85,8 @@
 	private static final String KEY_MISSING_ABORT = "FeaturePage.missing.abort";
 	private static final String KEY_SEARCH_OBJECT_NAME =
 		"FeaturePage.missing.searchObjectName";
+	private static final String KEY_OPTIONAL_INSTALL_MESSAGE = "FeaturePage.optionalInstall.message";
+	private static final String KEY_OPTIONAL_INSTALL_TITLE = "FeaturePage.optionalInstall.title";
 	//	
 
 	private Label imageLabel;
@@ -872,12 +874,12 @@
 			executeJob(job);
 		}
 		else {
-			String message = "Feature cannot be found using "+siteURL;
+			String message = UpdateUIPlugin.getFormattedMessage(KEY_OPTIONAL_INSTALL_MESSAGE, siteURL.toString());
 			status = new Status(IStatus.ERROR, UpdateUIPlugin.PLUGIN_ID, IStatus.OK, message, null);
 		}
 		if (status!=null) {
 			// Show error dialog
-			ErrorDialog.openError(getControl().getShell(), "Optional Install", null, status);
+			ErrorDialog.openError(getControl().getShell(), UpdateUIPlugin.getResourceString(KEY_OPTIONAL_INSTALL_TITLE), null, status);
 		}
 	}
 	
@@ -935,6 +937,24 @@
 	}
 	
 	private void unconfigurePatch(IFeature feature) {
+		IInstallConfiguration config = UpdateUIPlugin.getBackupConfigurationFor(feature);
+		if (config==null) {
+			String message = "This feature is a patch and cannot be directly disabled. Locate a configuration before it was installed and revert to it instead.";
+			MessageDialog.openError(getControl().getShell(), "Disable Feature", message);
+			return;
+		}
+		try {
+			ILocalSite localSite = SiteManager.getLocalSite();
+			boolean success = RevertSection.performRevert(config, false, false);
+			if (success) {
+				localSite.removeFromPreservedConfigurations(config);
+				localSite.save();
+				UpdateUIPlugin.informRestartNeeded();
+			}
+		}
+		catch (CoreException e) {
+			UpdateUIPlugin.logException(e);
+		}
 	}
 
 	private void doButtonSelected() {
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/RevertSection.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/RevertSection.java
index f8c29ce..4a9a29d 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/RevertSection.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/forms/RevertSection.java
@@ -21,24 +21,15 @@
 
 public class RevertSection extends UpdateSection {
 	// NL keys
-	private static final String KEY_TITLE =
-		"InstallConfigurationPage.RevertSection.title"; //$NON-NLS-1$
-	private static final String KEY_DESC =
-		"InstallConfigurationPage.RevertSection.desc"; //$NON-NLS-1$
-	private static final String KEY_CURRENT_TEXT =
-		"InstallConfigurationPage.RevertSection.currentText"; //$NON-NLS-1$
-	private static final String KEY_REVERT_TEXT =
-		"InstallConfigurationPage.RevertSection.revertText"; //$NON-NLS-1$
-	private static final String KEY_REVERT_BUTTON =
-		"InstallConfigurationPage.RevertSection.revertButton"; //$NON-NLS-1$
-	private static final String KEY_RESTORE_TEXT =
-		"InstallConfigurationPage.RevertSection.restoreText"; //$NON-NLS-1$
-	private static final String KEY_RESTORE_BUTTON =
-		"InstallConfigurationPage.RevertSection.restoreButton"; //$NON-NLS-1$
-	private static final String KEY_DIALOG_TITLE =
-		"InstallConfigurationPage.RevertSection.dialog.title"; //$NON-NLS-1$
-	private static final String KEY_DIALOG_MESSAGE =
-		"InstallConfigurationPage.RevertSection.dialog.message"; //$NON-NLS-1$
+	private static final String KEY_TITLE = "InstallConfigurationPage.RevertSection.title"; //$NON-NLS-1$
+	private static final String KEY_DESC = "InstallConfigurationPage.RevertSection.desc"; //$NON-NLS-1$
+	private static final String KEY_CURRENT_TEXT = "InstallConfigurationPage.RevertSection.currentText"; //$NON-NLS-1$
+	private static final String KEY_REVERT_TEXT = "InstallConfigurationPage.RevertSection.revertText"; //$NON-NLS-1$
+	private static final String KEY_REVERT_BUTTON = "InstallConfigurationPage.RevertSection.revertButton"; //$NON-NLS-1$
+	private static final String KEY_RESTORE_TEXT = "InstallConfigurationPage.RevertSection.restoreText"; //$NON-NLS-1$
+	private static final String KEY_RESTORE_BUTTON = "InstallConfigurationPage.RevertSection.restoreButton"; //$NON-NLS-1$
+	private static final String KEY_DIALOG_TITLE = "InstallConfigurationPage.RevertSection.dialog.title"; //$NON-NLS-1$
+	private static final String KEY_DIALOG_MESSAGE = "InstallConfigurationPage.RevertSection.dialog.message"; //$NON-NLS-1$
 
 	private Composite container;
 	private FormWidgetFactory factory;
@@ -136,14 +127,20 @@
 	}
 
 	public static void performRevert(final IInstallConfiguration target) {
-		// ask the user to confirm and bail if canceled
-		String title = UpdateUIPlugin.getActivePage().getLabel();
-		if (!MessageDialog.openConfirm(
-				UpdateUIPlugin.getActiveWorkbenchShell(),
-				title,
-				UpdateUIPlugin.getResourceString("InstallConfigurationPage.RevertSection.confirm.message"))) //$NON-NLS-1$
-			return;
-				
+		performRevert(target, true, true);
+	}
+
+	public static boolean performRevert(
+		final IInstallConfiguration target,
+		boolean confirm, 
+		final boolean restart) {
+		if (confirm) {
+			// ask the user to confirm and bail if canceled
+			String title = UpdateUIPlugin.getActivePage().getLabel();
+			if (!MessageDialog.openConfirm(UpdateUIPlugin.getActiveWorkbenchShell(), title, UpdateUIPlugin.getResourceString("InstallConfigurationPage.RevertSection.confirm.message"))) //$NON-NLS-1$
+				return false;
+		}
+
 		// make sure we can actually do the revert
 		IStatus status = ActivityConstraints.validatePendingRevert(target);
 		if (status != null) {
@@ -152,10 +149,12 @@
 				null,
 				null,
 				status);
-			return;
+			return false;
 		}
 
 		// ok to perform the operation
+		final boolean [] result = new boolean[1];
+		result[0] = false;
 		IRunnableWithProgress operation = new IRunnableWithProgress() {
 
 			public void run(IProgressMonitor monitor) {
@@ -169,7 +168,8 @@
 					UpdateUIPlugin.logException(e);
 				} finally {
 					monitor.done();
-					if (success)
+					result[0] = success;
+					if (success && restart)
 						UpdateUIPlugin.informRestartNeeded();
 				}
 			}
@@ -183,6 +183,7 @@
 			UpdateUIPlugin.logException(e);
 		} catch (InterruptedException e) {
 		}
+		return result[0];
 	}
 
 	private static void saveLocalSite() throws CoreException {
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/DuplicateConflictsDialog.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/DuplicateConflictsDialog.java
index 67b8aa9..5b3a0d4 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/DuplicateConflictsDialog.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/DuplicateConflictsDialog.java
@@ -1,38 +1,20 @@
 package org.eclipse.update.internal.ui.wizards;
 
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.*;
 
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.*;
 import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.viewers.*;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.update.configuration.IConfiguredSite;
-import org.eclipse.update.configuration.IInstallConfiguration;
-import org.eclipse.update.configuration.ILocalSite;
-import org.eclipse.update.core.IFeature;
-import org.eclipse.update.core.IFeatureReference;
-import org.eclipse.update.core.SiteManager;
-import org.eclipse.update.core.VersionedIdentifier;
-import org.eclipse.update.internal.ui.UpdateUIPlugin;
-import org.eclipse.update.internal.ui.UpdateUIPluginImages;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.update.configuration.*;
+import org.eclipse.update.core.*;
+import org.eclipse.update.internal.ui.*;
 import org.eclipse.update.internal.ui.model.PendingChange;
-import org.eclipse.update.internal.ui.parts.DefaultContentProvider;
-import org.eclipse.update.internal.ui.parts.OverlayIcon;
+import org.eclipse.update.internal.ui.parts.*;
 
 /*
  * (c) Copyright IBM Corp. 2000, 2001.
@@ -258,7 +240,7 @@
 			IFeatureReference[] refs = csite.getConfiguredFeatures();
 			for (int j = 0; j < refs.length; j++) {
 				try {
-					addEntry(refs[j].getFeature(), null, table);
+					addEntry(refs[j].getFeature(), csite, table);
 				} catch (CoreException e) {
 					// don't let one bad feature stop the loop
 				}
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/InstallWizard.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/InstallWizard.java
index 7c48f79..2736697 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/InstallWizard.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/InstallWizard.java
@@ -15,6 +15,7 @@
 import org.eclipse.update.configuration.*;

 import org.eclipse.update.core.*;

 import org.eclipse.update.core.model.InstallAbortedException;

+import org.eclipse.update.internal.ui.*;

 import org.eclipse.update.internal.ui.UpdateUIPlugin;

 import org.eclipse.update.internal.ui.UpdateUIPluginImages;

 import org.eclipse.update.internal.ui.model.PendingChange;

@@ -143,7 +144,6 @@
 	public static void makeConfigurationCurrent(IInstallConfiguration config, PendingChange job)

 		throws CoreException {

 		ILocalSite localSite = SiteManager.getLocalSite();

-		/*

 		if (job!=null && job.getJobType()==PendingChange.INSTALL) {

 			if (UpdateUIPlugin.isPatch(job.getFeature())) {

 				// Installing a patch - preserve the current configuration

@@ -157,7 +157,6 @@
 				model.fireObjectChanged(savedConfig, null);

 			}

 		}

-		*/

 		localSite.addConfiguration(config);

 	}

 

@@ -297,7 +296,10 @@
 		throws CoreException {

 		IConfiguredSite site = findConfigSite(feature, config);

 		if (site != null) {

-			return site.unconfigure(feature);

+			PatchCleaner cleaner = new PatchCleaner(site, feature);

+			boolean result = site.unconfigure(feature);

+			cleaner.dispose();

+			return result;

 		}

 		return false;

 	}

diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/NewUpdatesWizard.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/NewUpdatesWizard.java
index 757fbaa..1d15c11 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/NewUpdatesWizard.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/NewUpdatesWizard.java
@@ -16,6 +16,7 @@
 import org.eclipse.update.configuration.IInstallConfiguration;
 import org.eclipse.update.core.*;
 import org.eclipse.update.core.model.InstallAbortedException;
+import org.eclipse.update.internal.ui.*;
 import org.eclipse.update.internal.ui.UpdateUIPlugin;
 import org.eclipse.update.internal.ui.UpdateUIPluginImages;
 import org.eclipse.update.internal.ui.forms.ActivityConstraints;
@@ -272,7 +273,10 @@
 	private boolean unconfigure(IFeature feature) throws CoreException {
 		IConfiguredSite site = findConfigSite(feature, config);
 		if (site != null) {
-			return site.unconfigure(feature);
+			PatchCleaner cleaner = new PatchCleaner(site, feature);
+			boolean result = site.unconfigure(feature);
+			cleaner.dispose();
+			return result;
 		}
 		return false;
 	}