KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > update > internal > core > SiteReconciler


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.update.internal.core;
12 import java.io.IOException JavaDoc;
13 import java.net.URL JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Set JavaDoc;
20
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.FileLocator;
23 import org.eclipse.core.runtime.PluginVersionIdentifier;
24 import org.eclipse.osgi.util.NLS;
25 import org.eclipse.update.configuration.IConfiguredSite;
26 import org.eclipse.update.configurator.IPlatformConfiguration;
27 import org.eclipse.update.core.IFeature;
28 import org.eclipse.update.core.IFeatureReference;
29 import org.eclipse.update.core.IIncludedFeatureReference;
30 import org.eclipse.update.core.Utilities;
31 import org.eclipse.update.core.VersionedIdentifier;
32 import org.eclipse.update.core.model.ModelObject;
33
34 /**
35  * This class manages the reconciliation.
36  */

37
38 public class SiteReconciler extends ModelObject {
39
40     /**
41      *
42      */

43     public SiteReconciler(LocalSite siteLocal) {
44 // this.siteLocal = siteLocal;
45
}
46
47
48     /**
49     *
50     */

51     /*package */
52     URL JavaDoc resolveSiteEntry(IPlatformConfiguration.ISiteEntry newSiteEntry) throws CoreException {
53         URL JavaDoc resolvedURL = null;
54         try {
55             resolvedURL = FileLocator.resolve(newSiteEntry.getURL());
56         } catch (IOException JavaDoc e) {
57             throw Utilities.newCoreException(NLS.bind(Messages.SiteLocal_UnableToResolve, (new String JavaDoc[] { newSiteEntry.getURL().toExternalForm() })), e);
58         }
59         return resolvedURL;
60     }
61
62
63     /**
64      * Validate we have only one configured feature of a specific id
65      * per configured site
66      */

67     public static void checkConfiguredFeaturesOld(IConfiguredSite configuredSite) throws CoreException {
68
69         // NOT USED
70

71         ConfiguredSite cSite = (ConfiguredSite) configuredSite;
72         IFeatureReference[] configuredFeatures = cSite.getConfiguredFeatures();
73         ConfigurationPolicy cPolicy = cSite.getConfigurationPolicy();
74
75         // TRACE
76
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
77             UpdateCore.debug("Compare features within :" + configuredSite.getSite().getURL()); //$NON-NLS-1$
78
}
79
80         for (int indexConfiguredFeatures = 0; indexConfiguredFeatures < configuredFeatures.length - 1; indexConfiguredFeatures++) {
81
82             IFeatureReference featureToCompare = configuredFeatures[indexConfiguredFeatures];
83
84             // within the configured site
85
// compare with the other configured features of this site
86
for (int restOfConfiguredFeatures = indexConfiguredFeatures + 1; restOfConfiguredFeatures < configuredFeatures.length; restOfConfiguredFeatures++) {
87                 int result = compare(featureToCompare, configuredFeatures[restOfConfiguredFeatures]);
88                 if (result != 0) {
89                     if (result == 1) {
90                         cPolicy.unconfigure(configuredFeatures[restOfConfiguredFeatures], true, false);
91                     }
92                     if (result == 2) {
93                         cPolicy.unconfigure(featureToCompare, true, false);
94                     }
95                 }
96             }
97         }
98     }
99
100     /**
101      * compare two feature references
102      * returns 0 if the feature are different
103      * returns 1 if the version of feature 1 is greater than the version of feature 2
104      * returns 2 if opposite
105      */

106     private static int compare(IFeatureReference featureRef1, IFeatureReference featureRef2) throws CoreException {
107
108         // TRACE
109
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
110             UpdateCore.debug("Compare: " + featureRef1 + " && " + featureRef2); //$NON-NLS-1$ //$NON-NLS-2$
111
}
112
113         if (featureRef1 == null)
114             return 0;
115
116         IFeature feature1 = null;
117         IFeature feature2 = null;
118         try {
119             feature1 = featureRef1.getFeature(null);
120             feature2 = featureRef2.getFeature(null);
121         } catch (CoreException e) {
122             UpdateCore.warn(null, e);
123             return 0;
124         }
125
126         if (feature1 == null || feature2 == null) {
127             return 0;
128         }
129
130         VersionedIdentifier id1 = feature1.getVersionedIdentifier();
131         VersionedIdentifier id2 = feature2.getVersionedIdentifier();
132
133         if (id1 == null || id2 == null) {
134             return 0;
135         }
136
137         if (id1.getIdentifier() != null && id1.getIdentifier().equals(id2.getIdentifier())) {
138             PluginVersionIdentifier version1 = id1.getVersion();
139             PluginVersionIdentifier version2 = id2.getVersion();
140             if (version1 != null) {
141                 if (version1.isGreaterThan(version2)) {
142                     return 1;
143                 } else {
144                     return 2;
145                 }
146             } else {
147                 return 2;
148             }
149         }
150         return 0;
151     }
152
153     /**
154      * Validate the list of configured features eliminating extra
155      * entries (if possible). Make sure we do not leave configured
156      * nested features with "holes" (ie. unconfigured children)
157      */

158     public static void checkConfiguredFeatures(IConfiguredSite configuredSite) {
159
160         // Note: if we hit errors in the various computation
161
// methods and throw a CoreException, we will not catch it
162
// in this method. Consequently we will not attempt to
163
// unconfigure any "extra" features because we would
164
// likely get it wrong. The platform will run with extra features
165
// configured. The runtime will eliminate extra plugins based
166
// on runtime binding rules.
167

168         // determine "proposed" list of configured features
169
ConfiguredSite cSite = (ConfiguredSite) configuredSite;
170         // debug
171
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
172             UpdateCore.debug("Validate configuration of site " + cSite.getSite().getURL()); //$NON-NLS-1$
173
}
174         IFeatureReference[] configuredRefs = cSite.getConfiguredFeatures();
175         ArrayList JavaDoc allPossibleConfiguredFeatures = new ArrayList JavaDoc();
176         for (int i = 0; i < configuredRefs.length; i++) {
177             try {
178                 IFeature feature = configuredRefs[i].getFeature(null);
179                 allPossibleConfiguredFeatures.add(feature);
180                 // debug
181
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
182                     UpdateCore.debug(" configured feature " + feature.getVersionedIdentifier().toString()); //$NON-NLS-1$
183
}
184             } catch (CoreException e) {
185                 UpdateCore.warn("", e); //$NON-NLS-1$
186
}
187         }
188
189         // find top level features
190
ArrayList JavaDoc topFeatures = computeTopFeatures(allPossibleConfiguredFeatures);
191
192         // find non efix top level features
193
ArrayList JavaDoc topNonEfixFeatures = getNonEfixFeatures(topFeatures);
194
195         // expand non efix top level features (compute full nesting structures).
196
ArrayList JavaDoc configuredFeatures = expandFeatures(topNonEfixFeatures, configuredSite);
197
198         // retrieve efixes that patch enable feature
199
// they must be kept enabled
200
if (topFeatures.size() != topNonEfixFeatures.size()) {
201             Map JavaDoc patches = getPatchesAsFeature(allPossibleConfiguredFeatures);
202             if (!patches.isEmpty()) {
203                 // calculate efixes to enable
204
List JavaDoc efixesToEnable = getPatchesToEnable(patches, configuredFeatures);
205                 // add efies to keep enable
206
//add them to the enable list
207
for (Iterator JavaDoc iter = efixesToEnable.iterator(); iter.hasNext();) {
208                     IFeature element = (IFeature) iter.next();
209                     ArrayList JavaDoc expandedEfix = new ArrayList JavaDoc();
210                     expandEfixFeature(element, expandedEfix, configuredSite);
211                     configuredFeatures.addAll(expandedEfix);
212                 }
213             }
214         }
215
216         // compute extra features
217
ArrayList JavaDoc extras = diff(allPossibleConfiguredFeatures, configuredFeatures);
218
219         // unconfigure extra features
220
ConfigurationPolicy cPolicy = cSite.getConfigurationPolicy();
221         for (int i = 0; i < extras.size(); i++) {
222             IFeature feature = (IFeature) extras.get(i);
223             IFeatureReference ref = cSite.getSite().getFeatureReference(feature);
224             try {
225                 cPolicy.unconfigure(ref, true, false);
226                 // debug
227
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
228                     UpdateCore.debug("Unconfiguring \"extra\" feature " + feature.getVersionedIdentifier().toString()); //$NON-NLS-1$
229
}
230             } catch (CoreException e) {
231                 UpdateCore.warn("", e); //$NON-NLS-1$
232
}
233         }
234     }
235
236     /*
237      *
238      */

239     private static ArrayList JavaDoc computeTopFeatures(ArrayList JavaDoc features) {
240         /* map of Feature by VersionedIdentifier */
241         Map JavaDoc topFeatures = new HashMap JavaDoc(features.size());
242         // start with the features passed in
243
for (Iterator JavaDoc it = features.iterator(); it.hasNext();) {
244             IFeature f = ((IFeature) it.next());
245             topFeatures.put(f.getVersionedIdentifier(), f);
246         }
247         // remove all features that nest in some other feature
248
for (Iterator JavaDoc it = features.iterator(); it.hasNext();) {
249             try {
250                 IIncludedFeatureReference[] children = ((IFeature) it.next()).getIncludedFeatureReferences();
251                 for (int j = 0; j < children.length; j++) {
252                     try {
253                         topFeatures.remove(children[j].getVersionedIdentifier());
254                     } catch (CoreException e1) {
255                         if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_WARNINGS)
256                             UpdateCore.warn("", e1); //$NON-NLS-1$
257
}
258                 }
259             } catch (CoreException e) {
260                 UpdateCore.warn("", e); //$NON-NLS-1$
261
}
262         }
263         ArrayList JavaDoc list = new ArrayList JavaDoc();
264         list.addAll(topFeatures.values());
265         // debug
266
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
267             UpdateCore.debug("Computed top-level features"); //$NON-NLS-1$
268
for (int i = 0; i < topFeatures.size(); i++) {
269                 UpdateCore.debug(" " + ((IFeature) list.get(i)).getVersionedIdentifier().toString()); //$NON-NLS-1$
270
}
271         }
272         return list;
273     }
274
275     /*
276      *
277      */

278     private static ArrayList JavaDoc expandFeatures(ArrayList JavaDoc features, IConfiguredSite configuredSite) {
279         ArrayList JavaDoc result = new ArrayList JavaDoc();
280
281         // expand all top level features
282
for (int i = 0; i < features.size(); i++) {
283             expandFeature((IFeature) features.get(i), result, configuredSite);
284         }
285
286         return result;
287     }
288
289     /*
290      *
291      */

292     private static void expandFeature(IFeature feature, ArrayList JavaDoc features, IConfiguredSite configuredSite) {
293
294         // add feature
295
if (!features.contains(feature)) {
296             features.add(feature);
297             // debug
298
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
299                 UpdateCore.debug("Retaining configured feature " + feature.getVersionedIdentifier().toString()); //$NON-NLS-1$
300
}
301         }
302
303         // add nested children to the list
304
IIncludedFeatureReference[] children = null;
305         try {
306             children = feature.getIncludedFeatureReferences();
307         } catch (CoreException e) {
308             UpdateCore.warn("", e); //$NON-NLS-1$
309
return;
310         }
311
312         for (int j = 0; j < children.length; j++) {
313             IFeature child = null;
314             try {
315                 child = children[j].getFeature(null);
316             } catch (CoreException e) {
317                 if (!UpdateManagerUtils.isOptional(children[j]))
318                     UpdateCore.warn("", e); //$NON-NLS-1$
319
// 25202 do not return right now, the peer children may be ok
320
}
321             if (child != null)
322                 expandFeature(child, features, configuredSite);
323         }
324     }
325
326     /*
327      *
328      */

329     private static ArrayList JavaDoc diff(ArrayList JavaDoc left, ArrayList JavaDoc right) {
330         ArrayList JavaDoc result = new ArrayList JavaDoc();
331
332         // determine difference (left "minus" right)
333
for (int i = 0; i < left.size(); i++) {
334             IFeature feature = (IFeature) left.get(i);
335             if (!right.contains(feature))
336                 result.add(feature);
337         }
338         return result;
339     }
340
341     /*
342      * get the list of enabled patches
343      */

344     private static Map JavaDoc getPatchesAsFeature(ArrayList JavaDoc allConfiguredFeatures) {
345         // get all efixes and the associated patched features
346
Map JavaDoc patches = new HashMap JavaDoc();
347         if (allConfiguredFeatures != null) {
348             Iterator JavaDoc iter = allConfiguredFeatures.iterator();
349             while (iter.hasNext()) {
350                 List JavaDoc patchedFeaturesID = new ArrayList JavaDoc();
351                 IFeature element = (IFeature) iter.next();
352                 // add the patched feature identifiers
353
for (int i = 0; i < element.getImports().length; i++) {
354                     if (element.getImports()[i].isPatch()) {
355                         VersionedIdentifier id = element.getImports()[i].getVersionedIdentifier();
356                         if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER)
357                             UpdateCore.debug("Found patch " + element + " for feature identifier " + id); //$NON-NLS-1$ //$NON-NLS-2$
358
patchedFeaturesID.add(id);
359                     }
360                 }
361
362                 if (!patchedFeaturesID.isEmpty()) {
363                     patches.put(element, patchedFeaturesID);
364                 }
365             }
366         }
367
368         return patches;
369     }
370
371     /*
372      * retruns the list of pathes-feature who patch enabled features
373      */

374     private static List JavaDoc getPatchesToEnable(Map JavaDoc efixes, ArrayList JavaDoc configuredFeatures) {
375
376         ArrayList JavaDoc enabledVersionedIdentifier = new ArrayList JavaDoc();
377         Iterator JavaDoc iter = configuredFeatures.iterator();
378         while (iter.hasNext()) {
379             IFeature element = (IFeature) iter.next();
380             enabledVersionedIdentifier.add(element.getVersionedIdentifier());
381         }
382
383         // loop through the patches
384
List JavaDoc result = new ArrayList JavaDoc();
385         iter = efixes.keySet().iterator();
386         while (iter.hasNext()) {
387             boolean toEnable = false;
388             IFeature efixFeature = (IFeature) iter.next();
389             List JavaDoc patchedFeatures = (List JavaDoc) efixes.get(efixFeature);
390             // loop through the 'patched features identifier' the for this patch
391
// see if it the patch patches at least one enable feature
392
Iterator JavaDoc patchedFeaturesIter = patchedFeatures.iterator();
393             while (patchedFeaturesIter.hasNext() && !toEnable) {
394                 VersionedIdentifier patchedFeatureID = (VersionedIdentifier) patchedFeaturesIter.next();
395                 if (enabledVersionedIdentifier.contains(patchedFeatureID)) {
396                     toEnable = true;
397                 }
398             }
399
400             if (!toEnable) {
401                 if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER)
402                 UpdateCore.debug("The Patch " + efixFeature + " does not patch any enabled features: it will be disabled"); //$NON-NLS-1$ //$NON-NLS-2$
403
} else {
404                 if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER)
405                     UpdateCore.debug("The patch " + efixFeature + " will be enabled."); //$NON-NLS-1$ //$NON-NLS-2$
406
result.add(efixFeature);
407             }
408         }
409         return result;
410     }
411
412     /*
413      * returns the feature that are not patches
414      */

415     private static ArrayList JavaDoc getNonEfixFeatures(ArrayList JavaDoc topFeatures) {
416         Map JavaDoc efixFeatures = getPatchesAsFeature(topFeatures);
417         Set JavaDoc keySet = efixFeatures.keySet();
418         if (keySet == null || keySet.isEmpty())
419             return topFeatures;
420
421         Iterator JavaDoc iter = topFeatures.iterator();
422         ArrayList JavaDoc result = new ArrayList JavaDoc();
423         while (iter.hasNext()) {
424             IFeature element = (IFeature) iter.next();
425             if (!keySet.contains(element)) {
426                 result.add(element);
427             }
428         }
429         return result;
430     }
431
432
433
434
435     /*
436      * only enable non-efix children recursively
437      */

438     private static void expandEfixFeature(IFeature feature, ArrayList JavaDoc features, IConfiguredSite configuredSite) {
439
440         // add feature
441
if (!features.contains(feature)) {
442             features.add(feature);
443             // debug
444
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) {
445                 UpdateCore.debug("Retaining configured feature " + feature.getVersionedIdentifier().toString()); //$NON-NLS-1$
446
}
447         }
448
449         // add nested children to the list
450
IIncludedFeatureReference[] children = null;
451         try {
452             children = feature.getIncludedFeatureReferences();
453         } catch (CoreException e) {
454             UpdateCore.warn("", e); //$NON-NLS-1$
455
return;
456         }
457
458         for (int j = 0; j < children.length; j++) {
459             IFeature child = null;
460             try {
461                 child = children[j].getFeature(null);
462             } catch (CoreException e) {
463                 if (!children[j].isOptional())
464                     UpdateCore.warn("", e); //$NON-NLS-1$
465
// 25202 do not return right now, the peer children may be ok
466
}
467             if (child != null){
468                 if (!UpdateCore.isPatch(child))
469                     expandEfixFeature(child, features, configuredSite);
470             }
471         }
472     }
473     
474 }
475
Popular Tags