*** empty log message ***
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 3353a6f..59aafa6 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
@@ -252,6 +252,26 @@
}
return (IFeature[]) features.toArray(new IFeature[features.size()]);
}
+
+ public static boolean isPatch(
+ IFeature target,
+ IFeature candidate) {
+ VersionedIdentifier vid = target.getVersionedIdentifier();
+ IImport[] imports = candidate.getImports();
+ IImport reference = null;
+ for (int i = 0; i < imports.length; i++) {
+ IImport iimport = imports[i];
+ if (iimport.isPatch()) {
+ VersionedIdentifier ivid = iimport.getVersionedIdentifier();
+ if (vid.equals(ivid)) {
+ // Bingo.
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Gets the database.
* @return Returns a AuthorizationDatabase
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 1a7b122..fbfac0e 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
@@ -111,11 +111,13 @@
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.
ActivityConstraints.primary = Resulting configuration does not contain the primary feature.
-ActivityConstraints.prereq = Feature requires plug-in "{0}".
-ActivityConstraints.prereqPerfect = Feature requires plug-in "{0} ({1})".
-ActivityConstraints.prereqEquivalent = Feature requires plug-in "{0} ({1})", or equivalent.
-ActivityConstraints.prereqCompatible = Feature requires plug-in "{0} ({1})", or compatible.
-ActivityConstraints.prereqGreaterOrEqual = Feature requires plug-in "{0} ({1})", or later version.
+ActivityConstaints.prereq.plugin = plug-in
+ActivityConstaints.prereq.feature = feature
+ActivityConstraints.prereq = Feature requires {0} "{1}".
+ActivityConstraints.prereqPerfect = Feature requires {0} "{1} ({2})".
+ActivityConstraints.prereqEquivalent = Feature requires {0} "{1} ({2})", or equivalent.
+ActivityConstraints.prereqCompatible = Feature requires {0} "{1} ({2})", or compatible.
+ActivityConstraints.prereqGreaterOrEqual = Feature requires {0} "{1} ({2})", or later version.
ActivityConstraints.os = Feature operating system does not match current environment.
ActivityConstraints.ws = Feature windowing system does not match current environment.
ActivityConstraints.arch = Feature platform architecture does not match current environment.
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 7da4fe8..4d16330 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
@@ -25,6 +25,10 @@
private static final String KEY_WS = "ActivityConstraints.ws";
private static final String KEY_ARCH = "ActivityConstraints.arch";
private static final String KEY_PREREQ = "ActivityConstraints.prereq";
+ private static final String KEY_PREREQ_PLUGIN =
+ "ActivityConstaints.prereq.plugin";
+ private static final String KEY_PREREQ_FEATURE =
+ "ActivityConstaints.prereq.feature";
private static final String KEY_PREREQ_PERFECT =
"ActivityConstraints.prereqPerfect";
private static final String KEY_PREREQ_EQUIVALENT =
@@ -33,7 +37,7 @@
"ActivityConstraints.prereqCompatible";
private static final String KEY_PREREQ_GREATER =
"ActivityConstraints.prereqGreaterOrEqual";
- private static final String KEY_OPTIONAL_CHILD =
+ private static final String KEY_OPTIONAL_CHILD =
"ActivityConstraints.optionalChild";
private static final String KEY_CYCLE = "ActivityConstraints.cycle";
private static final String KEY_CONFLICT = "ActivityConstraints.conflict";
@@ -192,6 +196,8 @@
ArrayList status) {
try {
ArrayList features = computeFeatures();
+ if (oldFeature == null)
+ checkPatch(newFeature, features, status);
features =
computeFeaturesAfterOperation(features, newFeature, oldFeature);
checkConstraints(features, status);
@@ -290,7 +296,8 @@
/*
* Compute a list of configured features
*/
- private static ArrayList computeFeatures(boolean configuredOnly) throws CoreException {
+ private static ArrayList computeFeatures(boolean configuredOnly)
+ throws CoreException {
ArrayList features = new ArrayList();
ILocalSite localSite = SiteManager.getLocalSite();
IInstallConfiguration config = localSite.getCurrentConfiguration();
@@ -298,9 +305,9 @@
for (int i = 0; i < csites.length; i++) {
IConfiguredSite csite = csites[i];
-
+
IFeatureReference[] crefs;
-
+
if (configuredOnly)
crefs = csite.getConfiguredFeatures();
else
@@ -383,6 +390,11 @@
null,
true /* tolerate missing children */
);
+ if (remove!=null) {
+ // Patches to features are removed together with
+ // those features. Include them in the list.
+ contributePatchesFor(remove, features, removeTree);
+ }
if (add != null)
features.addAll(addTree);
@@ -393,6 +405,21 @@
return features;
}
+ private static void contributePatchesFor(
+ IFeature feature,
+ ArrayList features,
+ ArrayList result)
+ throws CoreException {
+ for (int i = 0; i < features.size(); i++) {
+ IFeature candidate = (IFeature) features.get(i);
+ if (UpdateUIPlugin.isPatch(feature, candidate)) {
+ ArrayList removeTree =
+ computeFeatureSubtree(candidate, null, null, true);
+ result.addAll(removeTree);
+ }
+ }
+ }
+
/*
* Compute a list of features that will be configured after performing the revert
*/
@@ -501,6 +528,68 @@
}
/*
+ *
+ */
+ private static void checkPatch(
+ IFeature feature,
+ ArrayList features,
+ ArrayList status)
+ throws CoreException {
+ IImport[] imports = feature.getImports();
+ for (int i = 0; i < imports.length; i++) {
+ IImport iimport = imports[i];
+ if (iimport.isPatch()) {
+ // A patch - check unique
+ checkUnique(feature, features, status);
+ return;
+ }
+ }
+ }
+
+ /*
+ *
+ */
+ private static void checkUnique(
+ IFeature feature,
+ ArrayList features,
+ ArrayList status)
+ throws CoreException {
+ if (features == null)
+ return;
+ IFeatureReference[] irefs = feature.getIncludedFeatureReferences();
+ for (int i = 0; i < irefs.length; i++) {
+ IFeatureReference iref = irefs[i];
+ IFeature ifeature = iref.getFeature();
+ VersionedIdentifier vid = ifeature.getVersionedIdentifier();
+ String id = vid.getIdentifier();
+ PluginVersionIdentifier version = vid.getVersion();
+ for (int j = 0; j < features.size(); j++) {
+ IFeature candidate = (IFeature) features.get(j);
+ VersionedIdentifier cvid = candidate.getVersionedIdentifier();
+ String cid = cvid.getIdentifier();
+ PluginVersionIdentifier cversion = cvid.getVersion();
+ if (cid.equals(id)) {
+ // The same identifier - this one will
+ // be unconfigured. Check if it is lower,
+ // otherwise flag.
+ if (!version.isGreaterThan(cversion)) {
+ // Don't allow this.
+ String msg =
+ "Included feature \""
+ + ifeature.getLabel()
+ + "("
+ + version.toString()
+ + ")\" is older than the currently active feature.";
+ status.add(createStatus(feature, msg));
+
+ }
+ }
+ }
+ checkUnique(ifeature, features, status);
+ }
+ }
+
+ /*
* validate constraints
*/
private static void checkConstraints(ArrayList features, ArrayList status)
@@ -635,10 +724,12 @@
for (int j = 0; j < imports.length; j++) {
IImport iimport = imports[j];
- // for each import determine plugin, version, match we need
+ // for each import determine plugin or feature, version, match we need
VersionedIdentifier iid = iimport.getVersionedIdentifier();
String id = iid.getIdentifier();
PluginVersionIdentifier version = iid.getVersion();
+ boolean featurePrereq =
+ iimport.getKind() == IImport.KIND_FEATURE;
boolean ignoreVersion =
version.getMajorComponent() == 0
&& version.getMinorComponent() == 0
@@ -648,65 +739,99 @@
rule = IImport.RULE_COMPATIBLE;
boolean found = false;
- for (int k = 0; k < plugins.size(); k++) {
- // see if we have a plugin that matches
- IPluginEntry plugin = (IPluginEntry) plugins.get(k);
- VersionedIdentifier pid = plugin.getVersionedIdentifier();
- PluginVersionIdentifier pversion = pid.getVersion();
- if (id.equals(pid.getIdentifier())) {
+
+ ArrayList candidates;
+
+ if (featurePrereq)
+ candidates = features;
+ else
+ candidates = plugins;
+ for (int k = 0; k < candidates.size(); k++) {
+ VersionedIdentifier cid;
+ if (featurePrereq) {
+ // the candidate is a feature
+ IFeature candidate = (IFeature) candidates.get(k);
+ // skip self
+ if (feature.equals(candidate))
+ continue;
+ cid = candidate.getVersionedIdentifier();
+ } else {
+ // the candidate is a plug-in
+ IPluginEntry plugin = (IPluginEntry) candidates.get(k);
+ cid = plugin.getVersionedIdentifier();
+ }
+ PluginVersionIdentifier cversion = cid.getVersion();
+ if (id.equals(cid.getIdentifier())) {
// have a candidate
if (ignoreVersion)
found = true;
else if (
rule == IImport.RULE_PERFECT
- && pversion.isPerfect(version))
+ && cversion.isPerfect(version))
found = true;
else if (
rule == IImport.RULE_EQUIVALENT
- && pversion.isEquivalentTo(version))
+ && cversion.isEquivalentTo(version))
found = true;
else if (
rule == IImport.RULE_COMPATIBLE
- && pversion.isCompatibleWith(version))
+ && cversion.isCompatibleWith(version))
found = true;
else if (
rule == IImport.RULE_GREATER_OR_EQUAL
- && pversion.isGreaterOrEqualTo(version))
+ && cversion.isGreaterOrEqualTo(version))
found = true;
}
if (found)
break;
}
+
if (!found) {
// report status
+ String target =
+ featurePrereq
+ ? UpdateUIPlugin.getResourceString(
+ KEY_PREREQ_FEATURE)
+ : UpdateUIPlugin.getResourceString(KEY_PREREQ_PLUGIN);
String msg =
UpdateUIPlugin.getFormattedMessage(
KEY_PREREQ,
- new String[] { id });
+ new String[] { target, id });
if (!ignoreVersion) {
if (rule == IImport.RULE_PERFECT)
msg =
UpdateUIPlugin.getFormattedMessage(
KEY_PREREQ_PERFECT,
- new String[] { id, version.toString()});
+ new String[] {
+ target,
+ id,
+ version.toString()});
else if (rule == IImport.RULE_EQUIVALENT)
msg =
UpdateUIPlugin.getFormattedMessage(
KEY_PREREQ_EQUIVALENT,
- new String[] { id, version.toString()});
+ new String[] {
+ target,
+ id,
+ version.toString()});
else if (rule == IImport.RULE_COMPATIBLE)
msg =
UpdateUIPlugin.getFormattedMessage(
KEY_PREREQ_COMPATIBLE,
- new String[] { id, version.toString()});
+ new String[] {
+ target,
+ id,
+ version.toString()});
else if (rule == IImport.RULE_GREATER_OR_EQUAL)
msg =
UpdateUIPlugin.getFormattedMessage(
KEY_PREREQ_GREATER,
- new String[] { id, version.toString()});
+ new String[] {
+ target,
+ id,
+ version.toString()});
}
-
status.add(createStatus(feature, msg));
}
}
@@ -734,28 +859,30 @@
}
}
}
-
+
/*
* Verify that a parent of an optional child is configured
* before we allow the child to be configured as well
*/
-
- private static void checkOptionalChildConfiguring(IFeature feature, ArrayList status) throws CoreException {
+
+ private static void checkOptionalChildConfiguring(
+ IFeature feature,
+ ArrayList status)
+ throws CoreException {
ILocalSite localSite = SiteManager.getLocalSite();
IInstallConfiguration config = localSite.getCurrentConfiguration();
IConfiguredSite[] csites = config.getConfiguredSites();
- boolean included=false;
+ boolean included = false;
for (int i = 0; i < csites.length; i++) {
IConfiguredSite csite = csites[i];
IFeatureReference[] crefs = csite.getSite().getFeatureReferences();
for (int j = 0; j < crefs.length; j++) {
IFeatureReference cref = crefs[j];
- IFeature cfeature=null;
+ IFeature cfeature = null;
try {
cfeature = cref.getFeature();
- }
- catch (CoreException e) {
+ } catch (CoreException e) {
// Ignore missing optional feature.
if (cref.isOptional())
continue;
@@ -764,7 +891,7 @@
}
if (isParent(cfeature, feature, true)) {
// Included in at least one feature as optional
- included=true;
+ included = true;
if (csite.isConfigured(cfeature)) {
// At least one feature parent
// is enabled - it is OK to
@@ -779,21 +906,23 @@
// no parent is currently configured.
String msg = UpdateUIPlugin.getResourceString(KEY_OPTIONAL_CHILD);
status.add(createStatus(feature, msg));
- }
- else {
+ } else {
//feature is root - can be configured
}
}
-
- private static boolean isParent(IFeature candidate, IFeature feature, boolean optionalOnly) throws CoreException {
- IFeatureReference [] refs = candidate.getIncludedFeatureReferences();
- for (int i=0; i<refs.length; i++) {
+
+ private static boolean isParent(
+ IFeature candidate,
+ IFeature feature,
+ boolean optionalOnly)
+ throws CoreException {
+ IFeatureReference[] refs = candidate.getIncludedFeatureReferences();
+ for (int i = 0; i < refs.length; i++) {
IFeatureReference child = refs[i];
VersionedIdentifier cvid;
try {
cvid = child.getVersionedIdentifier();
- }
- catch (CoreException e) {
+ } catch (CoreException e) {
// Ignore missing optional children
if (child.isOptional())
continue;
@@ -803,7 +932,7 @@
if (feature.getVersionedIdentifier().equals(cvid)) {
// included; return true if optionality is not
// important or it is and the inclusion is optional
- return optionalOnly==false || child.isOptional();
+ return optionalOnly == false || child.isOptional();
}
}
return false;
@@ -847,12 +976,13 @@
fullMessage,
null);
}
-
+
private static ArrayList createList(String commaSeparatedList) {
ArrayList list = new ArrayList();
if (commaSeparatedList != null) {
- StringTokenizer t = new StringTokenizer(commaSeparatedList.trim(), ",");
- while(t.hasMoreTokens()) {
+ StringTokenizer t =
+ new StringTokenizer(commaSeparatedList.trim(), ",");
+ while (t.hasMoreTokens()) {
String token = t.nextToken().trim();
if (!token.equals(""))
list.add(token);
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 cff9f9c..a288352 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
@@ -185,6 +185,9 @@
throwError(UpdateUIPlugin.getResourceString(KEY_OLD));
}
}
+ if (oldFeature == null) {
+ ensureUnique(config, feature, targetSite);
+ }
} else if (job.getJobType() == PendingChange.CONFIGURE) {
configure(job.getFeature());
} else if (job.getJobType() == PendingChange.UNCONFIGURE) {
@@ -197,6 +200,35 @@
model.addPendingChange(job);
}
+ static void ensureUnique(
+ IInstallConfiguration config,
+ IFeature feature,
+ IConfiguredSite targetSite)
+ throws CoreException {
+ boolean patch = false;
+ IImport[] imports = feature.getImports();
+ for (int i = 0; i < imports.length; i++) {
+ IImport iimport = imports[i];
+ if (iimport.isPatch()) {
+ patch = true;
+ break;
+ }
+ }
+ // Only need to check features that patch other features.
+ if (!patch)
+ return;
+ IFeature localFeature = findLocalFeature(targetSite, feature);
+ ArrayList oldFeatures = new ArrayList();
+ // First collect all older active features that
+ // have the same ID as new features marked as 'unique'.
+ collectOldFeatures(localFeature, targetSite, oldFeatures);
+ // Now unconfigure old features to enforce uniqueness
+ for (int i = 0; i < oldFeatures.size(); i++) {
+ IFeature oldFeature = (IFeature) oldFeatures.get(i);
+ unconfigure(config, oldFeature);
+ }
+ }
+
private void throwError(String message) throws CoreException {
IStatus status =
new Status(
@@ -228,10 +260,33 @@
throws CoreException {
IConfiguredSite site = findConfigSite(feature, config);
if (site != null) {
- return site.unconfigure(feature);
+ boolean result = site.unconfigure(feature);
+ if (!result) return false;
+ return unconfigurePatches(site, feature);
}
return false;
}
+
+ static boolean unconfigurePatches(IConfiguredSite site, IFeature feature) {
+ IFeatureReference [] refs = site.getFeatureReferences();
+ boolean totalResult = true;
+ for (int i=0; i<refs.length; i++) {
+ IFeatureReference ref = refs[i];
+ try {
+ IFeature candidate = ref.getFeature();
+ if (UpdateUIPlugin.isPatch(feature, candidate)) {
+ // Unconfigure patch as well.
+ if (site.unconfigure(candidate)==false)
+ totalResult=false;
+ }
+ }
+ catch (CoreException e) {
+ // Tolerate this
+ }
+ }
+ return totalResult;
+ }
+
private void configure(IFeature feature) throws CoreException {
IConfiguredSite site = findConfigSite(feature, config);
if (site != null) {
@@ -298,13 +353,14 @@
for (int i = 0; i < optionalElements.length; i++) {
FeatureHierarchyElement fe =
(FeatureHierarchyElement) optionalElements[i];
- Object [] children = fe.getChildren(true);
+ Object[] children = fe.getChildren(true);
preserveOptionalState(config, targetSite, children);
if (!fe.isEnabled(config)) {
IFeature newFeature = fe.getFeature();
try {
- IFeature localFeature = findLocalFeature(targetSite, newFeature);
- if (localFeature!=null)
+ IFeature localFeature =
+ findLocalFeature(targetSite, newFeature);
+ if (localFeature != null)
targetSite.unconfigure(localFeature);
} catch (CoreException e) {
// Eat this - we will leave with it
@@ -312,9 +368,37 @@
}
}
}
- private static IFeature findLocalFeature(IConfiguredSite csite, IFeature feature) throws CoreException {
- IFeatureReference [] refs = csite.getConfiguredFeatures();
- for (int i=0; i<refs.length; i++) {
+
+ static void collectOldFeatures(
+ IFeature feature,
+ IConfiguredSite targetSite,
+ ArrayList result)
+ throws CoreException {
+ IFeatureReference[] included = feature.getIncludedFeatureReferences();
+ for (int i = 0; i < included.length; i++) {
+ IFeatureReference iref = included[i];
+ IFeature ifeature = iref.getFeature();
+ // find other features and unconfigure
+ String id = iref.getVersionedIdentifier().getIdentifier();
+ IFeature[] sameIds =
+ UpdateUIPlugin.searchSite(id, targetSite, true);
+ for (int j = 0; j < sameIds.length; j++) {
+ IFeature sameId = sameIds[j];
+ // Ignore self.
+ if (sameId.equals(ifeature))
+ continue;
+ result.add(sameId);
+ }
+ collectOldFeatures(ifeature, targetSite, result);
+ }
+ }
+
+ private static IFeature findLocalFeature(
+ IConfiguredSite csite,
+ IFeature feature)
+ throws CoreException {
+ IFeatureReference[] refs = csite.getConfiguredFeatures();
+ for (int i = 0; i < refs.length; i++) {
IFeatureReference ref = refs[i];
VersionedIdentifier refVid = ref.getVersionedIdentifier();
if (feature.getVersionedIdentifier().equals(refVid))
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 08024a7..b7deac0 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
@@ -265,7 +265,9 @@
private boolean unconfigure(IFeature feature) throws CoreException {
IConfiguredSite site = findConfigSite(feature, config);
if (site != null) {
- return site.unconfigure(feature);
+ boolean result = site.unconfigure(feature);
+ if (!result) return false;
+ return InstallWizard.unconfigurePatches(site, feature);
}
return false;
}