/*******************************************************************************
 * Copyright (c) 2000, 2009 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.core;


import org.eclipse.core.runtime.ListenerList;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.configuration.IActivity;
import org.eclipse.update.configuration.IConfiguredSite;
import org.eclipse.update.configuration.IConfiguredSiteChangedListener;
import org.eclipse.update.configuration.IInstallConfiguration;
import org.eclipse.update.configuration.IProblemHandler;
import org.eclipse.update.configurator.ConfiguratorUtils;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureReference;
import org.eclipse.update.core.IIncludedFeatureReference;
import org.eclipse.update.core.IPluginEntry;
import org.eclipse.update.core.ISite;
import org.eclipse.update.core.ISiteFeatureReference;
import org.eclipse.update.core.IVerificationListener;
import org.eclipse.update.core.SiteManager;
import org.eclipse.update.core.Utilities;
import org.eclipse.update.core.VersionedIdentifier;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.internal.model.ConfiguredSiteModel;
import org.eclipse.update.internal.operations.UpdateUtils;

/**
 * A Configured site manages the Configured and unconfigured features of a Site
 */
public class ConfiguredSite extends ConfiguredSiteModel implements IConfiguredSite {

	private static final String PRODUCT_SITE_MARKER = ".eclipseproduct"; //$NON-NLS-1$
	private static final String EXTENSION_SITE_MARKER = ".eclipseextension"; //$NON-NLS-1$

	// listeners	
	private ListenerList listeners = new ListenerList(ListenerList.IDENTITY);

	// verification status
	private IStatus verifyStatus;

	// transient: true if the site was just created so we can remove it
	private transient boolean justCreated = false;

	/*
	 * Default Constructor
	 */
	public ConfiguredSite() {
	}

	/*
	 * Copy Constructor
	 * As of now, configSite can only be of type ConfiguredSite
	 */
	public ConfiguredSite(IConfiguredSite configSite) {
		ConfiguredSite cSite = (ConfiguredSite) configSite;
		setSiteModel(cSite.getSiteModel());
		setConfigurationPolicyModel(new ConfigurationPolicy(cSite.getConfigurationPolicy()));
		setUpdatable(cSite.isUpdatable());
		setEnabled(cSite.isEnabled());
		setPreviousPluginPath(cSite.getPreviousPluginPath());
		setPlatformURLString(cSite.getPlatformURLString());
	}

	/*
	 *  Adds a listener
	 */
	public void addConfiguredSiteChangedListener(IConfiguredSiteChangedListener listener) {
		listeners.add(listener);
	}

	/*
	 * Removes a listener
	 */
	public void removeConfiguredSiteChangedListener(IConfiguredSiteChangedListener listener) {
		listeners.remove(listener);
	}

	/*
	 * @see IConfiguredSite#install(IFeature,IVerificationListener, IProgressMonitor)
	 */
	public IFeatureReference install(IFeature feature, IVerificationListener verificationListener, IProgressMonitor monitor) throws InstallAbortedException, CoreException {
		return install(feature, null, verificationListener, monitor);
	}

	/*
	 * @see IConfiguredSite#install(IFeature, IFeatureReference, IVerificationListener, IProgressMonitor)
	 */
	public IFeatureReference install(IFeature feature, IFeatureReference[] optionalFeatures, IVerificationListener verificationListener, IProgressMonitor monitor) throws InstallAbortedException, CoreException {

		// change the status if justCreated
		if (justCreated) justCreated=false;

		// ConfigSite is read only 
		if (!isUpdatable()) {
			String errorMessage = NLS.bind(Messages.ConfiguredSite_NonInstallableSite, (new String[] { getSite().getURL().toExternalForm() }));
			IStatus status = verifyUpdatableStatus();
			if (status != null)
				errorMessage += " " + status.getMessage(); //$NON-NLS-1$
			throw Utilities.newCoreException(errorMessage, null);
		}

		// feature is null
		if (feature == null) {
			String errorMessage = Messages.ConfiguredSite_NullFeatureToInstall; 
			throw Utilities.newCoreException(errorMessage, null);
		}

		// feature reference to return
		IFeatureReference installedFeatureRef;
		IFeature installedFeature = null;

		// create the Activity (INSTALL)
		ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_FEATURE_INSTALL);
		activity.setLabel(feature.getVersionedIdentifier().toString());
		activity.setDate(new Date());

		try {
			installedFeatureRef = getSite().install(feature, optionalFeatures, verificationListener, monitor);

			if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) {
				UpdateCore.debug("Sucessfully installed: " + installedFeatureRef.getURL().toExternalForm()); //$NON-NLS-1$
			}

			if (installedFeatureRef != null) {
				try {
					installedFeature = installedFeatureRef.getFeature(null);
				} catch (CoreException e) {
					UpdateCore.warn(null, e);
				}
			}

			// everything done ok
			activity.setStatus(IActivity.STATUS_OK);

			// notify listeners
			Object[] siteListeners = listeners.getListeners();
			for (int i = 0; i < siteListeners.length; i++) {
				if (installedFeature != null) {
					IConfiguredSiteChangedListener listener = ((IConfiguredSiteChangedListener) siteListeners[i]);
					listener.featureInstalled(installedFeature);
				}
			}
		} catch (CoreException e) {
			// not ok, set Activity status
			activity.setStatus(IActivity.STATUS_NOK);
			throw e;
		} finally {
			IInstallConfiguration current = SiteManager.getLocalSite().getCurrentConfiguration();
			((InstallConfiguration) current).addActivity(activity);
		}
		// call the configure task	
		if (installedFeature != null)
			configure(installedFeature, optionalFeatures, true);
		/*callInstallHandler*/

		return installedFeatureRef;
	}

	/*
	 * @see IConfiguredSite#remove(IFeature, IProgressMonitor)
	 */
	public void remove(IFeature feature, IProgressMonitor monitor) throws CoreException {

		// ConfigSite is read only
		if (!isUpdatable()) {
			String errorMessage = NLS.bind(Messages.ConfiguredSite_NonUninstallableSite, (new String[] { getSite().getURL().toExternalForm() }));
			throw Utilities.newCoreException(errorMessage, null);
		}

		// create the Activity
		ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_FEATURE_REMOVE);
		activity.setLabel(feature.getVersionedIdentifier().toString());
		activity.setDate(new Date());

		try {
			IFeatureReference referenceToRemove = null;
			ISiteFeatureReference[] featureRef = getSite().getFeatureReferences();
			ISiteFeatureReference ref = getSite().getFeatureReference(feature);
			for (int i = 0; i < featureRef.length; i++) {
				if (featureRef[i].equals(ref)) {
					referenceToRemove = featureRef[i];
					break;
				}
			}

			// we found a feature reference on the site matching the feature			
			if (referenceToRemove != null) {
				// Check if feature is unconfigured before we remove it
				// our UI will check.
				// For non-UI application, throw error is feature is configured
				if (getConfigurationPolicy().isConfigured(referenceToRemove)) {
					IFeature featureToRemove = referenceToRemove.getFeature(null);
					String featureLabel = (featureToRemove == null) ? null : featureToRemove.getLabel();
					throw Utilities.newCoreException(NLS.bind(Messages.ConfiguredSite_UnableToRemoveConfiguredFeature, (new String[] { featureLabel })), null);
				}
			} else {
				throw Utilities.newCoreException(NLS.bind(Messages.ConfiguredSite_UnableToFindFeature, (new String[] { feature.getURL().toString() })),
				null);
			}

			// remove the feature
			getSite().remove(feature, monitor);
			getConfigurationPolicy().removeFeatureReference(referenceToRemove);
			// everything done ok
			activity.setStatus(IActivity.STATUS_OK);
			// notify listeners
			Object[] siteListeners = listeners.getListeners();
			for (int i = 0; i < siteListeners.length; i++) {
				((IConfiguredSiteChangedListener) siteListeners[i]).featureRemoved(feature);
			}
		} catch (CoreException e) {
			activity.setStatus(IActivity.STATUS_NOK);
			throw e;
		} finally {
			IInstallConfiguration current = SiteManager.getLocalSite().getCurrentConfiguration();
			((InstallConfiguration) current).addActivity(activity);
		}
	}

	/*
	 * @see IConfiguredSite#configure(IFeature) 
	 */
	public void configure(IFeature feature) throws CoreException {
		configure(feature, null, true /*callInstallHandler*/
		);
	}

	/*
	 * 
	 */
	private void configure(IFeature feature, IFeatureReference[] optionalFeatures, boolean callInstallHandler) throws CoreException {

		if (feature == null) {
			UpdateCore.warn("Attempting to configure a null feature in site:" + getSite().getURL().toExternalForm()); //$NON-NLS-1$
			return;
		}

		ConfigurationPolicy configPolicy = getConfigurationPolicy();
		if (configPolicy == null)
			return;

		// bottom up approach, same configuredSite
		IIncludedFeatureReference[] childrenRef = feature.getIncludedFeatureReferences();
		if (optionalFeatures != null) {
			childrenRef = childrenToConfigure(childrenRef, optionalFeatures);
		}

		for (int i = 0; i < childrenRef.length; i++) {
			try {
				IFeature child = childrenRef[i].getFeature(null);
				configure(child, optionalFeatures, callInstallHandler);
			} catch (CoreException e) {
				// if not an optional feature, throw exception
				if (!childrenRef[i].isOptional()) {
					UpdateCore.warn("Unable to configure child feature: " + childrenRef[i] + " " + e); //$NON-NLS-1$ //$NON-NLS-2$
					throw e;
				}
			}
		}

		// configure root feature 	
		IFeatureReference featureReference = getSite().getFeatureReference(feature);
		configPolicy.configure(featureReference, callInstallHandler, true);

		// notify listeners
		Object[] siteListeners = listeners.getListeners();
		for (int i = 0; i < siteListeners.length; i++) {
			((IConfiguredSiteChangedListener) siteListeners[i]).featureConfigured(feature);
		}
	}

	/*
	 * Return the optional children to configure
	 * 
	 * @param children all the nested features
	 * @param optionalfeatures optional features to install
	 * @return IFeatureReference[]
	 */
	private IIncludedFeatureReference[] childrenToConfigure(IIncludedFeatureReference[] children, IFeatureReference[] optionalfeatures) {

		List childrenToInstall = new ArrayList();
		for (int i = 0; i < children.length; i++) {
			IIncludedFeatureReference optionalFeatureToConfigure = children[i];
			if (!optionalFeatureToConfigure.isOptional()) {
				childrenToInstall.add(optionalFeatureToConfigure);
			} else {
				for (int j = 0; j < optionalfeatures.length; j++) {
					// must compare feature as optionalFeatures are from the install site
					// where children are on the local site
					try {
						IFeature installedChildren = optionalfeatures[j].getFeature(null);
						if (installedChildren.equals(optionalFeatureToConfigure.getFeature(null))) {
							childrenToInstall.add(optionalFeatureToConfigure);
							break;
						}
					} catch (CoreException e) {
						UpdateCore.warn("", e); //$NON-NLS-1$
					}
				}
			}
		}

		IIncludedFeatureReference[] result = new IIncludedFeatureReference[childrenToInstall.size()];
		if (childrenToInstall.size() > 0) {
			childrenToInstall.toArray(result);
		}

		return result;
	}

	/*
	 * @see IConfiguredSite#unconfigure(IFeature)
	 */
	public boolean unconfigure(IFeature feature) throws CoreException {
		// the first call sould disable without checking for enable parent
		return unconfigure(feature, true, false);
	}

	private boolean unconfigure(IFeature feature, boolean includePatches, boolean verifyEnableParent) throws CoreException {
		IFeatureReference featureReference = getSite().getFeatureReference(feature);

		if (featureReference == null) {
			UpdateCore.warn("Unable to retrieve Feature Reference for feature" + feature); //$NON-NLS-1$
			return false;
		}

		ConfigurationPolicy configPolicy = getConfigurationPolicy();
		if (configPolicy == null)
			return false;

		// verify no enable parent
		if (verifyEnableParent && !validateNoConfiguredParents(feature)) {
			UpdateCore.warn("The feature " + feature.getVersionedIdentifier() + " to disable is needed by another enable feature"); //$NON-NLS-1$ //$NON-NLS-2$
			return false;
		}

		boolean sucessfullyUnconfigured = false;
		try {
			sucessfullyUnconfigured = configPolicy.unconfigure(featureReference, true, true);
		} catch (CoreException e) {
			URL url = featureReference.getURL();
			String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$
			UpdateCore.warn("Unable to unconfigure" + urlString, e); //$NON-NLS-1$
			throw e;
		}
		if (sucessfullyUnconfigured) {
			// 2.0.2: unconfigure patches that reference this feature.
			// A patch is a feature that contains an import
			// statement with patch="true" and an id/version
			// that matches an already installed and configured
			// feature. When patched feature is unconfigured,
			// all the patches that reference it must be 
			// unconfigured as well
			// (in contrast, patched features can be
			// configured without the patches).
			if (includePatches)
				unconfigurePatches(feature);

			// top down approach, same configuredSite
			IIncludedFeatureReference[] childrenRef = feature.getIncludedFeatureReferences();
			for (int i = 0; i < childrenRef.length; i++) {
				try {
					IFeature child = childrenRef[i].getFeature(null); // disable the exact feature
					unconfigure(child, includePatches, true); // check for parent as we should be the only parent.
				} catch (CoreException e) {
					// skip any bad children
					UpdateCore.warn("Unable to unconfigure child feature: " + childrenRef[i] + " " + e); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}

			// notify listeners
			Object[] siteListeners = listeners.getListeners();
			for (int i = 0; i < siteListeners.length; i++) {
				IConfiguredSiteChangedListener listener = ((IConfiguredSiteChangedListener) siteListeners[i]);
				listener.featureUnconfigured(feature);
			}

			return true;
		} else {
			URL url = featureReference.getURL();
			String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$
			UpdateCore.warn("Unable to unconfigure:" + urlString); //$NON-NLS-1$
			return false;
		}
	}

	/*
	 * Look for features that have an import reference
	 * that points to this feature and where patch=true.
	 * Unconfigure all the matching patches, but
	 * do not do the same lookup for them
	 * because patches cannot have patches themselves.
	 */

	private void unconfigurePatches(IFeature feature) {
		IFeatureReference[] frefs = getConfiguredFeatures();
		for (int i = 0; i < frefs.length; i++) {
			IFeatureReference fref = frefs[i];
			try {
				IFeature candidate = fref.getFeature(null);
				if (candidate.equals(feature))
					continue;

				if (UpdateUtils.isPatch(feature, candidate))
					unconfigure(candidate, false, false);
			} catch (CoreException e) {
				UpdateCore.warn("", e); //$NON-NLS-1$
			}
		}
	}

	/*
	 * @see IConfiguredSite#getConfiguredFeatures()
	 */
	public IFeatureReference[] getConfiguredFeatures() {
		if (isEnabled())
			return getRawConfiguredFeatures();
		else
			return new ISiteFeatureReference[0];
	}

	/*
	 * @see IConfiguredSite#getConfiguredFeatures()
	 */
	private IFeatureReference[] getRawConfiguredFeatures() {
		ConfigurationPolicy configPolicy = getConfigurationPolicy();
		if (configPolicy == null)
			return new ISiteFeatureReference[0];

		return configPolicy.getConfiguredFeatures();
	}

	/*
	 * adds configured and unconfigured feature references
	 */
	public IFeatureReference[] getFeatureReferences() {

		ConfigurationPolicy configPolicy = getConfigurationPolicy();
		if (configPolicy == null)
			return new ISiteFeatureReference[0];

		IFeatureReference[] configuredFeatures = getConfiguredFeatures();
		int confLen = configuredFeatures.length;
		IFeatureReference[] unconfiguredFeatures = configPolicy.getUnconfiguredFeatures();
		int unconfLen = unconfiguredFeatures.length;

		IFeatureReference[] result = new IFeatureReference[confLen + unconfLen];
		if (confLen > 0) {
			System.arraycopy(configuredFeatures, 0, result, 0, confLen);
		}
		if (unconfLen > 0) {
			System.arraycopy(unconfiguredFeatures, 0, result, confLen, unconfLen);
		}

		return result;
	}

	/*
	 * Configure and unconfigure appropriate feature to
	 * become 'like' currentConfiguration which is the configuration
	 * the user wants to revert to.
	 * 
	 * All features from currentConfiguration should be configured
	 */
	public void revertTo(IConfiguredSite oldConfiguration, IProgressMonitor monitor, IProblemHandler handler) throws CoreException, InterruptedException {

		ConfiguredSite oldConfiguredSite = (ConfiguredSite) oldConfiguration;

		// retrieve the feature that were configured
		IFeatureReference[] configuredFeatures = oldConfiguredSite.validConfiguredFeatures(handler);

		for (int i = 0; i < configuredFeatures.length; i++) {
			getConfigurationPolicy().configure(configuredFeatures[i], true, true);
		}

		// calculate all the features we have to unconfigure from the current state to this state
		// in the history. 				
		List featureToUnconfigure = oldConfiguredSite.calculateUnconfiguredFeatures(configuredFeatures);

		// for each unconfigured feature check if it still exists
		// if so add as unconfigured
		Iterator iter = featureToUnconfigure.iterator();
		while (iter.hasNext()) {
			IFeatureReference element = (IFeatureReference) iter.next();
			try {
				// do not log activity
				getConfigurationPolicy().unconfigure(element, true, true);
			} catch (CoreException e) {
				// log no feature to unconfigure
				String url = element.getURL().toString();
				ISite site = element.getSite();
				String siteString = (site != null) ? site.getURL().toExternalForm() : Messages.ConfiguredSite_NoSite; 
				UpdateCore.warn(NLS.bind(Messages.ConfiguredSite_CannotFindFeatureToUnconfigure, (new String[] { url, siteString })), e); 
			}
		}
		//} // end USER_EXCLUDE
	}

	/*
	 * We have to keep our configured feature
	 * check if they are all valid
	 * Return the valid configured features
	 */
	private IFeatureReference[] validConfiguredFeatures(IProblemHandler handler) throws InterruptedException {

		IFeatureReference[] configuredFeatures = getConfiguredFeatures();
		if (configuredFeatures != null) {
			for (int i = 0; i < configuredFeatures.length; i++) {
				IFeature feature = null;

				// attempt to access the feature
				try {
					feature = configuredFeatures[i].getFeature(null);
				} catch (CoreException e) {
					// notify we cannot find the feature
					UpdateCore.warn(null, e);
					String featureString = configuredFeatures[i].getURL().toExternalForm();
					if (!handler.reportProblem(NLS.bind(Messages.ConfiguredSite_CannotFindFeatureToConfigure, (new String[] { featureString })))) {
						throw new InterruptedException();
					}
				}

				// verify all the plugins still exist
				if (feature != null) {
					// get plugin identifier
					List sitePluginIdentifiers = new ArrayList();
					ISite site = feature.getSite();
					IPluginEntry[] sitePluginEntries = null;

					if (site != null) {
						sitePluginEntries = site.getPluginEntries();
						for (int index = 0; index < sitePluginEntries.length; index++) {
							IPluginEntry entry = sitePluginEntries[index];
							sitePluginIdentifiers.add(entry.getVersionedIdentifier());
						}
					}

					if (sitePluginEntries.length > 0) {
						IPluginEntry[] featurePluginEntries = feature.getPluginEntries();
						for (int index = 0; index < featurePluginEntries.length; index++) {
							IPluginEntry currentFeaturePluginEntry = featurePluginEntries[index];
							if (!contains(currentFeaturePluginEntry.getVersionedIdentifier(), sitePluginIdentifiers)) {
								// the plugin defined by the feature
								// doesn't seem to exist on the site
								String msg = "Error verifying existence of plugin:" + currentFeaturePluginEntry.getVersionedIdentifier().toString(); //$NON-NLS-1$
								UpdateCore.log(msg, new Exception());

								String siteString = (site != null) ? site.getURL().toExternalForm() : Messages.ConfiguredSite_NoSite;	
								String errorLabel = NLS.bind(Messages.ConfiguredSite_CannotFindPluginEntry, (new String[] { currentFeaturePluginEntry.getVersionedIdentifier().toString(), siteString }));
								if (handler == null) {
									throw new InterruptedException(errorLabel);
								}
								if (!handler.reportProblem(errorLabel)) {
									throw new InterruptedException();
								}
							} // end if not found in site
						} // end for
					}
				}
			} // end for configured feature
		}
		return configuredFeatures;
	}

	/*
	 * We are in the process of calculating the delta between what was configured in the current
	 * configuration that is not configured now
	 * 
	 * we have to figure out what feature have been unconfigured for the whole
	 * history between current and us... 
	 * 
	 * is it as simple as  get all configured, and unconfigured,
	 * the do the delta with what should be configured
	 * 
	 */
	private List calculateUnconfiguredFeatures(IFeatureReference[] configuredFeatures) throws CoreException {

		Set featureToUnconfigureSet = new HashSet();

		// loop for all history
		// try to see if the configured site existed
		// if it does, get the unconfigured features 
		// and the configured one
		IInstallConfiguration[] history = SiteManager.getLocalSite().getConfigurationHistory();

		for (int i = 0; i < history.length; i++) {
			IInstallConfiguration element = history[i];
			IConfiguredSite[] configSites = element.getConfiguredSites();
			for (int j = 0; j < configSites.length; j++) {
				ConfiguredSite configSite = (ConfiguredSite) configSites[j];
				if (configSite.getSite().equals(getSite())) {
					featureToUnconfigureSet.addAll(Arrays.asList(configSite.getConfigurationPolicy().getUnconfiguredFeatures()));
					featureToUnconfigureSet.addAll(Arrays.asList(configSite.getConfigurationPolicy().getConfiguredFeatures()));
				}
			}
		}

		// remove the unconfigured feature we found that are now to be configured 
		// (they may have been unconfigured in the past, but the revert makes them configured)
		List featureToUnconfigureList = remove(configuredFeatures, featureToUnconfigureSet);

		return featureToUnconfigureList;
	}

	/*
	 * Utilities: Remove an array of feature references
	 * from a list
	 */
	private List remove(IFeatureReference[] featureRefs, Set set) {
		List result = new ArrayList();

		if (set == null)
			return result;

		// if an element of the list is NOT found in the array,
		// add it to the result list			
		Iterator iter = set.iterator();
		while (iter.hasNext()) {
			IFeatureReference element = (IFeatureReference) iter.next();
			boolean found = false;
			for (int i = 0; i < featureRefs.length; i++) {
				if (element.equals(featureRefs[i])) {
					found = true;
				}
			}

			if (!found)
				result.add(element);
		}
		return result;
	}

	/*
	 * I have issues when running list.contain(versionedIdentifier)
	 * The code runs the Object.equals instead of the VersionedIdentifier.equals
	 */
	private boolean contains(VersionedIdentifier id, List list) {
		boolean found = false;
		if (list != null && !list.isEmpty()) {
			Iterator iter = list.iterator();
			while (iter.hasNext() && !found) {
				VersionedIdentifier element = (VersionedIdentifier) iter.next();
				if (element.equals(id)) {
					found = true;
				}
			}
		}
		return found;
	}

	/*
	 * 
	 */
	public ConfigurationPolicy getConfigurationPolicy() {
		return (ConfigurationPolicy) getConfigurationPolicyModel();
	}

	/*
	 * 
	 */
	public ISite getSite() {
		return (ISite) getSiteModel();
	}

	/*
	 * 
	 */
	public IInstallConfiguration getInstallConfiguration() {
		return (IInstallConfiguration) getInstallConfigurationModel();
	}

	/*
	 * 
	 */
	public IStatus getBrokenStatus(IFeature feature) {

		IStatus featureStatus = createStatus(IStatus.OK, IFeature.STATUS_HAPPY, "", null); //$NON-NLS-1$

		// check the Plugins of all the features
		// every plugin of the feature must be on the site
		IPluginEntry[] siteEntries = getSite().getPluginEntries();
		IPluginEntry[] featuresEntries = feature.getPluginEntries();
		IPluginEntry[] result = UpdateManagerUtils.diff(featuresEntries, siteEntries);
		if (result != null && (result.length != 0)) {
			String msg = Messages.SiteLocal_FeatureUnHappy; 
			MultiStatus multi = new MultiStatus(featureStatus.getPlugin(), IFeature.STATUS_UNHAPPY, msg, null);

			for (int k = 0; k < result.length; k++) {
				VersionedIdentifier id = result[k].getVersionedIdentifier();
				Object[] values = new String[] { "", "" }; //$NON-NLS-1$ //$NON-NLS-2$
				if (id != null) {
					values = new Object[] { id.getIdentifier(), id.getVersion()};
				}
				String msg1 = NLS.bind(Messages.ConfiguredSite_MissingPluginsBrokenFeature, values);
				UpdateCore.warn(msg1);
				IStatus status = createStatus(IStatus.ERROR, IFeature.STATUS_UNHAPPY, msg1, null);
				multi.add(status);
			}
			return multi;
		}

		// check os, arch, and ws

		String msg = Messages.SiteLocal_FeatureHappy; 
		return createStatus(IStatus.OK, IFeature.STATUS_HAPPY, msg, null);
	}

	/*
	 * 
	 */
	public boolean isConfigured(IFeature feature) {
		if (!isEnabled())
			return false;

		if (getConfigurationPolicy() == null)
			return false;
		IFeatureReference featureReference = getSite().getFeatureReference(feature);
		if (featureReference == null) {
			if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_WARNINGS)
				UpdateCore.warn("Unable to retrieve featureReference for feature:" + feature); //$NON-NLS-1$
			return false;
		}
		return getConfigurationPolicy().isConfigured(featureReference);
	}

	/**
	 * @see Object#toString()
	 */
	public String toString() {
		if (getSite() == null)
			return "No Site"; //$NON-NLS-1$
		if (getSite().getURL() == null)
			return "No URL"; //$NON-NLS-1$
		return getSite().getURL().toExternalForm();
	}

	/**
	 * @see IConfiguredSite#verifyUpdatableStatus()
	 */
	public IStatus verifyUpdatableStatus() {

		if (verifyStatus != null)
			return verifyStatus;

		URL siteURL = getSite().getURL();
		if (siteURL == null) {
			verifyStatus = createStatus(IStatus.ERROR, Messages.ConfiguredSite_SiteURLNull, null); 
			return verifyStatus;
		}

		if (!"file".equalsIgnoreCase(siteURL.getProtocol())) { //$NON-NLS-1$
			verifyStatus = createStatus(IStatus.ERROR, Messages.ConfiguredSite_NonLocalSite, null); 
			return verifyStatus;
		}

		String siteLocation = siteURL.getFile();
		File file = new File(siteLocation);

		// get the product name of the private marker
		// if there is no private marker, check if the site is contained in another site
		// if there is a marker and this is a different product, return false
		// otherwise don't check if we are contained in another site
		String productName = getProductName(file);
		if (productName != null) {
			if (!productName.equals(getProductIdentifier("id", getProductFile()))) { //$NON-NLS-1$
				verifyStatus = createStatus(IStatus.ERROR, NLS.bind(Messages.ConfiguredSite_NotSameProductId, (new String[] { productName })), null);
				return verifyStatus;
			}
		} else {
			File container = getSiteContaining(file);
			// allow the install location to pass even though it looks like this
			// site is contained in another site
			if (container != null && !siteLocation.equals(Platform.getInstallLocation().getURL().getFile())) {
				verifyStatus = createStatus(IStatus.ERROR, NLS.bind(Messages.ConfiguredSite_ContainedInAnotherSite, (new String[] { container.getAbsolutePath() })), null);
				return verifyStatus;
			}
		}

		if (!canWrite(file)) {
			verifyStatus = createStatus(IStatus.ERROR, Messages.ConfiguredSite_ReadOnlySite, null); 
			return verifyStatus;
		}

		verifyStatus = createStatus(IStatus.OK, "", null); //$NON-NLS-1$
		setUpdatable(true);
		return verifyStatus;
	}

	/*
	 * Verify we can write on the file system
	 */
    public static boolean canWrite(File file) {
        if (file.canWrite() == false)
            return false;

        if (!file.isDirectory())
            return false;

        File fileTest = null;
        try {
        	// we use the .dll suffix to properly test on Vista virtual directories
        	// on Vista you are not allowed to write executable files on virtual directories like "Program Files"
            fileTest = File.createTempFile("writtableArea", ".dll", file); //$NON-NLS-1$ //$NON-NLS-2$
        } catch (IOException e) {
            //If an exception occurred while trying to create the file, it means that it is not writable
            return false;
        } finally {
            if (fileTest != null)
                fileTest.delete();
        }
        return true;
    }

	/*
	 * Check if the directory contains a marker
	 * if not ask all directory children to check
	 * if one validates the condition, returns the marker
	 */
	private static File getSiteContaining(File file) {

		if (file == null)
			return null;

		UpdateCore.warn("IsContained: Checking for markers at:" + file); //$NON-NLS-1$
		if (file.exists() && file.isDirectory()) {
			File productFile = new File(file, PRODUCT_SITE_MARKER);
			File extensionFile = new File(file, EXTENSION_SITE_MARKER);
			if (productFile.exists() || extensionFile.exists())
				return file;
//			// do not check if a marker exists in the current but start from the parent
//			// the current is analyze by getProductname()
//			if (file.getParentFile() != null) {
//				File privateFile = new File(file.getParentFile(), PRIVATE_SITE_MARKER);
//				if (privateFile.exists())
//					return file.getParentFile();
//			}
		}
		return getSiteContaining(file.getParentFile());
	}

	/*
	 * Returns the name of the product if the identifier of the private Site markup is not
	 * the same as the identifier of the product the workbench was started with.
	 * If the product is the same, return null.
	 */
	private static String getProductName(File file) {

		if (file == null)
			return null;

		File markerFile = new File(file, EXTENSION_SITE_MARKER );
		if (!markerFile.exists()) {
			return null;
		}

		File productFile = getProductFile();
		String productId = null;
		String privateId = null;
		if (productFile != null) {
			productId = getProductIdentifier("id", productFile); //$NON-NLS-1$
			privateId = getProductIdentifier("id", markerFile); //$NON-NLS-1$
			if (productId == null) {
				UpdateCore.warn("Product ID is null at:" + productFile); //$NON-NLS-1$
				return null;
			}
			if (!productId.equalsIgnoreCase(privateId)) {
				UpdateCore.warn("Product id at" + productFile + " Different than:" + markerFile); //$NON-NLS-1$ //$NON-NLS-2$
				String name = getProductIdentifier("name", markerFile); //$NON-NLS-1$
				String version = getProductIdentifier("version", markerFile); //$NON-NLS-1$
				String markerID = (name == null) ? version : name + ":" + version; //$NON-NLS-1$
				if (markerID == null)
					markerID = ""; //$NON-NLS-1$
				return markerID;
			} else {
				return privateId;
			}
		} else {
			UpdateCore.warn("Product Marker doesn't exist:" + productFile); //$NON-NLS-1$
		}

		return null;
	}

	/*
	 * Returns the identifier of the product from the property file
	 */
	private static String getProductIdentifier(String identifier, File propertyFile) {
		String result = null;
		if (identifier == null)
			return result;
		InputStream in = null;
		try {
			in = new FileInputStream(propertyFile);
			PropertyResourceBundle bundle = new PropertyResourceBundle(in);
			result = bundle.getString(identifier);
		} catch (IOException e) {
			if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL)
				UpdateCore.debug("Exception reading property file:" + propertyFile); //$NON-NLS-1$
		} catch (MissingResourceException e) {
			if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL)
				UpdateCore.debug("Exception reading '" + identifier + "' from property file:" + propertyFile); //$NON-NLS-1$ //$NON-NLS-2$
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e1) {
				}
		}
		return result;
	}

	/*
	 * Returns the identifier of the product from the property file
	 */
	private static File getProductFile() {

		String productInstallDirectory = ConfiguratorUtils.getInstallURL().getFile();
		if (productInstallDirectory != null) {
			File productFile = new File(productInstallDirectory, PRODUCT_SITE_MARKER);
			if (productFile.exists()) {
				return productFile;
			} else {
				UpdateCore.warn("Product marker doesn't exist:" + productFile); //$NON-NLS-1$
			}
		} else {
			UpdateCore.warn("Cannot retrieve install URL from BootLoader"); //$NON-NLS-1$
		}
		return null;
	}

	/*
	 * 
	 */
	/*package*/
	boolean createPrivateSiteMarker() {
		URL siteURL = getSite().getURL();
		if (siteURL == null) {
			UpdateCore.warn("Unable to create marker. The Site url is null."); //$NON-NLS-1$
			return false;
		}

		if (!"file".equalsIgnoreCase(siteURL.getProtocol())) { //$NON-NLS-1$
			UpdateCore.warn("Unable to create private marker. The Site is not on the local file system."); //$NON-NLS-1$
			return false;
		}

		String siteLocation = siteURL.getFile();
		File productFile = getProductFile();
		boolean success = false;
		if (productFile != null) {
			String productId = getProductIdentifier("id", productFile); //$NON-NLS-1$
			String productName = getProductIdentifier("name", productFile); //$NON-NLS-1$
			String productVer = getProductIdentifier("version", productFile); //$NON-NLS-1$
			if (productId != null) {
				File file = new File(siteLocation, EXTENSION_SITE_MARKER);
				if (!file.exists()) {
					OutputStream out = null;
					OutputStreamWriter outWriter = null;
					try {
						out = new FileOutputStream(file);
						outWriter = new OutputStreamWriter(out, "UTF8"); //$NON-NLS-1$
						outWriter.write("id=" + productId+"\n"); //$NON-NLS-1$ //$NON-NLS-2$
						if (productName != null)
							outWriter.write("name=" + productName+"\n"); //$NON-NLS-1$ //$NON-NLS-2$
						if (productVer != null)
							outWriter.write("version=" + productVer+"\n"); //$NON-NLS-1$ //$NON-NLS-2$
						success = true;
						justCreated = true;
					} catch (Exception e) {
						UpdateCore.warn("Unable to create private Marker at:" + file, e); //$NON-NLS-1$
					} finally {
						try {
							if (outWriter != null)
								outWriter.close();
						} catch (IOException e1) {
						}
						try {
							if (out != null)
								out.close();
						} catch (IOException e2) {
						}
					}
				}
			}
		}
		return success;
	}


	/*
	 * Returns true if the directory of the Site contains
	 * .eclipseextension
	 */
	public boolean isExtensionSite() {
		return containsMarker(EXTENSION_SITE_MARKER);
	}

	/*
	 * Returns true if the directory of the Site contains
	 * .eclipseextension
	 */
	public boolean isProductSite() {
		return containsMarker(PRODUCT_SITE_MARKER);
	}

	/*
	 * Returns true if the directory of the Site contains
	 * .eclipseextension
	 */
	public boolean isPrivateSite() {
		return isExtensionSite();
	}

	/*
	 * 
	 */
	private boolean containsMarker(String marker) {
		ISite site = getSite();
		if (site == null) {
			UpdateCore.warn("Contains Markers:The site is null"); //$NON-NLS-1$
			return false;
		}

		URL url = site.getURL();
		if (url == null) {
			UpdateCore.warn("Contains Markers:Site URL is null"); //$NON-NLS-1$
			return false;
		}
		if (!"file".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
			UpdateCore.warn("Contains Markers:Non file protocol"); //$NON-NLS-1$
			return false;
		}
		File file = new File(url.getFile());
		if (!file.exists()) {
			UpdateCore.warn("Contains Markers:The site doesn't exist:" + file); //$NON-NLS-1$
			return false;
		}
		File extension = new File(file, marker);
		if (!extension.exists()) {
			UpdateCore.warn("Contains Markers:The extensionfile does not exist:" + extension); //$NON-NLS-1$
			return false;
		}
		return true;
	}

	/*
	 * Returns true if the Site is already natively linked
	 */
	public boolean isNativelyLinked() throws CoreException {
		String platformString = getPlatformURLString();
		if (platformString == null) {
			UpdateCore.warn("Unable to retrieve platformString"); //$NON-NLS-1$
			return false;
		}

		URL siteURL = null;
		try {
			// check if the site exists and is updateable
			// update configSite
			URL urlToCheck = new URL(platformString);
			IPlatformConfiguration runtimeConfig = ConfiguratorUtils.getCurrentPlatformConfiguration();
			IPlatformConfiguration.ISiteEntry entry = runtimeConfig.findConfiguredSite(urlToCheck);
			if (entry != null) {
				return entry.isNativelyLinked();
			} else {
				UpdateCore.warn("Unable to retrieve site:" + platformString + " from platform."); //$NON-NLS-1$ //$NON-NLS-2$
			}

			// check by comparing URLs
			IPlatformConfiguration.ISiteEntry[] sites = runtimeConfig.getConfiguredSites();
			for (int i = 0; i < sites.length; i++) {
				siteURL = sites[i].getURL();
				URL resolvedURL = FileLocator.resolve(siteURL);
				if (UpdateManagerUtils.sameURL(resolvedURL, urlToCheck))
					return true;
			}
		} catch (MalformedURLException e) {
			String msg = NLS.bind(Messages.ConfiguredSite_UnableResolveURL, (new String[] { platformString }));
			throw Utilities.newCoreException(msg, e);
		} catch (IOException e) {
			String msg = NLS.bind(Messages.ConfiguredSite_UnableToAccessSite, (new Object[] { siteURL }));
			throw Utilities.newCoreException(msg, e);
		}

		return false;
	}

	/*
	* we have to check that no configured/enable parent include this feature
	*/
	private boolean validateNoConfiguredParents(IFeature feature) throws CoreException {
		if (feature == null) {
			UpdateCore.warn("ConfigurationPolicy: validate Feature is null"); //$NON-NLS-1$
			return true;
		}

		IFeatureReference[] parents = UpdateManagerUtils.getParentFeatures(feature, getConfiguredFeatures(), false);
		return (parents.length == 0);
	}

}
