KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > update > internal > operations > OperationValidator


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.operations;
12
13 //import java.io.*;
14
//import java.net.*;
15
//import java.nio.channels.*;
16
import java.io.File JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.net.URL JavaDoc;
19 import java.net.URLConnection JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Set JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProduct;
29 import org.eclipse.core.runtime.IStatus;
30 import org.eclipse.core.runtime.MultiStatus;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.core.runtime.PluginVersionIdentifier;
33 import org.eclipse.osgi.util.NLS;
34 import org.eclipse.update.configuration.IConfiguredSite;
35 import org.eclipse.update.configuration.IInstallConfiguration;
36 import org.eclipse.update.configuration.ILocalSite;
37 import org.eclipse.update.configurator.ConfiguratorUtils;
38 import org.eclipse.update.configurator.IPlatformConfiguration;
39 import org.eclipse.update.core.IFeature;
40 import org.eclipse.update.core.IFeatureReference;
41 import org.eclipse.update.core.IImport;
42 import org.eclipse.update.core.IIncludedFeatureReference;
43 import org.eclipse.update.core.IPluginEntry;
44 import org.eclipse.update.core.ISiteFeatureReference;
45 import org.eclipse.update.core.IURLEntry;
46 import org.eclipse.update.core.SiteManager;
47 import org.eclipse.update.core.VersionedIdentifier;
48 import org.eclipse.update.internal.configurator.PlatformConfiguration;
49 import org.eclipse.update.internal.core.Messages;
50 import org.eclipse.update.internal.core.UpdateCore;
51 import org.eclipse.update.operations.IInstallFeatureOperation;
52 import org.eclipse.update.operations.IOperationValidator;
53 import org.osgi.framework.Bundle;
54
55 /**
56  *
57  */

58 public class OperationValidator implements IOperationValidator {
59     /**
60      * Checks if the platform configuration has been modified outside this program.
61      * @return the error status, or null if no errors
62      */

63     public IStatus validatePlatformConfigValid() {
64         ArrayList JavaDoc status = new ArrayList JavaDoc(1);
65         checkPlatformWasModified(status);
66         
67         // report status
68
if (status.size() > 0)
69             return createMultiStatus(Messages.ActivityConstraints_rootMessage, status, IStatus.ERROR);
70         return null;
71     }
72     
73     /*
74      * Called by UI before performing operation. Returns null if no errors, a
75      * status with IStatus.WARNING code when the initial configuration is
76      * broken, or a status with IStatus.ERROR when there the operation
77      * introduces new errors
78      */

79     public IStatus validatePendingInstall(
80         IFeature oldFeature,
81         IFeature newFeature) {
82         // check initial state
83
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
84         validateInitialState(beforeStatus);
85
86         // check proposed change
87
ArrayList JavaDoc status = new ArrayList JavaDoc();
88         checkPlatformWasModified(status);
89         validateInstall(oldFeature, newFeature, status);
90
91         // report status
92
return createCombinedReportStatus(beforeStatus, status);
93     }
94
95     /*
96      * Called by UI before performing operation
97      */

98     public IStatus validatePendingUnconfig(IFeature feature) {
99         // check initial state
100
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
101         validateInitialState(beforeStatus);
102
103         // check proposed change
104
ArrayList JavaDoc status = new ArrayList JavaDoc();
105         checkPlatformWasModified(status);
106         validateUnconfigure(feature, status);
107
108         // report status
109
return createCombinedReportStatus(beforeStatus, status);
110     }
111
112     /*
113      * Called by UI before performing operation
114      */

115     public IStatus validatePendingConfig(IFeature feature) {
116         // check initial state
117
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
118         validateInitialState(beforeStatus);
119
120         // check proposed change
121
ArrayList JavaDoc status = new ArrayList JavaDoc();
122         checkPlatformWasModified(status);
123         validateConfigure(feature, status);
124
125         // report status
126
return createCombinedReportStatus(beforeStatus, status);
127     }
128
129     /**
130      * Called before performing operation.
131      */

132     public IStatus validatePendingReplaceVersion(
133         IFeature feature,
134         IFeature anotherFeature) {
135         // check initial state
136
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
137         validateInitialState(beforeStatus);
138
139         // check proposed change
140
ArrayList JavaDoc status = new ArrayList JavaDoc();
141         checkPlatformWasModified(status);
142         validateReplaceVersion(feature, anotherFeature, status);
143
144         // report status
145
return createCombinedReportStatus(beforeStatus, status);
146     }
147
148
149     /*
150      * Called by the UI before doing a revert/ restore operation
151      */

152     public IStatus validatePendingRevert(IInstallConfiguration config) {
153         // check initial state
154
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
155         validateInitialState(beforeStatus);
156
157         // check proposed change
158
ArrayList JavaDoc status = new ArrayList JavaDoc();
159         checkPlatformWasModified(status);
160         validateRevert(config, status);
161
162         // report status
163
return createCombinedReportStatus(beforeStatus, status);
164     }
165
166     /*
167      * Called by the UI before doing a batched processing of several pending
168      * changes.
169      */

170     public IStatus validatePendingChanges(IInstallFeatureOperation[] jobs) {
171         // check initial state
172
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
173         validateInitialState(beforeStatus);
174         checkPlatformWasModified(beforeStatus);
175
176         // check proposed change
177
ArrayList JavaDoc status = new ArrayList JavaDoc();
178         validatePendingChanges(jobs, status, beforeStatus);
179
180         // report status
181
return createCombinedReportStatus(beforeStatus, status);
182     }
183     
184     /*
185      * Called by the UI before doing a batched processing of several pending
186      * changes.
187      */

188     public RequiredFeaturesResult getRequiredFeatures(IInstallFeatureOperation[] jobs) {
189         
190         RequiredFeaturesResult requiredFeaturesResult = new RequiredFeaturesResult();
191         // check initial state
192
ArrayList JavaDoc beforeStatus = new ArrayList JavaDoc();
193         validateInitialState(beforeStatus);
194         checkPlatformWasModified(beforeStatus);
195
196         // check proposed change
197
ArrayList JavaDoc status = new ArrayList JavaDoc();
198         Set JavaDoc requiredFeatures = validatePendingChanges(jobs, status, beforeStatus);
199
200         // report status
201
//return createCombinedReportStatus(beforeStatus, status);
202
requiredFeaturesResult.setRequiredFeatures(requiredFeatures);
203         requiredFeaturesResult.setStatus(createCombinedReportStatus(beforeStatus, status));
204         return requiredFeaturesResult;
205     }
206
207     /*
208      * Check the current state.
209      */

210     public IStatus validateCurrentState() {
211         // check the state
212
ArrayList JavaDoc status = new ArrayList JavaDoc();
213         checkPlatformWasModified(status);
214         validateInitialState(status);
215
216         // report status
217
if (status.size() > 0)
218             return createMultiStatus(Messages.ActivityConstraints_rootMessage, status, IStatus.ERROR);
219         return null;
220     }
221
222     /*
223      * Check to see if we are not broken even before we start
224      */

225     private static void validateInitialState(ArrayList JavaDoc status) {
226         try {
227             ArrayList JavaDoc features = computeFeatures();
228             // uncomment this when patch released in boot
229
//checkConfigurationLock(status);
230
checkConstraints(features, status);
231         } catch (CoreException e) {
232             status.add(e.getStatus());
233         }
234     }
235
236     /*
237      * handle unconfigure
238      */

239     private static void validateUnconfigure(
240         IFeature feature,
241         ArrayList JavaDoc status) {
242         try {
243             checkSiteReadOnly(feature,status);
244             ArrayList JavaDoc features = computeFeatures();
245             features = computeFeaturesAfterOperation(features, null, feature);
246             checkConstraints(features, status);
247         } catch (CoreException e) {
248             status.add(e.getStatus());
249         }
250     }
251
252
253     /*
254      * handle configure
255      */

256     private static void validateConfigure(IFeature feature, ArrayList JavaDoc status) {
257         try {
258             checkSiteReadOnly(feature,status);
259             ArrayList JavaDoc features = computeFeatures();
260             checkOptionalChildConfiguring(feature, status);
261             checkForCycles(feature, null, features);
262             features = computeFeaturesAfterOperation(features, feature, null);
263             checkConstraints(features, status);
264
265         } catch (CoreException e) {
266             status.add(e.getStatus());
267         }
268     }
269
270     /*
271      * handle replace version
272      */

273     private static void validateReplaceVersion(
274         IFeature feature,
275         IFeature anotherFeature,
276         ArrayList JavaDoc status) {
277         try {
278             checkSiteReadOnly(feature,status);
279             ArrayList JavaDoc features = computeFeatures();
280             checkForCycles(feature, null, features);
281             features =
282                 computeFeaturesAfterOperation(
283                     features,
284                     anotherFeature,
285                     feature);
286             checkConstraints(features, status);
287         } catch (CoreException e) {
288             status.add(e.getStatus());
289         }
290     }
291
292     /*
293      * handle install and update
294      */

295     private static void validateInstall(
296         IFeature oldFeature,
297         IFeature newFeature,
298         ArrayList JavaDoc status) {
299         try {
300             checkSiteReadOnly(oldFeature,status);
301             ArrayList JavaDoc features = computeFeatures();
302             checkForCycles(newFeature, null, features);
303             features =
304                 computeFeaturesAfterOperation(features, newFeature, oldFeature);
305             checkConstraints(features, status);
306             checkLicense(newFeature, status);
307         } catch (CoreException e) {
308             status.add(e.getStatus());
309         }
310     }
311
312     /*
313      * handle revert and restore
314      */

315     private static void validateRevert(
316         IInstallConfiguration config,
317         ArrayList JavaDoc status) {
318         try {
319 // // check the timeline and don't bother
320
// // to check anything else if negative
321
// if (!checkTimeline(config, status))
322
// return;
323
ArrayList JavaDoc features = computeFeaturesAfterRevert(config);
324             checkConstraints(features, status);
325             checkRevertConstraints(features, status);
326
327         } catch (CoreException e) {
328             status.add(e.getStatus());
329         }
330     }
331
332
333     /*
334      * Handle one-click changes as a batch
335      */

336     private static Set JavaDoc validatePendingChanges(
337         IInstallFeatureOperation[] jobs,
338         ArrayList JavaDoc status,
339         ArrayList JavaDoc beforeStatus) {
340         try {
341             ArrayList JavaDoc features = computeFeatures();
342             ArrayList JavaDoc savedFeatures = features;
343             int nexclusives = 0;
344
345             // pass 1: see if we can process the entire "batch"
346
ArrayList JavaDoc tmpStatus = new ArrayList JavaDoc();
347             for (int i = 0; i < jobs.length; i++) {
348                 IInstallFeatureOperation job = jobs[i];
349
350                 IFeature newFeature = job.getFeature();
351                 IFeature oldFeature = job.getOldFeature();
352                 checkLicense(newFeature, status);
353                 if (jobs.length > 1 && newFeature.isExclusive()) {
354                     nexclusives++;
355                     status.add(
356                         createStatus(
357                             newFeature,
358                             FeatureStatus.CODE_EXCLUSIVE,
359                             Messages.ActivityConstraints_exclusive));
360                     continue;
361                 }
362                 checkForCycles(newFeature, null, features);
363                 features =
364                     computeFeaturesAfterOperation(
365                         features,
366                         newFeature,
367                         oldFeature);
368             }
369             if (nexclusives > 0)
370                 return Collections.EMPTY_SET;
371             checkConstraints(features, tmpStatus);
372             if (tmpStatus.size() == 0) // the whole "batch" is OK
373
return Collections.EMPTY_SET;
374
375             // pass 2: we have conflicts
376
features = savedFeatures;
377             for (int i = 0; i < jobs.length; i++) {
378                 IInstallFeatureOperation job = jobs[i];
379                 IFeature newFeature = job.getFeature();
380                 IFeature oldFeature = job.getOldFeature();
381
382                 features =
383                     computeFeaturesAfterOperation(
384                         features,
385                         newFeature,
386                         oldFeature);
387
388                 Set JavaDoc result = checkConstraints(features, status);
389                 if (status.size() > 0
390                     && !isBetterStatus(beforeStatus, status)) {
391 // bug 75613
392
// IStatus conflict =
393
// createStatus(
394
// newFeature,
395
// FeatureStatus.CODE_OTHER,
396
// Policy.bind(KEY_CONFLICT));
397
// status.add(0, conflict);
398
return result;
399                 }
400             }
401         } catch (CoreException e) {
402             status.add(e.getStatus());
403         }
404         
405         return Collections.EMPTY_SET;
406     }
407     
408     private static void checkPlatformWasModified(ArrayList JavaDoc status) {
409         try {
410             // checks if the platform has been modified outside this eclipse instance
411
IPlatformConfiguration platformConfig = ConfiguratorUtils.getCurrentPlatformConfiguration();
412             
413             long currentTimeStamp = platformConfig.getChangeStamp();
414             // get the last modified value for this config, from this process point of view
415
if (platformConfig instanceof PlatformConfiguration)
416                 currentTimeStamp = ((PlatformConfiguration)platformConfig).getConfiguration().lastModified();
417                 
418             // get the real last modified value
419
URL JavaDoc platformXML = platformConfig.getConfigurationLocation();
420             long actualTimeStamp = currentTimeStamp;
421             if ("file".equals(platformXML.getProtocol())) //$NON-NLS-1$
422
actualTimeStamp = new File JavaDoc(platformXML.getFile()).lastModified();
423             else {
424                 URLConnection JavaDoc connection = platformXML.openConnection();
425                 actualTimeStamp = connection.getLastModified();
426             }
427             if (currentTimeStamp != actualTimeStamp)
428                 status.add(createStatus(
429                                 null,
430                                 FeatureStatus.CODE_OTHER,
431                                 Messages.ActivityConstraints_platformModified));
432         } catch (IOException JavaDoc e) {
433             // ignore
434
}
435     }
436     
437     private static void checkSiteReadOnly(IFeature feature, ArrayList JavaDoc status) {
438         if(feature == null){
439             return;
440         }
441         IConfiguredSite csite = feature.getSite().getCurrentConfiguredSite();
442         if (csite != null && !csite.isUpdatable())
443             status.add(createStatus(feature, FeatureStatus.CODE_OTHER,
444                     NLS.bind(Messages.ActivityConstraints_readOnly, (new String JavaDoc[] { csite.getSite().getURL().toExternalForm() }))));
445     }
446
447     /*
448      * Compute a list of configured features
449      */

450     private static ArrayList JavaDoc computeFeatures() throws CoreException {
451         return computeFeatures(true);
452     }
453     /*
454      * Compute a list of configured features
455      */

456     private static ArrayList JavaDoc computeFeatures(boolean configuredOnly)
457         throws CoreException {
458         ArrayList JavaDoc features = new ArrayList JavaDoc();
459         ILocalSite localSite = SiteManager.getLocalSite();
460         IInstallConfiguration config = localSite.getCurrentConfiguration();
461         IConfiguredSite[] csites = config.getConfiguredSites();
462
463         for (int i = 0; i < csites.length; i++) {
464             IConfiguredSite csite = csites[i];
465
466             IFeatureReference[] crefs;
467
468             if (configuredOnly)
469                 crefs = csite.getConfiguredFeatures();
470             else
471                 crefs = csite.getSite().getFeatureReferences();
472             for (int j = 0; j < crefs.length; j++) {
473                 IFeatureReference cref = crefs[j];
474                 IFeature cfeature = cref.getFeature(null);
475                 features.add(cfeature);
476             }
477         }
478
479         return features;
480     }
481
482     /*
483      * Compute the nested feature subtree starting at the specified base
484      * feature
485      */

486     public static ArrayList JavaDoc computeFeatureSubtree(
487             IFeature top,
488             IFeature feature,
489             ArrayList JavaDoc features,
490             boolean tolerateMissingChildren,
491             ArrayList JavaDoc configuredFeatures,
492             ArrayList JavaDoc visitedFeatures)
493     throws CoreException {
494
495         // check arguments
496
if (top == null)
497             return features;
498         if (feature == null)
499             feature = top;
500         if (features == null)
501             features = new ArrayList JavaDoc();
502         if (visitedFeatures == null)
503             visitedFeatures = new ArrayList JavaDoc();
504
505         // check for <includes> cycle
506
if (visitedFeatures.contains(feature)) {
507             IStatus status =
508             createStatus(top, FeatureStatus.CODE_CYCLE, Messages.ActivityConstraints_cycle);
509             throw new CoreException(status);
510         } else {
511             // keep track of visited features so we can detect cycles
512
visitedFeatures.add(feature);
513         }
514
515         // return specified base feature and all its children
516
if (!features.contains(feature))
517             features.add(feature);
518         IIncludedFeatureReference[] children =
519         feature.getIncludedFeatureReferences();
520         for (int i = 0; i < children.length; i++) {
521             try {
522                 IFeature child = UpdateUtils.getIncludedFeature(feature, children[i]);
523                 features =
524                 computeFeatureSubtree(
525                         top,
526                         child,
527                         features,
528                         tolerateMissingChildren,
529                         null,
530                         visitedFeatures);
531             } catch (CoreException e) {
532                 if (!children[i].isOptional() && !tolerateMissingChildren)
533                     throw e;
534             }
535         }
536         // no cycles for this feature during DFS
537
visitedFeatures.remove(feature);
538         return features;
539     }
540
541     private static void checkLicense(IFeature feature, ArrayList JavaDoc status) {
542         IURLEntry licenseEntry = feature.getLicense();
543         if (licenseEntry != null) {
544             String JavaDoc license = licenseEntry.getAnnotation();
545             if (license != null && license.trim().length() > 0)
546                 return;
547         }
548         status.add(
549             createStatus(feature, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_noLicense));
550     }
551
552     /*
553      * Compute a list of features that will be configured after the operation
554      */

555     private static ArrayList JavaDoc computeFeaturesAfterOperation(
556         ArrayList JavaDoc features,
557         IFeature add,
558         IFeature remove)
559         throws CoreException {
560
561         ArrayList JavaDoc addTree = computeFeatureSubtree(add, null, null, false,
562         /* do not tolerate missing children */
563         features, null);
564         ArrayList JavaDoc removeTree =
565             computeFeatureSubtree(
566                 remove,
567                 null,
568                 null,
569                 true /* tolerate missing children */,
570                 null,
571                 null
572         );
573         if (remove != null) {
574             // Patches to features are removed together with
575
// those features. Include them in the list.
576
contributePatchesFor(removeTree, features, removeTree);
577         }
578
579         if (remove != null)
580             features.removeAll(removeTree);
581
582         if (add != null)
583             features.addAll(addTree);
584
585         return features;
586     }
587
588     private static void contributePatchesFor(
589         ArrayList JavaDoc removeTree,
590         ArrayList JavaDoc features,
591         ArrayList JavaDoc result)
592         throws CoreException {
593
594         for (int i = 0; i < removeTree.size(); i++) {
595             IFeature feature = (IFeature) removeTree.get(i);
596             contributePatchesFor(feature, features, result);
597         }
598     }
599
600     private static void contributePatchesFor(
601         IFeature feature,
602         ArrayList JavaDoc features,
603         ArrayList JavaDoc result)
604         throws CoreException {
605         for (int i = 0; i < features.size(); i++) {
606             IFeature candidate = (IFeature) features.get(i);
607             if (UpdateUtils.isPatch(feature, candidate)) {
608                 ArrayList JavaDoc removeTree =
609                     computeFeatureSubtree(candidate, null, null, true,null,null);
610                 result.addAll(removeTree);
611             }
612         }
613     }
614
615     /*
616      * Compute a list of features that will be configured after performing the
617      * revert
618      */

619     private static ArrayList JavaDoc computeFeaturesAfterRevert(IInstallConfiguration config)
620         throws CoreException {
621
622         ArrayList JavaDoc list = new ArrayList JavaDoc();
623         IConfiguredSite[] csites = config.getConfiguredSites();
624         for (int i = 0; i < csites.length; i++) {
625             IConfiguredSite csite = csites[i];
626             IFeatureReference[] features = csite.getConfiguredFeatures();
627             for (int j = 0; j < features.length; j++) {
628                 list.add(features[j].getFeature(null));
629             }
630         }
631         return list;
632     }
633
634
635
636     /*
637      * Compute a list of plugin entries for the specified features.
638      */

639     private static ArrayList JavaDoc computePluginsForFeatures(ArrayList JavaDoc features)
640         throws CoreException {
641         if (features == null)
642             return new ArrayList JavaDoc();
643
644         HashMap JavaDoc plugins = new HashMap JavaDoc();
645         for (int i = 0; i < features.size(); i++) {
646             IFeature feature = (IFeature) features.get(i);
647             IPluginEntry[] entries = feature.getPluginEntries();
648             for (int j = 0; j < entries.length; j++) {
649                 IPluginEntry entry = entries[j];
650                 plugins.put(entry.getVersionedIdentifier(), entry);
651             }
652         }
653         ArrayList JavaDoc result = new ArrayList JavaDoc();
654         result.addAll(plugins.values());
655         return result;
656     }
657
658
659     /**
660      * Check for feature cycles:
661      * - visit feature
662      * - if feature is in the cycle candidates list, then cycle found, else add it to candidates list
663      * - DFS children
664      * - when return from DFS remove the feature from the candidates list
665      */

666     private static void checkForCycles(
667             IFeature feature,
668             ArrayList JavaDoc candidates,
669             ArrayList JavaDoc configuredFeatures)
670     throws CoreException {
671
672         // check arguments
673
if (feature == null)
674             return;
675         if (configuredFeatures == null)
676             configuredFeatures = new ArrayList JavaDoc();
677         if (candidates == null)
678             candidates = new ArrayList JavaDoc();
679         
680         // check for <includes> cycle
681
if (candidates.contains(feature)) {
682             String JavaDoc msg = NLS.bind(Messages.ActivityConstraints_cycle, (new String JavaDoc[] {feature.getLabel(),
683             feature.getVersionedIdentifier().toString()}));
684             IStatus status = createStatus(feature, FeatureStatus.CODE_CYCLE, msg);
685             throw new CoreException(status);
686         }
687
688         // potential candidate
689
candidates.add(feature);
690         
691         // recursively, check cycles with children
692
IIncludedFeatureReference[] children =
693         feature.getIncludedFeatureReferences();
694         for (int i = 0; i < children.length; i++) {
695             try {
696                 IFeature child = UpdateUtils.getIncludedFeature(feature, children[i]);
697                 checkForCycles(child, candidates, configuredFeatures);
698             } catch (CoreException e) {
699                 if (!children[i].isOptional())
700                     throw e;
701             }
702         }
703         // no longer a candidate, because no cycles with children
704
candidates.remove(feature);
705     }
706     
707     /*
708      * validate constraints
709      */

710     private static Set JavaDoc checkConstraints(ArrayList JavaDoc features, ArrayList JavaDoc status)
711         throws CoreException {
712         if (features == null)
713             return Collections.EMPTY_SET;
714
715         ArrayList JavaDoc plugins = computePluginsForFeatures(features);
716
717         checkEnvironment(features, status);
718         checkPlatformFeature(features, plugins, status);
719         checkPrimaryFeature(features, plugins, status);
720         return checkPrereqs(features, plugins, status);
721     }
722
723     /*
724      * Verify all features are either portable, or match the current
725      * environment
726      */

727     private static void checkEnvironment(
728         ArrayList JavaDoc features,
729         ArrayList JavaDoc status) {
730
731         String JavaDoc os = Platform.getOS();
732         String JavaDoc ws = Platform.getWS();
733         String JavaDoc arch = Platform.getOSArch();
734
735         for (int i = 0; i < features.size(); i++) {
736             IFeature feature = (IFeature) features.get(i);
737             ArrayList JavaDoc fos = createList(feature.getOS());
738             ArrayList JavaDoc fws = createList(feature.getWS());
739             ArrayList JavaDoc farch = createList(feature.getOSArch());
740
741             if (fos.size() > 0) {
742                 if (!fos.contains(os)) {
743                     IStatus s =
744                         createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Messages.ActivityConstraints_os);
745                     if (!status.contains(s))
746                         status.add(s);
747                     continue;
748                 }
749             }
750
751             if (fws.size() > 0) {
752                 if (!fws.contains(ws)) {
753                     IStatus s =
754                         createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Messages.ActivityConstraints_ws);
755                     if (!status.contains(s))
756                         status.add(s);
757                     continue;
758                 }
759             }
760
761             if (farch.size() > 0) {
762                 if (!farch.contains(arch)) {
763                     IStatus s =
764                         createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Messages.ActivityConstraints_arch);
765                     if (!status.contains(s))
766                         status.add(s);
767                     continue;
768                 }
769             }
770         }
771     }
772
773     /*
774      * Verify we end up with a version of platform configured
775      */

776     private static void checkPlatformFeature(
777         ArrayList JavaDoc features,
778         ArrayList JavaDoc plugins,
779         ArrayList JavaDoc status) {
780
781         // find the plugin that defines the product
782
IProduct product = Platform.getProduct();
783         if (product == null)
784             return; // normally this shouldn't happen
785
Bundle primaryBundle = product.getDefiningBundle();
786         // check if that plugin is among the resulting plugins
787
boolean found = false;
788         for (int j = 0; j < plugins.size(); j++) {
789             IPluginEntry plugin = (IPluginEntry) plugins.get(j);
790             if (primaryBundle.getSymbolicName().equals(plugin.getVersionedIdentifier().getIdentifier())) {
791                 found = true;
792                 break;
793             }
794         }
795         
796         if (!found) {
797             IStatus s =
798                 createStatus(null, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_platform);
799             if (!status.contains(s))
800                 status.add(s);
801         }
802     }
803
804     /*
805      * Verify we end up with a version of primary feature configured
806      */

807     private static void checkPrimaryFeature(
808         ArrayList JavaDoc features,
809         ArrayList JavaDoc plugins,
810         ArrayList JavaDoc status) {
811
812         String JavaDoc featureId =
813             ConfiguratorUtils
814                 .getCurrentPlatformConfiguration()
815                 .getPrimaryFeatureIdentifier();
816         
817         if (featureId != null) {
818             // primary feature is defined
819
for (int i = 0; i < features.size(); i++) {
820                 IFeature feature = (IFeature) features.get(i);
821                 if (featureId
822                     .equals(feature.getVersionedIdentifier().getIdentifier()))
823                     return;
824             }
825     
826             IStatus s = createStatus(null, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_primary);
827             if (!status.contains(s))
828                 status.add(s);
829         } else {
830             // check if the product still ends up contributed
831
// find the plugin that defines the product
832
IProduct product = Platform.getProduct();
833             if (product == null)
834                 return; // normally this shouldn't happen
835
Bundle primaryBundle = product.getDefiningBundle();
836             // check if that plugin is among the resulting plugins
837

838             for (int j = 0; j < plugins.size(); j++) {
839                 IPluginEntry plugin = (IPluginEntry) plugins.get(j);
840                 if (primaryBundle.getSymbolicName().equals(plugin.getVersionedIdentifier().getIdentifier())) {
841                     return; // product found
842
}
843             }
844             IStatus s =
845                 createStatus(null, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_primary);
846             if (!status.contains(s))
847                 status.add(s);
848         }
849     }
850
851     /*
852      * Verify we do not break prereqs
853      */

854     private static Set JavaDoc checkPrereqs(
855         ArrayList JavaDoc features,
856         ArrayList JavaDoc plugins,
857         ArrayList JavaDoc status) {
858         
859         HashSet JavaDoc result = new HashSet JavaDoc();
860
861         for (int i = 0; i < features.size(); i++) {
862             IFeature feature = (IFeature) features.get(i);
863             IImport[] imports = feature.getImports();
864
865             for (int j = 0; j < imports.length; j++) {
866                 IImport iimport = imports[j];
867                 // for each import determine plugin or feature, version, match
868
// we need
869
VersionedIdentifier iid = iimport.getVersionedIdentifier();
870                 String JavaDoc id = iid.getIdentifier();
871                 PluginVersionIdentifier version = iid.getVersion();
872                 boolean featurePrereq =
873                     iimport.getKind() == IImport.KIND_FEATURE;
874                 boolean ignoreVersion =
875                     version.getMajorComponent() == 0
876                         && version.getMinorComponent() == 0
877                         && version.getServiceComponent() == 0;
878                 int rule = iimport.getRule();
879                 if (rule == IImport.RULE_NONE)
880                     rule = IImport.RULE_COMPATIBLE;
881
882                 boolean found = false;
883
884                 ArrayList JavaDoc candidates;
885
886                 if (featurePrereq)
887                     candidates = features;
888                 else
889                     candidates = plugins;
890                 for (int k = 0; k < candidates.size(); k++) {
891                     VersionedIdentifier cid;
892                     if (featurePrereq) {
893                         // the candidate is a feature
894
IFeature candidate = (IFeature) candidates.get(k);
895                         // skip self
896
if (feature.equals(candidate))
897                             continue;
898                         cid = candidate.getVersionedIdentifier();
899                     } else {
900                         // the candidate is a plug-in
901
IPluginEntry plugin = (IPluginEntry) candidates.get(k);
902                         cid = plugin.getVersionedIdentifier();
903                     }
904                     PluginVersionIdentifier cversion = cid.getVersion();
905                     if (id.equals(cid.getIdentifier())) {
906                         // have a candidate
907
if (ignoreVersion)
908                             found = true;
909                         else if (
910                             rule == IImport.RULE_PERFECT
911                                 && cversion.isPerfect(version))
912                             found = true;
913                         else if (
914                             rule == IImport.RULE_EQUIVALENT
915                                 && cversion.isEquivalentTo(version))
916                             found = true;
917                         else if (
918                             rule == IImport.RULE_COMPATIBLE
919                                 && cversion.isCompatibleWith(version))
920                             found = true;
921                         else if (
922                             rule == IImport.RULE_GREATER_OR_EQUAL
923                                 && cversion.isGreaterOrEqualTo(version))
924                             found = true;
925                     }
926                     if (found)
927                         break;
928                 }
929
930                 if (!found) {
931                     // report status
932
String JavaDoc target =
933                         featurePrereq
934                             ? Messages.ActivityConstaints_prereq_feature
935                             : Messages.ActivityConstaints_prereq_plugin;
936                     int errorCode = featurePrereq
937                             ? FeatureStatus.CODE_PREREQ_FEATURE
938                             : FeatureStatus.CODE_PREREQ_PLUGIN;
939                     String JavaDoc msg =
940                         NLS.bind(Messages.ActivityConstraints_prereq, (new String JavaDoc[] { target, id }));
941
942                     if (!ignoreVersion) {
943                         if (rule == IImport.RULE_PERFECT)
944                             msg =
945                                 NLS.bind(Messages.ActivityConstraints_prereqPerfect, (new String JavaDoc[] {
946                                 target,
947                                 id,
948                                 version.toString()}));
949                         else if (rule == IImport.RULE_EQUIVALENT)
950                             msg =
951                                 NLS.bind(Messages.ActivityConstraints_prereqEquivalent, (new String JavaDoc[] {
952                                 target,
953                                 id,
954                                 version.toString()}));
955                         else if (rule == IImport.RULE_COMPATIBLE)
956                             msg =
957                                 NLS.bind(Messages.ActivityConstraints_prereqCompatible, (new String JavaDoc[] {
958                                 target,
959                                 id,
960                                 version.toString()}));
961                         else if (rule == IImport.RULE_GREATER_OR_EQUAL)
962                             msg =
963                                 NLS.bind(Messages.ActivityConstraints_prereqGreaterOrEqual, (new String JavaDoc[] {
964                                 target,
965                                 id,
966                                 version.toString()}));
967                     }
968                     IStatus s = createStatus(feature, errorCode, msg);
969                     result.add(new InternalImport(iimport));
970                     if (!status.contains(s))
971                         status.add(s);
972                 }
973             }
974         }
975         
976         return result;
977     }
978
979     /*
980      * Verify we end up with valid nested features after revert
981      */

982     private static void checkRevertConstraints(
983         ArrayList JavaDoc features,
984         ArrayList JavaDoc status) {
985
986         for (int i = 0; i < features.size(); i++) {
987             IFeature feature = (IFeature) features.get(i);
988             try {
989                 computeFeatureSubtree(
990                     feature,
991                     null,
992                     null,
993                     false /* do not tolerate missing children */,
994                     null,
995                     null
996                 );
997             } catch (CoreException e) {
998                 status.add(e.getStatus());
999             }
1000        }
1001    }
1002
1003    /*
1004     * Verify that a parent of an optional child is configured before we allow
1005     * the child to be configured as well
1006     */

1007
1008    private static void checkOptionalChildConfiguring(
1009        IFeature feature,
1010        ArrayList JavaDoc status)
1011        throws CoreException {
1012        ILocalSite localSite = SiteManager.getLocalSite();
1013        IInstallConfiguration config = localSite.getCurrentConfiguration();
1014        IConfiguredSite[] csites = config.getConfiguredSites();
1015
1016        boolean included = false;
1017        for (int i = 0; i < csites.length; i++) {
1018            IConfiguredSite csite = csites[i];
1019            ISiteFeatureReference[] crefs =
1020                csite.getSite().getFeatureReferences();
1021            for (int j = 0; j < crefs.length; j++) {
1022                IFeatureReference cref = crefs[j];
1023                IFeature cfeature = null;
1024                try {
1025                    cfeature = cref.getFeature(null);
1026                } catch (CoreException e) {
1027                    //FIXME: cannot ask 'isOptional' here
1028
// Ignore missing optional feature.
1029
/*
1030                     * if (cref.isOptional()) continue;
1031                     */

1032                    throw e;
1033                }
1034                if (isParent(cfeature, feature, true)) {
1035                    // Included in at least one feature as optional
1036
included = true;
1037                    if (csite.isConfigured(cfeature)) {
1038                        // At least one feature parent
1039
// is enabled - it is OK to
1040
// configure optional child.
1041
return;
1042                    }
1043                }
1044            }
1045        }
1046        if (included) {
1047            // feature is included as optional but
1048
// no parent is currently configured.
1049
String JavaDoc msg = Messages.ActivityConstraints_optionalChild;
1050            status.add(createStatus(feature, FeatureStatus.CODE_OPTIONAL_CHILD, msg));
1051        } else {
1052            //feature is root - can be configured
1053
}
1054    }
1055//
1056
// /**
1057
// * Checks if the configuration is locked by other instances
1058
// *
1059
// * @param status
1060
// */
1061
// private static void checkConfigurationLock(ArrayList status) {
1062
// IPlatformConfiguration config =
1063
// BootLoader.getCurrentPlatformConfiguration();
1064
// URL configURL = config.getConfigurationLocation();
1065
// if (!"file".equals(configURL.getProtocol())) {
1066
// status.add(
1067
// createStatus(
1068
// null,
1069
// "Configuration location is not writable:" + configURL));
1070
// return;
1071
// }
1072
// String locationString = configURL.getFile();
1073
// File configDir = new File(locationString);
1074
// if (!configDir.isDirectory())
1075
// configDir = configDir.getParentFile();
1076
// if (!configDir.exists()) {
1077
// status.add(
1078
// createStatus(null, "Configuration location does not exist"));
1079
// return;
1080
// }
1081
// File locksDir = new File(configDir, "locks");
1082
// // check all the possible lock files
1083
// File[] lockFiles = locksDir.listFiles();
1084
// File configLock = BootLoader.getCurrentPlatformConfiguration().getLockFile();
1085
// for (int i = 0; i < lockFiles.length; i++) {
1086
// if (lockFiles[i].equals(configLock))
1087
// continue;
1088
// try {
1089
// RandomAccessFile raf = new RandomAccessFile(lockFiles[i], "rw");
1090
// FileChannel channel = raf.getChannel();
1091
// System.out.println(channel.isOpen());
1092
// FileLock lock = channel.tryLock();
1093
// if (lock == null){
1094
// // there is another eclipse instance running
1095
// raf.close();
1096
// status.add(
1097
// createStatus(
1098
// null,
1099
// "Another instance is running, please close it before performing any configuration operations"));
1100
// return;
1101
// }
1102
//
1103
// } catch (Exception e) {
1104
// status.add(createStatus(null, "Failed to create lock:"+lockFiles[i]));
1105
// return;
1106
// }
1107
// }
1108
// }
1109

1110    private static boolean isParent(
1111        IFeature candidate,
1112        IFeature feature,
1113        boolean optionalOnly)
1114        throws CoreException {
1115        IIncludedFeatureReference[] refs =
1116            candidate.getIncludedFeatureReferences();
1117        for (int i = 0; i < refs.length; i++) {
1118            IIncludedFeatureReference child = refs[i];
1119            VersionedIdentifier fvid = feature.getVersionedIdentifier();
1120            VersionedIdentifier cvid = child.getVersionedIdentifier();
1121
1122            if (fvid.getIdentifier().equals(cvid.getIdentifier()) == false)
1123                continue;
1124            // same ID
1125
PluginVersionIdentifier fversion = fvid.getVersion();
1126            PluginVersionIdentifier cversion = cvid.getVersion();
1127
1128            if (fversion.equals(cversion)) {
1129                // included and matched; return true if optionality is not
1130
// important or it is and the inclusion is optional
1131
return optionalOnly == false || child.isOptional();
1132            }
1133        }
1134        return false;
1135    }
1136
1137// private static boolean checkTimeline(
1138
// IInstallConfiguration config,
1139
// ArrayList status) {
1140
// try {
1141
// ILocalSite lsite = SiteManager.getLocalSite();
1142
// IInstallConfiguration cconfig = lsite.getCurrentConfiguration();
1143
// if (cconfig.getTimeline() != config.getTimeline()) {
1144
// // Not the same timeline - cannot revert
1145
// String msg =
1146
// UpdateUtils.getFormattedMessage(
1147
// KEY_WRONG_TIMELINE,
1148
// config.getLabel());
1149
// status.add(createStatus(null, FeatureStatus.CODE_OTHER, msg));
1150
// return false;
1151
// }
1152
// } catch (CoreException e) {
1153
// status.add(e.getStatus());
1154
// }
1155
// return true;
1156
// }
1157

1158    private static IStatus createMultiStatus(
1159        String JavaDoc message,
1160        ArrayList JavaDoc children,
1161        int code) {
1162        IStatus[] carray =
1163            (IStatus[]) children.toArray(new IStatus[children.size()]);
1164        return new MultiStatus(
1165            UpdateCore.getPlugin().getBundle().getSymbolicName(),
1166            code,
1167            carray,
1168            message,
1169            null);
1170    }
1171
1172    private static IStatus createStatus(IFeature feature, int errorCode, String JavaDoc message) {
1173
1174        String JavaDoc fullMessage;
1175        if (feature == null)
1176            fullMessage = message;
1177        else {
1178            PluginVersionIdentifier version =
1179                feature.getVersionedIdentifier().getVersion();
1180            fullMessage =
1181                NLS.bind(Messages.ActivityConstraints_childMessage, (new String JavaDoc[] {
1182                feature.getLabel(),
1183                version.toString(),
1184                message }));
1185        }
1186
1187        return new FeatureStatus(
1188            feature,
1189            IStatus.ERROR,
1190            UpdateCore.getPlugin().getBundle().getSymbolicName(),
1191            errorCode,
1192            fullMessage,
1193            null);
1194    }
1195
1196    // private static IStatus createReportStatus(ArrayList beforeStatus,
1197
// ArrayList status) {
1198
// // report status
1199
// if (status.size() > 0) {
1200
// if (beforeStatus.size() > 0)
1201
// return createMultiStatus(KEY_ROOT_MESSAGE_INIT,
1202
// beforeStatus,IStatus.ERROR);
1203
// else
1204
// return createMultiStatus(KEY_ROOT_MESSAGE, status,IStatus.ERROR);
1205
// }
1206
// return null;
1207
// }
1208

1209    private static IStatus createCombinedReportStatus(
1210        ArrayList JavaDoc beforeStatus,
1211        ArrayList JavaDoc status) {
1212        if (beforeStatus.size() == 0) { // good initial config
1213
if (status.size() == 0) {
1214                return null; // all fine
1215
} else {
1216                return createMultiStatus(Messages.ActivityConstraints_rootMessage,
1217                    status,
1218                    IStatus.ERROR);
1219                // error after operation
1220
}
1221        } else { // beforeStatus.size() > 0 : initial config errors
1222
if (status.size() == 0) {
1223                return null; // errors will be fixed
1224
} else {
1225                if (isBetterStatus(beforeStatus, status)) {
1226                    return createMultiStatus(
1227                        Messages.ActivityConstraints_warning,
1228                        beforeStatus,
1229                        IStatus.WARNING);
1230                    // errors may be fixed
1231
} else {
1232                    ArrayList JavaDoc combined = new ArrayList JavaDoc();
1233                    combined.add(
1234                        createMultiStatus(
1235                            Messages.ActivityConstraints_beforeMessage,
1236                            beforeStatus,
1237                            IStatus.ERROR));
1238                    combined.add(
1239                        createMultiStatus(
1240                            Messages.ActivityConstraints_afterMessage,
1241                            status,
1242                            IStatus.ERROR));
1243                    return createMultiStatus(
1244                        Messages.ActivityConstraints_rootMessageInitial,
1245                        combined,
1246                        IStatus.ERROR);
1247                }
1248            }
1249        }
1250    }
1251
1252    private static ArrayList JavaDoc createList(String JavaDoc commaSeparatedList) {
1253        ArrayList JavaDoc list = new ArrayList JavaDoc();
1254        if (commaSeparatedList != null) {
1255            StringTokenizer JavaDoc t =
1256                new StringTokenizer JavaDoc(commaSeparatedList.trim(), ","); //$NON-NLS-1$
1257
while (t.hasMoreTokens()) {
1258                String JavaDoc token = t.nextToken().trim();
1259                if (!token.equals("")) //$NON-NLS-1$
1260
list.add(token);
1261            }
1262        }
1263        return list;
1264    }
1265
1266    /**
1267     * Returns true if status is a subset of beforeStatus
1268     *
1269     * @param beforeStatus
1270     * @param status
1271     * @return
1272     */

1273    private static boolean isBetterStatus(
1274        ArrayList JavaDoc beforeStatus,
1275        ArrayList JavaDoc status) {
1276        // if no status at all, then it's a subset
1277
if (status == null || status.size() == 0)
1278            return true;
1279        // there is some status, so if there is no initial status, then it's
1280
// not a subset
1281
if (beforeStatus == null || beforeStatus.size() == 0)
1282            return false;
1283        // quick check
1284
if (beforeStatus.size() < status.size())
1285            return false;
1286
1287        // check if all the status elements appear in the original status
1288
for (int i = 0; i < status.size(); i++) {
1289            IStatus s = (IStatus) status.get(i);
1290            // if this is not a feature status, something is wrong, so return
1291
// false
1292
if (!(s instanceof FeatureStatus))
1293                return false;
1294            FeatureStatus fs = (FeatureStatus) s;
1295            // check against all status elements
1296
boolean found = false;
1297            for (int j = 0; !found && j < beforeStatus.size(); j++) {
1298                if (fs.equals(beforeStatus.get(j)))
1299                    found = true;
1300            }
1301            if (!found)
1302                return false;
1303        }
1304        return true;
1305    }
1306    
1307    public class RequiredFeaturesResult {
1308        
1309        private IStatus status;
1310        private Set JavaDoc requiredFeatures;
1311        
1312        public Set JavaDoc getRequiredFeatures() {
1313            return requiredFeatures;
1314        }
1315        public void setRequiredFeatures(Set JavaDoc requiredFeatures) {
1316            this.requiredFeatures = requiredFeatures;
1317        }
1318        public void addRequiredFeatures(Set JavaDoc requiredFeatures) {
1319            if (requiredFeatures == null) {
1320                requiredFeatures = new HashSet JavaDoc();
1321            }
1322            this.requiredFeatures.addAll(requiredFeatures);
1323        }
1324        public IStatus getStatus() {
1325            return status;
1326        }
1327        public void setStatus(IStatus status) {
1328            this.status = status;
1329        }
1330        
1331        
1332    }
1333    
1334    public static class InternalImport {
1335        
1336        private IImport iimport;
1337
1338        public InternalImport(IImport iimport) {
1339            this.iimport = iimport;
1340        }
1341        
1342        public IImport getImport() {
1343            return iimport;
1344        }
1345
1346        public void setImport(IImport iimport) {
1347            this.iimport = iimport;
1348        }
1349        
1350        public boolean equals(Object JavaDoc object) {
1351
1352            if ( ( object == null) || !(object instanceof InternalImport))
1353                return false;
1354            
1355            if ( object == this)
1356                return true;
1357            
1358            return iimport.getVersionedIdentifier().equals( ((InternalImport)object).getImport().getVersionedIdentifier()) && (getImport().getRule() == ((InternalImport)object).getImport().getRule());
1359
1360        }
1361
1362        public int hashCode() {
1363            return iimport.getVersionedIdentifier().hashCode() * iimport.getRule();
1364        }
1365        
1366    }
1367
1368}
1369
Popular Tags