*** empty log message ***
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/UpdateManagerUtils.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/UpdateManagerUtils.java
index a533d04..9370082 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/UpdateManagerUtils.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/UpdateManagerUtils.java
@@ -421,7 +421,7 @@
 					children = possibleParentFeature.getIncludedFeatureReferences();

 					for (int j = 0; j < children.length; j++) {

 						try {

-							compareFeature = children[j].getFeature();

+							compareFeature = children[j].getFeature(true,null); //BUG 25796

 						} catch (CoreException e) {

 							UpdateManagerPlugin.warn("", e);

 						};

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 43f26cd..0ecfb84 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
@@ -615,8 +615,11 @@
 			if (!found) {
 				// All the features carried in a patch must
 				// already be present, unless this feature
-				// is a patch itself
-				if (!isPatch(ifeature)) {
+				// is a patch itself.
+				//
+				// 30849: optional feature does not need
+				// to be present.
+				if (!isPatch(ifeature) && iref.isOptional()==false) {
 					String msg = UpdateUIPlugin.getFormattedMessage(KEY_PATCH_MISSING_TARGET,
 							new String[] { ifeature.getLabel(), version.toString() });
 					status.add(createStatus(feature, msg));
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/FeatureHierarchyElement.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/FeatureHierarchyElement.java
index b44bb5b..50b255e 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/FeatureHierarchyElement.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/FeatureHierarchyElement.java
@@ -173,15 +173,15 @@
 	 * Computes children by linking matching features from the
 	 * old feature's and new feature's hierarchy.
 	 */
-	public Object[] getChildren(boolean update) {
-		computeChildren(update);
+	public Object[] getChildren(boolean update, boolean patch, IInstallConfiguration config) {
+		computeChildren(update, patch, config);
 		return children.toArray();
 	}
 	/**
 	 * Computes children of this node.
 	 * @return true if some of the children are optional, false otherwise.
 	 */
-	public void computeChildren(boolean update) {
+	public void computeChildren(boolean update, boolean patch, IInstallConfiguration config) {
 		if (children == null) {
 			children = new ArrayList();
 			try {
@@ -190,7 +190,7 @@
 				newFeature = newFeatureRef.getFeature();
 				if (oldFeatureRef != null)
 					oldFeature = oldFeatureRef.getFeature();
-				optionalChildren = computeElements(oldFeature, newFeature, update, children);
+				optionalChildren = computeElements(oldFeature, newFeature, update, patch, config, children);
 			} catch (CoreException e) {
 			}
 		}
@@ -204,7 +204,7 @@
 	/**
 	 * Adds checked optional features to the provided set.
 	 */
-	public void addCheckedOptionalFeatures(boolean update, Set set) {
+	public void addCheckedOptionalFeatures(boolean update, boolean patch, IInstallConfiguration config, Set set) {
 		if (isOptional() && isChecked()) {
 			// Do not add checked optional features
 			// if this is an update case but
@@ -213,10 +213,10 @@
 			if (!update || !isFalseUpdate())
 			set.add(newFeatureRef);
 		}
-		Object[] list = getChildren(update);
+		Object[] list = getChildren(update, patch, config);
 		for (int i = 0; i < list.length; i++) {
 			FeatureHierarchyElement element = (FeatureHierarchyElement) list[i];
-			element.addCheckedOptionalFeatures(update, set);
+			element.addCheckedOptionalFeatures(update, patch, config, set);
 		}
 	}
 
@@ -230,6 +230,8 @@
 		IFeature oldFeature,
 		IFeature newFeature,
 		boolean update,
+		boolean patch,
+		IInstallConfiguration config,
 		ArrayList list) {
 		Object[] oldChildren = null;
 		Object[] newChildren = getIncludedFeatures(newFeature);
@@ -261,10 +263,18 @@
 						}
 					}
 				}
+				else if (patch) {
+					// 30849 - find the old reference in the
+					// configuration.
+					if (!UpdateUIPlugin.isPatch(newFeature)) {
+						oldRef = findPatchedReference(newRef, config);
+					}
+				}
 				// test if the old optional feature exists
-				if (oldRef!=null && oldRef.isOptional()) {
+				if (oldRef!=null && (oldRef.isOptional() || patch)) {
 					try {
-						oldRef.getFeature();
+						IFeature f = oldRef.getFeature();
+						if (f==null) oldRef = null;
 					}
 					catch (CoreException e) {
 						// missing
@@ -276,7 +286,7 @@
 				// If this is an update (old feature exists), 
 				// only check the new optional feature if the old exists.
 				// Otherwise, always check.
-				if (newRef.isOptional() && update) {
+				if (newRef.isOptional() && (update || patch)) {
 					element.setChecked(oldRef != null);
 					if (oldRef == null) {
 						// Does not have an old reference,
@@ -293,7 +303,7 @@
 				} else
 					element.setChecked(true);
 				list.add(element);
-				element.computeChildren(update);
+				element.computeChildren(update, patch, config);
 				if (element.isOptional() || element.hasOptionalChildren())
 					optionalChildren=true;
 			}
@@ -301,6 +311,23 @@
 		}
 		return optionalChildren;
 	}
+
+	private static IFeatureReference findPatchedReference(IFeatureReference newRef, IInstallConfiguration config) throws CoreException {
+		VersionedIdentifier vid = newRef.getVersionedIdentifier();
+		IConfiguredSite [] csites = config.getConfiguredSites();
+		for (int i=0; i<csites.length; i++) {
+			IConfiguredSite csite = csites[i];
+			IFeatureReference [] refs = csite.getConfiguredFeatures();
+			for (int j=0; j<refs.length; j++) {
+				IFeatureReference ref = refs[j];
+				VersionedIdentifier refVid = ref.getVersionedIdentifier();
+				if (vid.getIdentifier().equals(refVid.getIdentifier()))
+					return ref;
+			}
+		}
+		return null;
+	}
+	
 	private static boolean hasOlderVersion(IFeatureReference newRef) {
 		try {
 			IFeature feature = newRef.getFeature();
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 2736697..631a4a2 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
@@ -32,6 +32,7 @@
 	private PendingChange job;

 	private boolean successfulInstall = false;

 	private IInstallConfiguration config;

+	private boolean patch;

 

 	public InstallWizard(PendingChange job) {

 		setDialogSettings(UpdateUIPlugin.getDefault().getDialogSettings());

@@ -39,6 +40,8 @@
 		setForcePreviousAndNextButtons(true);

 		setNeedsProgressMonitor(true);

 		this.job = job;

+		IFeature feature = job.getFeature();

+		patch = UpdateUIPlugin.isPatch(feature);

 	}

 

 	public boolean isSuccessfulInstall() {

@@ -206,8 +209,10 @@
 					monitor);

 			IFeature oldFeature = job.getOldFeature();

 			if (oldFeature != null && !job.isOptionalDelta()) {

-				if (optionalElements != null)

-					preserveOptionalState(config, targetSite, optionalElements);

+				if (optionalElements != null) {

+					boolean patch = UpdateUIPlugin.isPatch(feature);

+					preserveOptionalState(config, targetSite, patch, optionalElements);

+				}

 				boolean oldSuccess = unconfigure(config, oldFeature);

 				if (!oldSuccess) {

 					if (!isNestedChild(oldFeature))

@@ -366,12 +371,13 @@
 	static void preserveOptionalState(

 		IInstallConfiguration config,

 		IConfiguredSite targetSite,

+		boolean patch,

 		Object[] optionalElements) {

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

 			FeatureHierarchyElement fe =

 				(FeatureHierarchyElement) optionalElements[i];

-			Object[] children = fe.getChildren(true);

-			preserveOptionalState(config, targetSite, children);

+			Object[] children = fe.getChildren(true, patch, config);

+			preserveOptionalState(config, targetSite, patch, children);

 			if (!fe.isEnabled(config)) {

 				IFeature newFeature = fe.getFeature();

 				try {

@@ -394,7 +400,16 @@
 		IFeatureReference[] included = feature.getIncludedFeatureReferences();

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

 			IFeatureReference iref = included[i];

-			IFeature ifeature = iref.getFeature();

+			IFeature ifeature;

+			

+			try {

+				ifeature = iref.getFeature();

+			}

+			catch (CoreException e) {

+				if (iref.isOptional())

+					continue;

+				throw e;

+			}

 			// find other features and unconfigure

 			String id = iref.getVersionedIdentifier().getIdentifier();

 			IFeature[] sameIds =

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 1d15c11..ac5e7f9 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
@@ -213,6 +213,8 @@
 			oldFeature,
 			feature,
 			oldFeature != null,
+			false,
+			config,
 			optionalElements);
 		if (hasOptionalFeatures)
 			optionalFeatures = computeOptionalFeatures(optionalElements, oldFeature!=null);
@@ -224,7 +226,7 @@
 			targetSite.install(feature, getVerificationListener(), monitor);
 		if (!reinstall) {
 			if (optionalFeatures!=null) {
-				InstallWizard.preserveOptionalState(config, targetSite, optionalElements.toArray());
+				InstallWizard.preserveOptionalState(config, targetSite, false, optionalElements.toArray());
 			}
 			unconfigure(oldFeature);
 		}
@@ -239,6 +241,8 @@
 				(FeatureHierarchyElement) elements.get(i);
 			element.addCheckedOptionalFeatures(
 				update,
+				false,
+				config,
 				set);
 		}
 		return (IFeatureReference[]) set.toArray(
diff --git a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/OptionalFeaturesPage.java b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/OptionalFeaturesPage.java
index 0bd9abe..c1c7ddd 100644
--- a/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/OptionalFeaturesPage.java
+++ b/update/org.eclipse.update.ui/src/org/eclipse/update/internal/ui/wizards/OptionalFeaturesPage.java
@@ -34,6 +34,7 @@
 	private PendingChange pendingChange;
 	private Image featureImage;
 	private Object[] elements;
+	private boolean patch;
 
 	class TreeContentProvider
 		extends DefaultContentProvider
@@ -42,7 +43,7 @@
 		public Object[] getChildren(Object parent) {
 			if (parent instanceof FeatureHierarchyElement) {
 				FeatureHierarchyElement fe = (FeatureHierarchyElement) parent;
-				return fe.getChildren(pendingChange.getOldFeature() != null);
+				return fe.getChildren(pendingChange.getOldFeature() != null, patch, config);
 			}
 			return new Object[0];
 		}
@@ -89,6 +90,7 @@
 		this.config = config;
 		this.pendingChange = pendingChange;
 		featureImage = UpdateUIPluginImages.DESC_FEATURE_OBJ.createImage();
+		patch = UpdateUIPlugin.isPatch(pendingChange.getFeature());
 	}
 
 	public void dispose() {
@@ -191,6 +193,8 @@
 			oldFeature,
 			newFeature,
 			oldFeature != null,
+			patch,
+			config,
 			list);
 		elements = list.toArray();
 	}
@@ -217,7 +221,7 @@
 			if (!element.isEditable())
 				grayed.add(element);
 			Object[] children =
-				element.getChildren(pendingChange.getOldFeature() != null);
+				element.getChildren(pendingChange.getOldFeature() != null, patch, config);
 			initializeStates(children, checked, grayed);
 		}
 	}
@@ -252,7 +256,7 @@
 			}
 		}
 		Object[] included =
-			ref.getChildren(pendingChange.getOldFeature() != null);
+			ref.getChildren(pendingChange.getOldFeature() != null, patch, config);
 		for (int i = 0; i < included.length; i++) {
 			FeatureHierarchyElement fe = (FeatureHierarchyElement) included[i];
 			selectAll(fe, selected, value);
@@ -282,6 +286,8 @@
 				(FeatureHierarchyElement) elements[i];
 			element.addCheckedOptionalFeatures(
 				pendingChange.getOldFeature() != null,
+				patch,
+				config,
 				set);
 		}
 		return (IFeatureReference[]) set.toArray(