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