/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-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 org.eclipse.update.core.IUpdateConstants;

import org.eclipse.osgi.service.resolver.PlatformAdmin;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.configuration.*;
import org.eclipse.update.configurator.ConfiguratorUtils;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.eclipse.update.core.*;
import org.eclipse.update.internal.configurator.PlatformConfiguration;
import org.eclipse.update.internal.core.Messages;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.operations.IInstallFeatureOperation;
import org.eclipse.update.operations.IOperationValidator;
import org.osgi.framework.*;

/**
 *  
 */
public class OperationValidator implements IOperationValidator {
	/**
	 * 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(Messages.ActivityConstraints_rootMessage, 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);
	}
	
	/*
	 * Called by the UI before doing a batched processing of several pending
	 * changes.
	 */
	public RequiredFeaturesResult getRequiredFeatures(IInstallFeatureOperation[] jobs) {
		
		RequiredFeaturesResult requiredFeaturesResult = new RequiredFeaturesResult();
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);
		checkPlatformWasModified(beforeStatus);

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

		// report status
		//return createCombinedReportStatus(beforeStatus, status);
		requiredFeaturesResult.setRequiredFeatures(requiredFeatures);
		requiredFeaturesResult.setStatus(createCombinedReportStatus(beforeStatus, status));
		return requiredFeaturesResult;
	}

	/*
	 * 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(Messages.ActivityConstraints_rootMessage, 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 Set 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,
							Messages.ActivityConstraints_exclusive));
					continue;
				}
				checkForCycles(newFeature, null, features);
				features =
					computeFeaturesAfterOperation(
						features,
						newFeature,
						oldFeature);
			}
			if (nexclusives > 0)
				return Collections.EMPTY_SET;
			checkConstraints(features, tmpStatus);
			if (tmpStatus.size() == 0) // the whole "batch" is OK
				return Collections.EMPTY_SET;

			// 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);

				Set result = checkConstraints(features, status);
				if (status.size() > 0
					&& !isBetterStatus(beforeStatus, status)) {
// bug 75613
//					IStatus conflict =
//						createStatus(
//							newFeature,
//							FeatureStatus.CODE_OTHER,
//							Policy.bind(KEY_CONFLICT));
//					status.add(0, conflict);
					return result;
				}
			}
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
		
		return Collections.EMPTY_SET;
	}
	
	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,
								Messages.ActivityConstraints_platformModified)); 
		} 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,
					NLS.bind(Messages.ActivityConstraints_readOnly, (new String[] { 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
	 */
	public 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, Messages.ActivityConstraints_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 = UpdateUtils.getIncludedFeature(feature, children[i]);
				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, Messages.ActivityConstraints_noLicense));
	}

	/*
	 * 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 = NLS.bind(Messages.ActivityConstraints_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 = UpdateUtils.getIncludedFeature(feature, children[i]);
				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 Set  checkConstraints(ArrayList features, ArrayList status)
		throws CoreException {
		if (features == null)
			return Collections.EMPTY_SET;

		ArrayList plugins = computePluginsForFeatures(features);

		checkEnvironment(features, status);
		checkPlatformFeature(features, plugins, status);
		checkPrimaryFeature(features, plugins, status);
		return 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, Messages.ActivityConstraints_os);
					if (!status.contains(s))
						status.add(s);
					continue;
				}
			}

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

			if (farch.size() > 0) {
				if (!farch.contains(arch)) {
					IStatus s =
						createStatus(feature, FeatureStatus.CODE_ENVIRONMENT, Messages.ActivityConstraints_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) {

		// find the plugin that defines the product
		IProduct product = Platform.getProduct();
		if (product == null)
			return; // normally this shouldn't happen
		Bundle primaryBundle = product.getDefiningBundle();
		// check if that plugin is among the resulting plugins
		boolean found = false;
		for (int j = 0; j < plugins.size(); j++) {
			IPluginEntry plugin = (IPluginEntry) plugins.get(j);
			if (primaryBundle.getSymbolicName().equals(plugin.getVersionedIdentifier().getIdentifier())) {
				found = true;
				break;
			}
		}
		
		if (!found) {
			IStatus s =
				createStatus(null, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_platform);
			if (!status.contains(s))
				status.add(s);
		}
	}

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

		String featureId =
			ConfiguratorUtils
				.getCurrentPlatformConfiguration()
				.getPrimaryFeatureIdentifier();
		
		if (featureId != null) {
			// primary feature is defined
			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, Messages.ActivityConstraints_primary);
			if (!status.contains(s))
				status.add(s);
		} else {
			// check if the product still ends up contributed
			// find the plugin that defines the product
			IProduct product = Platform.getProduct();
			if (product == null)
				return; // normally this shouldn't happen
			Bundle primaryBundle = product.getDefiningBundle();
			// check if that plugin is among the resulting plugins

			for (int j = 0; j < plugins.size(); j++) {
				IPluginEntry plugin = (IPluginEntry) plugins.get(j);
				if (primaryBundle.getSymbolicName().equals(plugin.getVersionedIdentifier().getIdentifier())) {
					return; // product found
				}
			}
			IStatus s =
				createStatus(null, FeatureStatus.CODE_OTHER, Messages.ActivityConstraints_primary);
			if (!status.contains(s))
				status.add(s);
		}
	}

	/*
	 * Verify we do not break prereqs
	 */
	private static Set checkPrereqs(
		ArrayList features,
		ArrayList plugins,
		ArrayList status) {
		
		HashSet result = new HashSet();

		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 == IUpdateConstants.RULE_NONE)
					rule = IUpdateConstants.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 == IUpdateConstants.RULE_PERFECT
								&& cversion.isPerfect(version))
							found = true;
						else if (
							rule == IUpdateConstants.RULE_EQUIVALENT
								&& cversion.isEquivalentTo(version))
							found = true;
						else if (
							rule == IUpdateConstants.RULE_COMPATIBLE
								&& cversion.isCompatibleWith(version))
							found = true;
						else if (
							rule == IUpdateConstants.RULE_GREATER_OR_EQUAL
								&& cversion.isGreaterOrEqualTo(version))
							found = true;
					}
					if (found)
						break;
				}
				
				// perhaps the bundle that we are looking for was installed
				// but isn't a part of a feature
				if (!found && !featurePrereq)
					found = isInstalled(iid, rule, ignoreVersion);

				if (!found) {
					// report status
					String target =
						featurePrereq
							? Messages.ActivityConstaints_prereq_feature
							: Messages.ActivityConstaints_prereq_plugin;
					int errorCode = featurePrereq
							? FeatureStatus.CODE_PREREQ_FEATURE
							: FeatureStatus.CODE_PREREQ_PLUGIN;
					String msg =
						NLS.bind(Messages.ActivityConstraints_prereq, (new String[] { target, id }));

					if (!ignoreVersion) {
						if (rule == IUpdateConstants.RULE_PERFECT)
							msg =
								NLS.bind(Messages.ActivityConstraints_prereqPerfect, (new String[] {
                                target,
                                id,
                                version.toString()}));
						else if (rule == IUpdateConstants.RULE_EQUIVALENT)
							msg =
								NLS.bind(Messages.ActivityConstraints_prereqEquivalent, (new String[] {
                                target,
                                id,
                                version.toString()}));
						else if (rule == IUpdateConstants.RULE_COMPATIBLE)
							msg =
								NLS.bind(Messages.ActivityConstraints_prereqCompatible, (new String[] {
                                target,
                                id,
                                version.toString()}));
						else if (rule == IUpdateConstants.RULE_GREATER_OR_EQUAL)
							msg =
								NLS.bind(Messages.ActivityConstraints_prereqGreaterOrEqual, (new String[] {
                                target,
                                id,
                                version.toString()}));
					}
					IStatus s = createStatus(feature, errorCode, msg);
					result.add(new InternalImport(iimport));
					if (!status.contains(s))
						status.add(s);
				}
			}
		}
		
		return result;
	}
	
	/*
	 * Return a boolean value indicating whether or not the bundle with the given id and version
	 * is installed in the system.
	 */
	private static boolean isInstalled(VersionedIdentifier vid, int rule, boolean ignoreVersion) {
		BundleContext context = UpdateCore.getPlugin().getBundleContext();
		if (context == null)
			return false;
		ServiceReference reference = context.getServiceReference(PlatformAdmin.class.getName());
		if (reference == null)
			return false;
		PlatformAdmin admin = (PlatformAdmin) context.getService(reference);
		try {
			State state = admin.getState(false);
			String id = vid.getIdentifier();
			PluginVersionIdentifier version = vid.getVersion();
			BundleDescription[] bundles = state.getBundles(id);
			if (bundles == null || bundles.length == 0)
				return false;
			for (int i=0; i<bundles.length; i++) {
				BundleDescription bundle = bundles[i];
				PluginVersionIdentifier cversion = new PluginVersionIdentifier(bundle.getVersion().toString());
				// have a candidate
				if (ignoreVersion)
					return true;
				if (rule == IUpdateConstants.RULE_PERFECT && cversion.isPerfect(version))
					return true;
				else if (rule == IUpdateConstants.RULE_EQUIVALENT && cversion.isEquivalentTo(version))
					return true;
				else if (rule == IUpdateConstants.RULE_COMPATIBLE && cversion.isCompatibleWith(version))
					return true;
				else if (rule == IUpdateConstants.RULE_GREATER_OR_EQUAL && cversion.isGreaterOrEqualTo(version))
					return true;
			}
			return false;
		} finally {
			context.ungetService(reference);
		}
	}

	/*
	 * 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 = Messages.ActivityConstraints_optionalChild;
			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 message,
		ArrayList children,
		int code) {
		IStatus[] carray =
			(IStatus[]) children.toArray(new IStatus[children.size()]);
		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 =
				NLS.bind(Messages.ActivityConstraints_childMessage, (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(Messages.ActivityConstraints_rootMessage,
					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(
						Messages.ActivityConstraints_warning,
						beforeStatus,
						IStatus.WARNING);
					// errors may be fixed
				} else {
					ArrayList combined = new ArrayList();
					combined.add(
						createMultiStatus(
							Messages.ActivityConstraints_beforeMessage,
							beforeStatus,
							IStatus.ERROR));
					combined.add(
						createMultiStatus(
							Messages.ActivityConstraints_afterMessage,
							status,
							IStatus.ERROR));
					return createMultiStatus(
						Messages.ActivityConstraints_rootMessageInitial,
						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;
	}
	
	public class RequiredFeaturesResult {
		
		private IStatus status;
		private Set requiredFeatures;
		
		public Set getRequiredFeatures() {
			return requiredFeatures;
		}
		public void setRequiredFeatures(Set requiredFeatures) {
			this.requiredFeatures = requiredFeatures;
		}
		public void addRequiredFeatures(Set requiredFeatures) {
			if (requiredFeatures == null) {
				requiredFeatures = new HashSet();
			}
			this.requiredFeatures.addAll(requiredFeatures);
		}
		public IStatus getStatus() {
			return status;
		}
		public void setStatus(IStatus status) {
			this.status = status;
		}
		
		
	}
	
	public static class InternalImport {
		
		private IImport iimport;

		public InternalImport(IImport iimport) {
			this.iimport = iimport;
		}
		
		public IImport getImport() {
			return iimport;
		}

		public void setImport(IImport iimport) {
			this.iimport = iimport;
		}
		
		public boolean equals(Object object) {

			if ( ( object == null) || !(object instanceof InternalImport))
				return false;
			
			if ( object == this)
				return true;
			
			return iimport.getVersionedIdentifier().equals( ((InternalImport)object).getImport().getVersionedIdentifier()) && (getImport().getRule() == ((InternalImport)object).getImport().getRule());

		}

		public int hashCode() {
			return iimport.getVersionedIdentifier().hashCode() * iimport.getRule();
		}
		
	}

}
