/******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.internal.operations;

//import java.io.*;
//import java.net.*;
//import java.nio.channels.*;
import java.io.*;
import java.net.*;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.update.configuration.*;
import org.eclipse.update.configurator.*;
import org.eclipse.update.core.*;
import org.eclipse.update.internal.configurator.PlatformConfiguration;
import org.eclipse.update.internal.core.*;
import org.eclipse.update.operations.*;

/**
 *  
 */
public class OperationValidator implements IOperationValidator {
	private static final String KEY_ROOT_MESSAGE =
		"ActivityConstraints.rootMessage"; //$NON-NLS-1$
	private static final String KEY_ROOT_MESSAGE_INIT =
		"ActivityConstraints.rootMessageInitial"; //$NON-NLS-1$
	private static final String KEY_CHILD_MESSAGE =
		"ActivityConstraints.childMessage"; //$NON-NLS-1$
	private static final String KEY_PLATFORM = "ActivityConstraints.platform"; //$NON-NLS-1$
	private static final String KEY_PRIMARY = "ActivityConstraints.primary"; //$NON-NLS-1$
	private static final String KEY_OS = "ActivityConstraints.os"; //$NON-NLS-1$
	private static final String KEY_WS = "ActivityConstraints.ws"; //$NON-NLS-1$
	private static final String KEY_ARCH = "ActivityConstraints.arch"; //$NON-NLS-1$
	private static final String KEY_PREREQ = "ActivityConstraints.prereq"; //$NON-NLS-1$
	private static final String KEY_PREREQ_PLUGIN =
		"ActivityConstaints.prereq.plugin"; //$NON-NLS-1$
	private static final String KEY_PREREQ_FEATURE =
		"ActivityConstaints.prereq.feature"; //$NON-NLS-1$
	private static final String KEY_PREREQ_PERFECT =
		"ActivityConstraints.prereqPerfect"; //$NON-NLS-1$
	private static final String KEY_PREREQ_EQUIVALENT =
		"ActivityConstraints.prereqEquivalent"; //$NON-NLS-1$
	private static final String KEY_PREREQ_COMPATIBLE =
		"ActivityConstraints.prereqCompatible"; //$NON-NLS-1$
	private static final String KEY_PREREQ_GREATER =
		"ActivityConstraints.prereqGreaterOrEqual"; //$NON-NLS-1$
	private static final String KEY_OPTIONAL_CHILD =
		"ActivityConstraints.optionalChild"; //$NON-NLS-1$
	private static final String KEY_CYCLE = "ActivityConstraints.cycle"; //$NON-NLS-1$
	private static final String KEY_CONFLICT = "ActivityConstraints.conflict"; //$NON-NLS-1$
	private static final String KEY_EXCLUSIVE = "ActivityConstraints.exclusive"; //$NON-NLS-1$
	private static final String KEY_NO_LICENSE =
		"ActivityConstraints.noLicense"; //$NON-NLS-1$

	/**
	 * Checks if the platform configuration has been modified outside this program.
	 * @return the error status, or null if no errors
	 */
	public IStatus validatePlatformConfigValid() {
		ArrayList status = new ArrayList(1);
		checkPlatformWasModified(status);
		
		// report status
		if (status.size() > 0)
			return createMultiStatus(KEY_ROOT_MESSAGE, status, IStatus.ERROR);
		return null;
	}
	
	/*
	 * Called by UI before performing operation. Returns null if no errors, a
	 * status with IStatus.WARNING code when the initial configuration is
	 * broken, or a status with IStatus.ERROR when there the operation
	 * introduces new errors
	 */
	public IStatus validatePendingInstall(
		IFeature oldFeature,
		IFeature newFeature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateInstall(oldFeature, newFeature, status);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}

	/*
	 * Called by UI before performing operation
	 */
	public IStatus validatePendingUnconfig(IFeature feature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateUnconfigure(feature, status);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}

	/*
	 * Called by UI before performing operation
	 */
	public IStatus validatePendingConfig(IFeature feature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateConfigure(feature, status);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}

	/**
	 * Called before performing operation.
	 */
	public IStatus validatePendingReplaceVersion(
		IFeature feature,
		IFeature anotherFeature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateReplaceVersion(feature, anotherFeature, status);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}


	/*
	 * Called by the UI before doing a revert/ restore operation
	 */
	public IStatus validatePendingRevert(IInstallConfiguration config) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateRevert(config, status);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}

	/*
	 * Called by the UI before doing a batched processing of several pending
	 * changes.
	 */
	public IStatus validatePendingChanges(IInstallFeatureOperation[] jobs) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);
		checkPlatformWasModified(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validatePendingChanges(jobs, status, beforeStatus);

		// report status
		return createCombinedReportStatus(beforeStatus, status);
	}

	/*
	 * Check the current state.
	 */
	public IStatus validateCurrentState() {
		// check the state
		ArrayList status = new ArrayList();
		checkPlatformWasModified(status);
		validateInitialState(status);

		// report status
		if (status.size() > 0)
			return createMultiStatus(KEY_ROOT_MESSAGE, status, IStatus.ERROR);
		return null;
	}

	/*
	 * Check to see if we are not broken even before we start
	 */
	private static void validateInitialState(ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			// uncomment this when patch released in boot
			//checkConfigurationLock(status);
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle unconfigure
	 */
	private static void validateUnconfigure(
		IFeature feature,
		ArrayList status) {
		try {
			checkSiteReadOnly(feature,status);
			ArrayList features = computeFeatures();
			features = computeFeaturesAfterOperation(features, null, feature);
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}


	/*
	 * handle configure
	 */
	private static void validateConfigure(IFeature feature, ArrayList status) {
		try {
			checkSiteReadOnly(feature,status);
			ArrayList features = computeFeatures();
			checkOptionalChildConfiguring(feature, status);
			checkForCycles(feature, null, features);
			features = computeFeaturesAfterOperation(features, feature, null);
			checkConstraints(features, status);

		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle replace version
	 */
	private static void validateReplaceVersion(
		IFeature feature,
		IFeature anotherFeature,
		ArrayList status) {
		try {
			checkSiteReadOnly(feature,status);
			ArrayList features = computeFeatures();
			checkForCycles(feature, null, features);
			features =
				computeFeaturesAfterOperation(
					features,
					anotherFeature,
					feature);
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle install and update
	 */
	private static void validateInstall(
		IFeature oldFeature,
		IFeature newFeature,
		ArrayList status) {
		try {
			checkSiteReadOnly(oldFeature,status);
			ArrayList features = computeFeatures();
			checkForCycles(newFeature, null, features);
			features =
				computeFeaturesAfterOperation(features, newFeature, oldFeature);
			checkConstraints(features, status);
			checkLicense(newFeature, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle revert and restore
	 */
	private static void validateRevert(
		IInstallConfiguration config,
		ArrayList status) {
		try {
//			// check the timeline and don't bother
//			// to check anything else if negative
//			if (!checkTimeline(config, status))
//				return;
			ArrayList features = computeFeaturesAfterRevert(config);
			checkConstraints(features, status);
			checkRevertConstraints(features, status);

		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}


	/*
	 * Handle one-click changes as a batch
	 */
	private static void validatePendingChanges(
		IInstallFeatureOperation[] jobs,
		ArrayList status,
		ArrayList beforeStatus) {
		try {
			ArrayList features = computeFeatures();
			ArrayList savedFeatures = features;
			int nexclusives = 0;

			// pass 1: see if we can process the entire "batch"
			ArrayList tmpStatus = new ArrayList();
			for (int i = 0; i < jobs.length; i++) {
				IInstallFeatureOperation job = jobs[i];

				IFeature newFeature = job.getFeature();
				IFeature oldFeature = job.getOldFeature();
				checkLicense(newFeature, status);
				if (jobs.length > 1 && newFeature.isExclusive()) {
					nexclusives++;
					status.add(
						createStatus(
							newFeature,
							FeatureStatus.CODE_EXCLUSIVE,
							Policy.bind(KEY_EXCLUSIVE)));
					continue;
				}
				checkForCycles(newFeature, null, features);
				features =
					computeFeaturesAfterOperation(
						features,
						newFeature,
						oldFeature);
			}
			if (nexclusives > 0)
				return;
			checkConstraints(features, tmpStatus);
			if (tmpStatus.size() == 0) // the whole "batch" is OK
				return;

			// pass 2: we have conflicts
			features = savedFeatures;
			for (int i = 0; i < jobs.length; i++) {
				IInstallFeatureOperation job = jobs[i];
				IFeature newFeature = job.getFeature();
				IFeature oldFeature = job.getOldFeature();

				features =
					computeFeaturesAfterOperation(
						features,
						newFeature,
						oldFeature);

				checkConstraints(features, status);
				if (status.size() > 0
					&& !isBetterStatus(beforeStatus, status)) {
					IStatus conflict =
						createStatus(
							newFeature,
							FeatureStatus.CODE_OTHER,
							Policy.bind(KEY_CONFLICT));
					status.add(0, conflict);
					return;
				}
			}
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}
	
	private static void checkPlatformWasModified(ArrayList status) {
		try {
			// checks if the platform has been modified outside this eclipse instance
			IPlatformConfiguration platformConfig = ConfiguratorUtils.getCurrentPlatformConfiguration();
			
			long currentTimeStamp = platformConfig.getChangeStamp();
			// get the last modified value for this config, from this process point of view
			if (platformConfig instanceof PlatformConfiguration) 
				currentTimeStamp = ((PlatformConfiguration)platformConfig).getConfiguration().lastModified();
				
			// get the real last modified value
			URL platformXML = platformConfig.getConfigurationLocation();
			long actualTimeStamp = currentTimeStamp;
			if ("file".equals(platformXML.getProtocol())) //$NON-NLS-1$
				actualTimeStamp = new File(platformXML.getFile()).lastModified();
			else {
				URLConnection connection = platformXML.openConnection();
				actualTimeStamp = connection.getLastModified();
			}
			if (currentTimeStamp != actualTimeStamp)
				status.add(createStatus(
								null,
								FeatureStatus.CODE_OTHER,
								Policy.bind("ActivityConstraints.platformModified"))); //$NON-NLS-1$
		} catch (IOException e) {
			// ignore
		}
	}
	
	private static void checkSiteReadOnly(IFeature feature, ArrayList status) {
		if(feature == null){
			return;
		}
		IConfiguredSite csite = feature.getSite().getCurrentConfiguredSite();
		if (csite != null && !csite.isUpdatable())
			status.add(createStatus(feature, FeatureStatus.CODE_OTHER,
					Policy
					.bind("ActivityConstraints.readOnly", //$NON-NLS-1$
							csite.getSite().getURL().toExternalForm())));
	}

	/*
	 * Compute a list of configured features
	 */
	private static ArrayList computeFeatures() throws CoreException {
		return computeFeatures(true);
	}
	/*
	 * Compute a list of configured features
	 */
	private static ArrayList computeFeatures(boolean configuredOnly)
		throws CoreException {
		ArrayList features = new ArrayList();
		ILocalSite localSite = SiteManager.getLocalSite();
		IInstallConfiguration config = localSite.getCurrentConfiguration();
		IConfiguredSite[] csites = config.getConfiguredSites();

		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];

			IFeatureReference[] crefs;

			if (configuredOnly)
				crefs = csite.getConfiguredFeatures();
			else
				crefs = csite.getSite().getFeatureReferences();
			for (int j = 0; j < crefs.length; j++) {
				IFeatureReference cref = crefs[j];
				IFeature cfeature = cref.getFeature(null);
				features.add(cfeature);
			}
		}

		return features;
	}

	/*
	 * Compute the nested feature subtree starting at the specified base
	 * feature
	 */
	private static ArrayList computeFeatureSubtree(
			IFeature top,
			IFeature feature,
			ArrayList features,
			boolean tolerateMissingChildren,
			ArrayList configuredFeatures,
			ArrayList visitedFeatures)
	throws CoreException {

		// check arguments
		if (top == null)
			return features;
		if (feature == null)
			feature = top;
		if (features == null)
			features = new ArrayList();
		if (visitedFeatures == null)
			visitedFeatures = new ArrayList();

		// check for <includes> cycle
		if (visitedFeatures.contains(feature)) {
			IStatus status =
			createStatus(top, FeatureStatus.CODE_CYCLE, Policy.bind(KEY_CYCLE));
			throw new CoreException(status);
		} else {
			// keep track of visited features so we can detect cycles
			visitedFeatures.add(feature);
		}

		// return specified base feature and all its children
		if (!features.contains(feature))
			features.add(feature);
		IIncludedFeatureReference[] children =
		feature.getIncludedFeatureReferences();
		for (int i = 0; i < children.length; i++) {
			try {
				IFeature child = children[i].getFeature(null);
				features =
				computeFeatureSubtree(
						top,
						child,
						features,
						tolerateMissingChildren,
						null,
						visitedFeatures);
			} catch (CoreException e) {
				if (!children[i].isOptional() && !tolerateMissingChildren)
					throw e;
			}
		}
		// no cycles for this feature during DFS
		visitedFeatures.remove(feature);
		return features;
	}

	private static void checkLicense(IFeature feature, ArrayList status) {
		IURLEntry licenseEntry = feature.getLicense();
		if (licenseEntry != null) {
			String license = licenseEntry.getAnnotation();
			if (license != null && license.trim().length() > 0)
				return;
		}
		status.add(
			createStatus(feature, FeatureStatus.CODE_OTHER, Policy.bind(KEY_NO_LICENSE)));
	}

	/*
	 * Compute a list of features that will be configured after the operation
	 */
	private static ArrayList computeFeaturesAfterOperation(
		ArrayList features,
		IFeature add,
		IFeature remove)
		throws CoreException {

		ArrayList addTree = computeFeatureSubtree(add, null, null, false,
		/* do not tolerate missing children */
		features, null);
		ArrayList removeTree =
			computeFeatureSubtree(
				remove,
				null,
				null,
				true /* tolerate missing children */,
				null,
				null
		);
		if (remove != null) {
			// Patches to features are removed together with
			// those features. Include them in the list.
			contributePatchesFor(removeTree, features, removeTree);
		}

		if (remove != null)
			features.removeAll(removeTree);

		if (add != null)
			features.addAll(addTree);

		return features;
	}

	private static void contributePatchesFor(
		ArrayList removeTree,
		ArrayList features,
		ArrayList result)
		throws CoreException {

		for (int i = 0; i < removeTree.size(); i++) {
			IFeature feature = (IFeature) removeTree.get(i);
			contributePatchesFor(feature, features, result);
		}
	}

	private static void contributePatchesFor(
		IFeature feature,
		ArrayList features,
		ArrayList result)
		throws CoreException {
		for (int i = 0; i < features.size(); i++) {
			IFeature candidate = (IFeature) features.get(i);
			if (UpdateUtils.isPatch(feature, candidate)) {
				ArrayList removeTree =
					computeFeatureSubtree(candidate, null, null, true,null,null);
				result.addAll(removeTree);
			}
		}
	}

	/*
	 * Compute a list of features that will be configured after performing the
	 * revert
	 */
	private static ArrayList computeFeaturesAfterRevert(IInstallConfiguration config)
		throws CoreException {

		ArrayList list = new ArrayList();
		IConfiguredSite[] csites = config.getConfiguredSites();
		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];
			IFeatureReference[] features = csite.getConfiguredFeatures();
			for (int j = 0; j < features.length; j++) {
				list.add(features[j].getFeature(null));
			}
		}
		return list;
	}



	/*
	 * Compute a list of plugin entries for the specified features.
	 */
	private static ArrayList computePluginsForFeatures(ArrayList features)
		throws CoreException {
		if (features == null)
			return new ArrayList();

		HashMap plugins = new HashMap();
		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			IPluginEntry[] entries = feature.getPluginEntries();
			for (int j = 0; j < entries.length; j++) {
				IPluginEntry entry = entries[j];
				plugins.put(entry.getVersionedIdentifier(), entry);
			}
		}
		ArrayList result = new ArrayList();
		result.addAll(plugins.values());
		return result;
	}


	/**
	 * Check for feature cycles:
	 * - visit feature
	 * - if feature is in the cycle candidates list, then cycle found, else add it to candidates list
	 * - DFS children 
	 * - when return from DFS remove the feature from the candidates list
	 */
	private static void checkForCycles(
			IFeature feature,
			ArrayList candidates,
			ArrayList configuredFeatures)
	throws CoreException {

		// check arguments
		if (feature == null)
			return;
		if (configuredFeatures == null)
			configuredFeatures = new ArrayList();
		if (candidates == null)
			candidates = new ArrayList();
		
		// check for <includes> cycle
		if (candidates.contains(feature)) {
			String msg = Policy.bind(
					KEY_CYCLE, 
					new String[] {feature.getLabel(), 
							feature.getVersionedIdentifier().toString()});
			IStatus status = createStatus(feature, FeatureStatus.CODE_CYCLE, msg);
			throw new CoreException(status);
		}

		// potential candidate
		candidates.add(feature);
		
		// recursively, check cycles with children
		IIncludedFeatureReference[] children =
		feature.getIncludedFeatureReferences();
		for (int i = 0; i < children.length; i++) {
			try {
				IFeature child = children[i].getFeature(null);
				checkForCycles(child, candidates, configuredFeatures);
			} catch (CoreException e) {
				if (!children[i].isOptional())
					throw e;
			}
		}
		// no longer a candidate, because no cycles with children
		candidates.remove(feature);
	}
	
	/*
	 * validate constraints
	 */
	private static void checkConstraints(ArrayList features, ArrayList status)
		throws CoreException {
		if (features == null)
			return;

		ArrayList plugins = computePluginsForFeatures(features);

		checkEnvironment(features, status);
		checkPlatformFeature(features, plugins, status);
		checkPrimaryFeature(features, status);
		checkPrereqs(features, plugins, status);
	}

	/*
	 * Verify all features are either portable, or match the current
	 * environment
	 */
	private static void checkEnvironment(
		ArrayList features,
		ArrayList status) {

		String os = Platform.getOS();
		String ws = Platform.getWS();
		String arch = Platform.getOSArch();

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			ArrayList fos = createList(feature.getOS());
			ArrayList fws = createList(feature.getWS());
			ArrayList farch = createList(feature.getOSArch());

			if (fos.size() > 0) {
				if (!fos.contains(os)) {
					IStatus s =
						createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Policy.bind(KEY_OS));
					if (!status.contains(s))
						status.add(s);
					continue;
				}
			}

			if (fws.size() > 0) {
				if (!fws.contains(ws)) {
					IStatus s =
						createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Policy.bind(KEY_WS));
					if (!status.contains(s))
						status.add(s);
					continue;
				}
			}

			if (farch.size() > 0) {
				if (!farch.contains(arch)) {
					IStatus s =
						createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Policy.bind(KEY_ARCH));
					if (!status.contains(s))
						status.add(s);
					continue;
				}
			}
		}
	}

	/*
	 * Verify we end up with a version of platform configured
	 */
	private static void checkPlatformFeature(
		ArrayList features,
		ArrayList plugins,
		ArrayList status) {

		String[] bootstrapPlugins =
			ConfiguratorUtils
				.getCurrentPlatformConfiguration()
				.getBootstrapPluginIdentifiers();

		for (int i = 0; i < bootstrapPlugins.length; i++) {
			boolean found = false;
			for (int j = 0; j < plugins.size(); j++) {
				IPluginEntry plugin = (IPluginEntry) plugins.get(j);
				if (bootstrapPlugins[i]
					.equals(plugin.getVersionedIdentifier().getIdentifier())) {
					found = true;
					break;
				}
			}
			if (!found) {
				IStatus s =
					createStatus(null, FeatureStatus.CODE_OTHER, Policy.bind(KEY_PLATFORM));
				if (!status.contains(s))
					status.add(s);

				return;
			}
		}
	}

	/*
	 * Verify we end up with a version of primary feature configured
	 */
	private static void checkPrimaryFeature(
		ArrayList features,
		ArrayList status) {

		String featureId =
			ConfiguratorUtils
				.getCurrentPlatformConfiguration()
				.getPrimaryFeatureIdentifier();
		
		if (featureId == null)
			return; // no existing primary feature, nothing to worry about

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			if (featureId
				.equals(feature.getVersionedIdentifier().getIdentifier()))
				return;
		}

		IStatus s = createStatus(null, FeatureStatus.CODE_OTHER, Policy.bind(KEY_PRIMARY));
		if (!status.contains(s))
			status.add(s);
	}

	/*
	 * Verify we do not break prereqs
	 */
	private static void checkPrereqs(
		ArrayList features,
		ArrayList plugins,
		ArrayList status) {

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			IImport[] imports = feature.getImports();

			for (int j = 0; j < imports.length; j++) {
				IImport iimport = imports[j];
				// for each import determine plugin or feature, version, match
				// we need
				VersionedIdentifier iid = iimport.getVersionedIdentifier();
				String id = iid.getIdentifier();
				PluginVersionIdentifier version = iid.getVersion();
				boolean featurePrereq =
					iimport.getKind() == IImport.KIND_FEATURE;
				boolean ignoreVersion =
					version.getMajorComponent() == 0
						&& version.getMinorComponent() == 0
						&& version.getServiceComponent() == 0;
				int rule = iimport.getRule();
				if (rule == IImport.RULE_NONE)
					rule = IImport.RULE_COMPATIBLE;

				boolean found = false;

				ArrayList candidates;

				if (featurePrereq)
					candidates = features;
				else
					candidates = plugins;
				for (int k = 0; k < candidates.size(); k++) {
					VersionedIdentifier cid;
					if (featurePrereq) {
						// the candidate is a feature
						IFeature candidate = (IFeature) candidates.get(k);
						// skip self
						if (feature.equals(candidate))
							continue;
						cid = candidate.getVersionedIdentifier();
					} else {
						// the candidate is a plug-in
						IPluginEntry plugin = (IPluginEntry) candidates.get(k);
						cid = plugin.getVersionedIdentifier();
					}
					PluginVersionIdentifier cversion = cid.getVersion();
					if (id.equals(cid.getIdentifier())) {
						// have a candidate
						if (ignoreVersion)
							found = true;
						else if (
							rule == IImport.RULE_PERFECT
								&& cversion.isPerfect(version))
							found = true;
						else if (
							rule == IImport.RULE_EQUIVALENT
								&& cversion.isEquivalentTo(version))
							found = true;
						else if (
							rule == IImport.RULE_COMPATIBLE
								&& cversion.isCompatibleWith(version))
							found = true;
						else if (
							rule == IImport.RULE_GREATER_OR_EQUAL
								&& cversion.isGreaterOrEqualTo(version))
							found = true;
					}
					if (found)
						break;
				}

				if (!found) {
					// report status
					String target =
						featurePrereq
							? Policy.bind(KEY_PREREQ_FEATURE)
							: Policy.bind(KEY_PREREQ_PLUGIN);
					int errorCode = featurePrereq
							? FeatureStatus.CODE_PREREQ_FEATURE
							: FeatureStatus.CODE_PREREQ_PLUGIN;
					String msg =
						Policy.bind(
							KEY_PREREQ,
							new String[] { target, id });

					if (!ignoreVersion) {
						if (rule == IImport.RULE_PERFECT)
							msg =
								Policy.bind(
									KEY_PREREQ_PERFECT,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_EQUIVALENT)
							msg =
								Policy.bind(
									KEY_PREREQ_EQUIVALENT,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_COMPATIBLE)
							msg =
								Policy.bind(
									KEY_PREREQ_COMPATIBLE,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_GREATER_OR_EQUAL)
							msg =
								Policy.bind(
									KEY_PREREQ_GREATER,
									new String[] {
										target,
										id,
										version.toString()});
					}
					IStatus s = createStatus(feature, errorCode, msg);
					if (!status.contains(s))
						status.add(s);
				}
			}
		}
	}

	/*
	 * Verify we end up with valid nested features after revert
	 */
	private static void checkRevertConstraints(
		ArrayList features,
		ArrayList status) {

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			try {
				computeFeatureSubtree(
					feature,
					null,
					null,
					false /* do not tolerate missing children */,
					null,
					null
				);
			} catch (CoreException e) {
				status.add(e.getStatus());
			}
		}
	}

	/*
	 * Verify that a parent of an optional child is configured before we allow
	 * the child to be configured as well
	 */

	private static void checkOptionalChildConfiguring(
		IFeature feature,
		ArrayList status)
		throws CoreException {
		ILocalSite localSite = SiteManager.getLocalSite();
		IInstallConfiguration config = localSite.getCurrentConfiguration();
		IConfiguredSite[] csites = config.getConfiguredSites();

		boolean included = false;
		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];
			ISiteFeatureReference[] crefs =
				csite.getSite().getFeatureReferences();
			for (int j = 0; j < crefs.length; j++) {
				IFeatureReference cref = crefs[j];
				IFeature cfeature = null;
				try {
					cfeature = cref.getFeature(null);
				} catch (CoreException e) {
					//FIXME: cannot ask 'isOptional' here
					// Ignore missing optional feature.
					/*
					 * if (cref.isOptional()) continue;
					 */
					throw e;
				}
				if (isParent(cfeature, feature, true)) {
					// Included in at least one feature as optional
					included = true;
					if (csite.isConfigured(cfeature)) {
						// At least one feature parent
						// is enabled - it is OK to
						// configure optional child.
						return;
					}
				}
			}
		}
		if (included) {
			// feature is included as optional but
			// no parent is currently configured.
			String msg = Policy.bind(KEY_OPTIONAL_CHILD);
			status.add(createStatus(feature, FeatureStatus.CODE_OPTIONAL_CHILD, msg));
		} else {
			//feature is root - can be configured
		}
	}
//
//	/**
//	 * Checks if the configuration is locked by other instances
//	 * 
//	 * @param status
//	 */
//	private static void checkConfigurationLock(ArrayList status) {
//		IPlatformConfiguration config =
//			BootLoader.getCurrentPlatformConfiguration();
//		URL configURL = config.getConfigurationLocation();
//		if (!"file".equals(configURL.getProtocol())) {
//			status.add(
//				createStatus(
//					null,
//					"Configuration location is not writable:" + configURL));
//			return;
//		}
//		String locationString = configURL.getFile();
//		File configDir = new File(locationString);
//		if (!configDir.isDirectory())
//			configDir = configDir.getParentFile();
//		if (!configDir.exists()) {
//			status.add(
//				createStatus(null, "Configuration location does not exist"));
//			return;
//		}
//		File locksDir = new File(configDir, "locks");
//		// check all the possible lock files
//		File[] lockFiles = locksDir.listFiles();
//		File configLock = BootLoader.getCurrentPlatformConfiguration().getLockFile();
//		for (int i = 0; i < lockFiles.length; i++) {
//			if (lockFiles[i].equals(configLock))
//				continue;
//			try {
//				RandomAccessFile raf = new RandomAccessFile(lockFiles[i], "rw");
//				FileChannel channel = raf.getChannel();
//				System.out.println(channel.isOpen());
//				FileLock lock = channel.tryLock();
//				if (lock == null){
//					// there is another eclipse instance running
//					raf.close();
//					status.add(
//						createStatus(
//							null,
//							"Another instance is running, please close it before performing any configuration operations"));
//					return;
//				}
//
//			} catch (Exception e) {
//				status.add(createStatus(null, "Failed to create lock:"+lockFiles[i]));
//				return;
//			} 
//		}
//	}

	private static boolean isParent(
		IFeature candidate,
		IFeature feature,
		boolean optionalOnly)
		throws CoreException {
		IIncludedFeatureReference[] refs =
			candidate.getIncludedFeatureReferences();
		for (int i = 0; i < refs.length; i++) {
			IIncludedFeatureReference child = refs[i];
			VersionedIdentifier fvid = feature.getVersionedIdentifier();
			VersionedIdentifier cvid = child.getVersionedIdentifier();

			if (fvid.getIdentifier().equals(cvid.getIdentifier()) == false)
				continue;
			// same ID
			PluginVersionIdentifier fversion = fvid.getVersion();
			PluginVersionIdentifier cversion = cvid.getVersion();

			if (fversion.equals(cversion)) {
				// included and matched; return true if optionality is not
				// important or it is and the inclusion is optional
				return optionalOnly == false || child.isOptional();
			}
		}
		return false;
	}

//	private static boolean checkTimeline(
//		IInstallConfiguration config,
//		ArrayList status) {
//		try {
//			ILocalSite lsite = SiteManager.getLocalSite();
//			IInstallConfiguration cconfig = lsite.getCurrentConfiguration();
//			if (cconfig.getTimeline() != config.getTimeline()) {
//				// Not the same timeline - cannot revert
//				String msg =
//					UpdateUtils.getFormattedMessage(
//						KEY_WRONG_TIMELINE,
//						config.getLabel());
//				status.add(createStatus(null, FeatureStatus.CODE_OTHER, msg));
//				return false;
//			}
//		} catch (CoreException e) {
//			status.add(e.getStatus());
//		}
//		return true;
//	}

	private static IStatus createMultiStatus(
		String rootKey,
		ArrayList children,
		int code) {
		IStatus[] carray =
			(IStatus[]) children.toArray(new IStatus[children.size()]);
		String message = Policy.bind(rootKey);
		return new MultiStatus(
			UpdateCore.getPlugin().getBundle().getSymbolicName(),
			code,
			carray,
			message,
			null);
	}

	private static IStatus createStatus(IFeature feature, int errorCode, String message) {

		String fullMessage;
		if (feature == null)
			fullMessage = message;
		else {
			PluginVersionIdentifier version =
				feature.getVersionedIdentifier().getVersion();
			fullMessage =
				Policy.bind(
					KEY_CHILD_MESSAGE,
					new String[] {
						feature.getLabel(),
						version.toString(),
						message });
		}

		return new FeatureStatus(
			feature,
			IStatus.ERROR,
			UpdateCore.getPlugin().getBundle().getSymbolicName(),
			errorCode,
			fullMessage,
			null);
	}

	//	private static IStatus createReportStatus(ArrayList beforeStatus,
	// ArrayList status) {
	//		// report status
	//		if (status.size() > 0) {
	//			if (beforeStatus.size() > 0)
	//				return createMultiStatus(KEY_ROOT_MESSAGE_INIT,
	// beforeStatus,IStatus.ERROR);
	//			else
	//				return createMultiStatus(KEY_ROOT_MESSAGE, status,IStatus.ERROR);
	//		}
	//		return null;
	//	}

	private static IStatus createCombinedReportStatus(
		ArrayList beforeStatus,
		ArrayList status) {
		if (beforeStatus.size() == 0) { // good initial config
			if (status.size() == 0) {
				return null; // all fine
			} else {
				return createMultiStatus(
					KEY_ROOT_MESSAGE,
					status,
					IStatus.ERROR);
				// error after operation
			}
		} else { // beforeStatus.size() > 0 : initial config errors
			if (status.size() == 0) {
				return null; // errors will be fixed
			} else {
				if (isBetterStatus(beforeStatus, status)) {
					return createMultiStatus(
						"ActivityConstraints.warning", //$NON-NLS-1$
						beforeStatus,
						IStatus.WARNING);
					// errors may be fixed
				} else {
					ArrayList combined = new ArrayList();
					combined.add(
						createMultiStatus(
							"ActivityConstraints.beforeMessage", //$NON-NLS-1$
							beforeStatus,
							IStatus.ERROR));
					combined.add(
						createMultiStatus(
							"ActivityConstraints.afterMessage", //$NON-NLS-1$
							status,
							IStatus.ERROR));
					return createMultiStatus(
						KEY_ROOT_MESSAGE_INIT,
						combined,
						IStatus.ERROR);
				}
			}
		}
	}

	private static ArrayList createList(String commaSeparatedList) {
		ArrayList list = new ArrayList();
		if (commaSeparatedList != null) {
			StringTokenizer t =
				new StringTokenizer(commaSeparatedList.trim(), ","); //$NON-NLS-1$
			while (t.hasMoreTokens()) {
				String token = t.nextToken().trim();
				if (!token.equals("")) //$NON-NLS-1$
					list.add(token);
			}
		}
		return list;
	}

	/**
	 * Returns true if status is a subset of beforeStatus
	 * 
	 * @param beforeStatus
	 * @param status
	 * @return
	 */
	private static boolean isBetterStatus(
		ArrayList beforeStatus,
		ArrayList status) {
		// if no status at all, then it's a subset
		if (status == null || status.size() == 0)
			return true;
		// there is some status, so if there is no initial status, then it's
		// not a subset
		if (beforeStatus == null || beforeStatus.size() == 0)
			return false;
		// quick check
		if (beforeStatus.size() < status.size())
			return false;

		// check if all the status elements appear in the original status
		for (int i = 0; i < status.size(); i++) {
			IStatus s = (IStatus) status.get(i);
			// if this is not a feature status, something is wrong, so return
			// false
			if (!(s instanceof FeatureStatus))
				return false;
			FeatureStatus fs = (FeatureStatus) s;
			// check against all status elements
			boolean found = false;
			for (int j = 0; !found && j < beforeStatus.size(); j++) {
				if (fs.equals(beforeStatus.get(j)))
					found = true;
			}
			if (!found)
				return false;
		}
		return true;
	}

}