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

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.model.ContentEntryModel;
import org.eclipse.update.core.model.FeatureModel;
import org.eclipse.update.core.model.FeatureReferenceModel;
import org.eclipse.update.core.model.ImportModel;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.core.model.NonPluginEntryModel;
import org.eclipse.update.core.model.PluginEntryModel;
import org.eclipse.update.core.model.URLEntryModel;
import org.eclipse.update.internal.core.ErrorRecoveryLog;
import org.eclipse.update.internal.core.InstallHandlerProxy;
import org.eclipse.update.internal.core.InstallRegistry;
import org.eclipse.update.internal.core.Messages;
import org.eclipse.update.internal.core.TargetFeature;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.internal.core.UpdateManagerUtils;
import org.eclipse.update.internal.core.UpdateSiteIncludedFeatureReference;

/**
 * Convenience implementation of a feature.
 * <p>
 * This class may be instantiated or subclassed by clients.
 * </p>
 * <p>
 * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
 * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
 * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
 * (repeatedly) as the API evolves.
 * </p> 
 * @see org.eclipse.update.core.IFeature
 * @see org.eclipse.update.core.model.FeatureModel
 * @since 2.0
 * @deprecated The org.eclipse.update component has been replaced by Equinox p2. This
 * provisional API was never promoted to stable API, and may be removed from a future release of the platform.
 */
public class Feature extends FeatureModel implements IFeature {

	/**
	 * Simple file name of the default feature manifest file
	 * @since 2.0
	 */
	public static final String FEATURE_FILE = "feature"; //$NON-NLS-1$

	/**
	 * File extension of the default feature manifest file
	 * @since 2.0
	 */
	public static final String FEATURE_XML = FEATURE_FILE + ".xml"; //$NON-NLS-1$

	private ISite site; // feature site
	private IFeatureContentProvider featureContentProvider; // content provider
	private List /*of IFeatureReference*/
	includedFeatureReferences;

	//PERF: new instance variable
	private VersionedIdentifier versionId;

	private InstallAbortedException abortedException = null;

	/**
	 * Feature default constructor
	 * 
	 * @since 2.0
	 */
	public Feature() {
	}

	/**
	 * Compares two features for equality
	 * 
	 * @param object feature object to compare with
	 * @return <code>true</code> if the two features are equal, 
	 * <code>false</code> otherwise
	 * @since 2.0
	 */
	public boolean equals(Object object) {
		if (!(object instanceof IFeature))
			return false;
		IFeature f = (IFeature) object;
		return getVersionedIdentifier().equals(f.getVersionedIdentifier());
	}

	/**
	 * Returns the feature identifier.
	 * 
	 * @see IFeature#getVersionedIdentifier()
	 * @since 2.0
	 */
	public VersionedIdentifier getVersionedIdentifier() {
		if (versionId != null)
			return versionId;

		String id = getFeatureIdentifier();
		String ver = getFeatureVersion();
		if (id != null && ver != null) {
			try {
				versionId = new VersionedIdentifier(id, ver);
				return versionId;
			} catch (Exception e) {
				UpdateCore.warn(
					"Unable to create versioned identifier:" + id + ":" + ver); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		versionId = new VersionedIdentifier(getURL().toExternalForm(), null);
		return versionId;
	}

	/**
	 * Returns the site this feature is associated with.
	 * 
	 * @see IFeature#getSite()
	 * @since 2.0
	 */
	public ISite getSite() {
		return site;
	}

	/**
	 * Returns the feature URL.
	 * 
	 * @see IFeature#getURL()
	 * @since 2.0
	 */
	public URL getURL() {
		IFeatureContentProvider contentProvider = null;
		try {
			contentProvider = getFeatureContentProvider();
		} catch (CoreException e) {
			UpdateCore.warn("No content Provider", e); //$NON-NLS-1$
		}
		return (contentProvider != null) ? contentProvider.getURL() : null;
	}

	/**
	 * Returns an information entry referencing the location of the
	 * feature update site. 
	 * 
	 * @see IFeature#getUpdateSiteEntry()
	 * @since 2.0
	 */
	public IURLEntry getUpdateSiteEntry() {
		return (IURLEntry) getUpdateSiteEntryModel();
	}

	/**
	 * Return an array of information entries referencing locations of other
	 * update sites.
	 * 
	 * @see IFeature#getDiscoverySiteEntries()
	 * @since 2.0
	 */
	public IURLEntry[] getDiscoverySiteEntries() {
		URLEntryModel[] result = getDiscoverySiteEntryModels();
		if (result.length == 0)
			return new IURLEntry[0];
		else
			return (IURLEntry[]) result;
	}

	/**
	 * Returns and optional custom install handler entry.
	 * 
	 * @see IFeature#getInstallHandlerEntry()
	 * @since 2.0
	 */
	public IInstallHandlerEntry getInstallHandlerEntry() {
		return (IInstallHandlerEntry) getInstallHandlerModel();
	}

	/**
	 * Returns the feature description.
	 * 
	 * @see IFeature#getDescription()
	 * @since 2.0
	 */
	public IURLEntry getDescription() {
		return (IURLEntry) getDescriptionModel();
	}

	/**
	 * Returns the copyright information for the feature.
	 * 
	 * @see IFeature#getCopyright()
	 * @since 2.0
	 */
	public IURLEntry getCopyright() {
		return (IURLEntry) getCopyrightModel();
	}

	/**
	 * Returns the license information for the feature.
	 * 
	 * @see IFeature#getLicense()
	 * @since 2.0
	 */
	public IURLEntry getLicense() {
		return (IURLEntry) getLicenseModel();
	}

	/**
	 * Return optional image for the feature.
	 * 
	 * @see IFeature#getImage()
	 * @since 2.0
	 */
	public URL getImage() {
		return getImageURL();
	}

	/**
	 * Return a list of plug-in dependencies for this feature.
	 * 
	 * @see IFeature#getRawImports()
	 * @since 2.0
	 */
	public IImport[] getRawImports() {
		ImportModel[] result = getImportModels();
		if (result.length == 0)
			return new IImport[0];
		else
			return (IImport[]) result;
	}

	/**
	 * Install the contents of this feature into the specified target feature.
	 * This method is a reference implementation of the feature installation
	 * protocol. Other concrete feature implementation that override this
	 * method need to implement this protocol.
	 * 
	 * @see IFeature#install(IFeature, IVerificationListener, IProgressMonitor)
	 * @since 2.0
	 */
	public IFeatureReference install(
		IFeature targetFeature,
		IVerificationListener verificationListener,
		IProgressMonitor progress)
		throws InstallAbortedException, CoreException {
		// call other API with all optional features, or setup variable meaning install all
		return install(targetFeature, null, verificationListener, progress);
	}

	/**
	 * Install the contents of this feature into the specified target feature.
	 * This method is a reference implementation of the feature installation
	 * protocol. Other concrete feature implementation that override this
	 * method need to implement this protocol.
	 * 
	 * @see IFeature#install(IFeature, IVerificationListener, IProgressMonitor)
	 * @since 2.0
	 */
	public IFeatureReference install(
		IFeature targetFeature,
		IFeatureReference[] optionalfeatures,
		IVerificationListener verificationListener,
		IProgressMonitor progress)
		throws InstallAbortedException, CoreException {

		//DEBUG
		debug("Installing...:" + getURL().toExternalForm()); //$NON-NLS-1$
		ErrorRecoveryLog recoveryLog = ErrorRecoveryLog.getLog();

		// make sure we have an InstallMonitor		
		InstallMonitor monitor;
		if (progress == null)
			monitor = new InstallMonitor(new NullProgressMonitor());
		else if (progress instanceof InstallMonitor)
			monitor = (InstallMonitor) progress;
		else
			monitor = new InstallMonitor(progress);

		// Setup optional install handler
		InstallHandlerProxy handler =
			new InstallHandlerProxy(
				IInstallHandler.HANDLER_ACTION_INSTALL,
				this,
				this.getInstallHandlerEntry(),
				monitor);
		boolean success = false;
		Throwable originalException = null;
		abortedException = null;

		// Get source feature provider and verifier.
		// Initialize target variables.
		IFeatureContentProvider provider = getFeatureContentProvider();
		IVerifier verifier = provider.getVerifier();
		IFeatureReference result = null;
		IFeatureReference alreadyInstalledFeature = null;
		IFeatureContentConsumer consumer = null;
		IPluginEntry[] targetSitePluginEntries = null;
		ArrayList justInstalledPlugins = new ArrayList();

		try {
			// determine list of plugins to install
			// find the intersection between the plugin entries already contained
			// on the target site, and plugin entries packaged in source feature
			IPluginEntry[] sourceFeaturePluginEntries = getPluginEntries();
			ISite targetSite = targetFeature.getSite();
			if (targetSite == null) {
				debug("The site to install in is null"); //$NON-NLS-1$
				targetSitePluginEntries = new IPluginEntry[0];
			} else {
				targetSitePluginEntries = targetSite.getPluginEntries();
			}
			IPluginEntry[] pluginsToInstall =
				UpdateManagerUtils.diff(
					sourceFeaturePluginEntries,
					targetSitePluginEntries);
			INonPluginEntry[] nonPluginsToInstall = getNonPluginEntries();

			IFeatureReference[] children = getIncludedFeatureReferences();
			if (optionalfeatures != null) {
				children =
					UpdateManagerUtils.optionalChildrenToInstall(
						children,
						optionalfeatures);
			}

			// determine number of monitor tasks
			//   2 tasks for the feature jar (download/verify + install)
			// + 2*n tasks for plugin entries (download/verify + install for each)
			// + 1*m tasks per non-plugin data entry (download for each)
			// + 1 task for custom non-plugin entry handling (1 for all combined)
			// + 5*x tasks for children features (5 subtasks per install)
			int taskCount =
				2
					+ 2 * pluginsToInstall.length
					+ nonPluginsToInstall.length
					+ 1
					+ 5 * children.length;
			monitor.beginTask("", taskCount); //$NON-NLS-1$
			SubProgressMonitor subMonitor = null;

			// start log
			recoveryLog.open(ErrorRecoveryLog.START_INSTALL_LOG);

			// Start the installation tasks			
			handler.installInitiated();

			// Download and verify feature archive(s)
			ContentReference[] references =
				provider.getFeatureEntryArchiveReferences(monitor);
			verifyReferences(
				verifier,
				references,
				monitor,
				verificationListener,
				true);
			monitorWork(monitor, 1);
			
			// Download and verify plugin archives
			for (int i = 0; i < pluginsToInstall.length; i++) {
				references = provider.getPluginEntryArchiveReferences(
						pluginsToInstall[i], monitor);
				verifyReferences(verifier, references, monitor,
								verificationListener, false);
				monitorWork(monitor, 1);
			}
			
			handler.pluginsDownloaded(pluginsToInstall);

			Vector filteredPlugins = new Vector();
            // Download non-plugin archives. Verification handled by optional
            // install handler
            for (int i = 0; i < nonPluginsToInstall.length; i++) {
                if (handler.acceptNonPluginData(nonPluginsToInstall[i])) {
                    references = provider.getNonPluginEntryArchiveReferences(
                            nonPluginsToInstall[i], monitor);
                    monitorWork(monitor, 1);
                    filteredPlugins.add(nonPluginsToInstall[i]);
                }
            }
            nonPluginsToInstall = (INonPluginEntry[]) filteredPlugins
                    .toArray(new INonPluginEntry[0]);
            handler.nonPluginDataDownloaded(nonPluginsToInstall,
                    verificationListener);

			// All archives are downloaded and verified. Get ready to install
			consumer = targetFeature.getFeatureContentConsumer();

			// install the children feature
			// check if they are optional, and if they should be installed [2.0.1]
			for (int i = 0; i < children.length; i++) {
				IFeature childFeature = null;
				try {
					childFeature = children[i].getFeature(null);
				} catch (CoreException e) {
					UpdateCore.warn(null, e);
				}
				if (childFeature != null) {
					subMonitor = new SubProgressMonitor(monitor, 5);
					((Site) targetSite).install(// need to cast
					childFeature,
						optionalfeatures,
						consumer,
						verifier,
						verificationListener,
						subMonitor);
				}
			}

			// Install plugin files
			for (int i = 0; i < pluginsToInstall.length; i++) {
				// if another feature has already installed this plugin, skip it
				if (InstallRegistry.getInstance().isPluginJustInstalled(pluginsToInstall[i])) {
					monitor.worked(1);
					continue;
				}
				IContentConsumer pluginConsumer =
					consumer.open(pluginsToInstall[i]);
				// TODO consumer.open returns either
				// SiteFilePackedPluginContentConsumer or SiteFilePluginContentConsumer
				// and they are fed either
				// PluginEntryArchiveReference or PluginEntryContentReferences
				// it would be better to have one that is given PluginEntryArchiveReference
				// but it would break external IContentConsumers

				if(pluginsToInstall[i] instanceof PluginEntryModel && !((PluginEntryModel)pluginsToInstall[i]).isUnpack()){
					// plugin can run from a jar
					references = provider.getPluginEntryArchiveReferences(
							pluginsToInstall[i], monitor);
				} else{
					// plugin must be unpacked
					references =
						provider.getPluginEntryContentReferences(
							pluginsToInstall[i],
							monitor);
				}

				String msg = ""; //$NON-NLS-1$
				subMonitor = new SubProgressMonitor(monitor, 1);
				VersionedIdentifier pluginVerId =
					pluginsToInstall[i].getVersionedIdentifier();
				String pluginID =
					(pluginVerId == null) ? "" : pluginVerId.getIdentifier(); //$NON-NLS-1$
				msg = NLS.bind(Messages.Feature_TaskInstallPluginFiles, (new String[] { pluginID }));

				for (int j = 0; j < references.length; j++) {
					setMonitorTaskName(
						subMonitor,
						msg + references[j].getIdentifier());
					pluginConsumer.store(references[j], subMonitor);
				}

				if (monitor.isCanceled())
					abort();
				else {
					justInstalledPlugins.add(pluginsToInstall[i]);
					InstallRegistry.registerPlugin(pluginsToInstall[i]);
				}
			}

			// check if we need to install feature files [16718]	
			// store will throw CoreException if another feature is already
			// installed in the same place
			alreadyInstalledFeature = featureAlreadyInstalled(targetSite);
			// 18867
			if (alreadyInstalledFeature == null) {
				//Install feature files
				references = provider.getFeatureEntryContentReferences(monitor);

				String msg = ""; //$NON-NLS-1$
				subMonitor = new SubProgressMonitor(monitor, 1);
				msg = Messages.Feature_TaskInstallFeatureFiles; 

				for (int i = 0; i < references.length; i++) {
					setMonitorTaskName(
						subMonitor,
						msg + " " + references[i].getIdentifier()); //$NON-NLS-1$
					consumer.store(references[i], subMonitor);
				}

				if (monitor.isCanceled())
					abort();
				else
					InstallRegistry.registerFeature(this);
			} else {
				if (monitor.isCanceled())
					abort();
				else
					monitor.worked(1);
			}

			// call handler to complete installation (eg. handle non-plugin entries)
			handler.completeInstall(consumer);
			monitorWork(monitor, 1);

			// indicate install success
			success = true;

		} catch (InstallAbortedException e) {
			abortedException = e;
		} catch (CoreException e) {
			originalException = e;
		} finally {
			Exception newException = null;
			try {
				if (consumer != null) {
					if (success) {
						result = consumer.close();
						if (result == null) {
							result = alreadyInstalledFeature; // 18867
							if (result != null
								&& optionalfeatures != null
								&& optionalfeatures.length > 0) {
								// reinitialize as new optional children may have been installed
								reinitializeFeature(result);
							}
						}
						// close the log
						recoveryLog.close(ErrorRecoveryLog.END_INSTALL_LOG);
					} else {
						// unregister the just installed plugins
						for (int i=0; i<justInstalledPlugins.size(); i++)
							InstallRegistry.unregisterPlugin(((IPluginEntry)justInstalledPlugins.get(i)));
						consumer.abort();
					}
				}
				handler.installCompleted(success);
				// if abort is done, no need for the log to stay
				recoveryLog.delete();
			} catch (CoreException e) {
				newException = e;
			}

			// original exception wins unless it is InstallAbortedException
			// and an error occured during abort
			if (originalException != null) {
				throw Utilities.newCoreException(
					NLS.bind(Messages.InstallHandler_error, (new String[] { this.getLabel() })),
					originalException);
			}

			if (newException != null)
				throw Utilities.newCoreException(
					NLS.bind(Messages.InstallHandler_error, (new String[] { this.getLabel() })),
					newException);

			if (abortedException != null) {
				throw abortedException;
			}

		}
		return result;
	}

	/**
	 * Returns an array of plug-in entries referenced by this feature
	 * 
	 * @see IFeature#getPluginEntries()
	 * @since 2.0
	 */
	public IPluginEntry[] getRawPluginEntries() {
		PluginEntryModel[] result = getPluginEntryModels();
		if (result.length == 0)
			return new IPluginEntry[0];
		else
			return (IPluginEntry[]) result;
	}

	/*
	 * Method filter.
	 * @param result
	 * @return IPluginEntry[]
	 */
	private IPluginEntry[] filterPluginEntry(IPluginEntry[] all) {
		List list = new ArrayList();
		if (all != null) {
			for (int i = 0; i < all.length; i++) {
				if (UpdateManagerUtils.isValidEnvironment(all[i]))
					list.add(all[i]);
			}
		}

		IPluginEntry[] result = new IPluginEntry[list.size()];
		if (!list.isEmpty()) {
			list.toArray(result);
		}

		return result;
	}

	/**
	 * Returns the count of referenced plug-in entries.
	 * 
	 * @see IFeature#getPluginEntryCount()
	 * @since 2.0
	 */
	public int getPluginEntryCount() {
		return getPluginEntries().length;
	}

	/**
	 * Returns an array of non-plug-in entries referenced by this feature
	 * 
	 * @see IFeature#getNonPluginEntries()
	 * @since 2.0
	 */
	public INonPluginEntry[] getRawNonPluginEntries() {
		NonPluginEntryModel[] result = getNonPluginEntryModels();
		if (result.length == 0)
			return new INonPluginEntry[0];
		else
			return (INonPluginEntry[]) result;
	}

	/**
	 * Returns the count of referenced non-plug-in entries.
	 * 
	 * @see IFeature#getNonPluginEntryCount()
	 * @since 2.0
	 */
	public int getNonPluginEntryCount() {
		return getNonPluginEntryModels().length;
	}

	/**
	 * Returns an array of feature references included by this feature
	 * 
	 * @return an erray of feature references, or an empty array.
	 * @since 2.0
	 */
	public IIncludedFeatureReference[] getRawIncludedFeatureReferences()
		throws CoreException {
		if (includedFeatureReferences == null)
			initializeIncludedReferences();

		if (includedFeatureReferences.size() == 0)
			return new IncludedFeatureReference[0];

		return (IIncludedFeatureReference[]) includedFeatureReferences.toArray(
			new IIncludedFeatureReference[includedFeatureReferences.size()]);
	}
	/**
	 * Returns the download size of the feature, if it can be determined.
	 * 
	 * @see IFeature#getDownloadSize()
	 * @since 2.0
	 */
	public long getDownloadSize() {
		try {
			Set allPluginEntries = new HashSet();
			Set allNonPluginEntries = new HashSet();

			IPluginEntry[] plugins = getPluginEntries();
			allPluginEntries.addAll(Arrays.asList(plugins));
			INonPluginEntry[] nonPlugins = getNonPluginEntries();
			allNonPluginEntries.addAll(Arrays.asList(nonPlugins));

			IFeatureReference[] children = getIncludedFeatureReferences();
			for (int i = 0; i < children.length; i++) {
				plugins = children[i].getFeature(null).getPluginEntries();
				allPluginEntries.addAll(Arrays.asList(plugins));
				nonPlugins = children[i].getFeature(null).getNonPluginEntries();
				allNonPluginEntries.addAll(Arrays.asList(nonPlugins));
			}

			IPluginEntry[] totalPlugins =
				new IPluginEntry[allPluginEntries.size()];
			INonPluginEntry[] totalNonPlugins =
				new INonPluginEntry[allNonPluginEntries.size()];
			if (allPluginEntries.size() != 0) {
				allPluginEntries.toArray(totalPlugins);
			}
			if (allNonPluginEntries.size() != 0) {
				allNonPluginEntries.toArray(totalNonPlugins);
			}

			return getFeatureContentProvider().getDownloadSizeFor(
				totalPlugins,
				totalNonPlugins);

		} catch (CoreException e) {
			UpdateCore.warn(null, e);
			return ContentEntryModel.UNKNOWN_SIZE;
		}
	}

	/**
	 * Returns the install size of the feature, if it can be determined.
	 * 
	 * @see IFeature#getInstallSize()
	 * @since 2.0
	 */
	public long getInstallSize() {
		try {
			Set allPluginEntries = new HashSet();
			Set allNonPluginEntries = new HashSet();

			IPluginEntry[] plugins = getPluginEntries();
			allPluginEntries.addAll(Arrays.asList(plugins));
			INonPluginEntry[] nonPlugins = getNonPluginEntries();
			allNonPluginEntries.addAll(Arrays.asList(nonPlugins));

			IFeatureReference[] children = getIncludedFeatureReferences();
			for (int i = 0; i < children.length; i++) {
				plugins = children[i].getFeature(null).getPluginEntries();
				allPluginEntries.addAll(Arrays.asList(plugins));
				nonPlugins = children[i].getFeature(null).getNonPluginEntries();
				allNonPluginEntries.addAll(Arrays.asList(nonPlugins));
			}

			IPluginEntry[] totalPlugins =
				new IPluginEntry[allPluginEntries.size()];
			INonPluginEntry[] totalNonPlugins =
				new INonPluginEntry[allNonPluginEntries.size()];
			if (allPluginEntries.size() != 0) {
				allPluginEntries.toArray(totalPlugins);
			}
			if (allNonPluginEntries.size() != 0) {
				allNonPluginEntries.toArray(totalNonPlugins);
			}

			return getFeatureContentProvider().getInstallSizeFor(
				totalPlugins,
				totalNonPlugins);

		} catch (CoreException e) {
			UpdateCore.warn(null, e);
			return ContentEntryModel.UNKNOWN_SIZE;
		}
	}

	/**
	 * Returns the content provider for this feature.
	 * 
	 * @see IFeature#getFeatureContentProvider()
	 * @since 2.0
	 */
	public IFeatureContentProvider getFeatureContentProvider()
		throws CoreException {
		if (featureContentProvider == null) {
			throw Utilities.newCoreException(
				NLS.bind(Messages.Feature_NoContentProvider, (new String[] { getVersionedIdentifier().toString() })),
				null);	
		}
		return this.featureContentProvider;
	}

	/**
	 * Returns the content consumer for this feature.
	 * 
	 * @see IFeature#getFeatureContentConsumer()
	 * @since 2.0
	 */
	public IFeatureContentConsumer getFeatureContentConsumer()
		throws CoreException {
		throw new UnsupportedOperationException();
	}

	/**
	 * Sets the site for this feature.
	 * 
	 * @see IFeature#setSite(ISite)
	 * @since 2.0
	 */
	public void setSite(ISite site) throws CoreException {
		if (this.site != null) {
			String featureURLString =
				(getURL() != null) ? getURL().toExternalForm() : ""; //$NON-NLS-1$
			throw Utilities.newCoreException(
				NLS.bind(Messages.Feature_SiteAlreadySet, (new String[] { featureURLString })),
				null);
		}
		this.site = site;
	}

	/**
	 * Sets the content provider for this feature.
	 * 
	 * @see IFeature#setFeatureContentProvider(IFeatureContentProvider)
	 * @since 2.0
	 */
	public void setFeatureContentProvider(IFeatureContentProvider featureContentProvider) {
		this.featureContentProvider = featureContentProvider;
		featureContentProvider.setFeature(this);
	}

	/**
	 * Return the string representation of this fetaure
	 * 
	 * @return feature as string
	 * @since 2.0
	 */
	public String toString() {
		String URLString =
			(getURL() == null)
				? Messages.Feature_NoURL
				: getURL().toExternalForm();

		String verString =
			NLS.bind(Messages.Feature_FeatureVersionToString, (new String[] { URLString, getVersionedIdentifier().toString() }));
		String label = getLabel() == null ? "" : getLabel(); //$NON-NLS-1$
		return verString + " [" + label + "]"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/*
	 * Installation has been cancelled, abort and revert
	 */
	private void abort() throws CoreException {
		String msg = Messages.Feature_InstallationCancelled; 
		throw new InstallAbortedException(msg, null);
	}

	/*
	 * Initializes includes feature references
	 * If the included feature reference is found on the site, add it to the List
	 * Otherwise attempt to instanciate it using the same type as this feature and
	 * using the default location on the site.
	 */
	private void initializeIncludedReferences() throws CoreException {
		includedFeatureReferences = new ArrayList();

		IIncludedFeatureReference[] nestedFeatures = getFeatureIncluded();
		if (nestedFeatures.length == 0)
			return;

		ISite site = getSite();
		if (site == null)
			return;

		for (int i = 0; i < nestedFeatures.length; i++) {
			IIncludedFeatureReference include = nestedFeatures[i];
			IIncludedFeatureReference newRef =
				getPerfectIncludeFeature(site, include);
			includedFeatureReferences.add(newRef);
		}
	}

	/*
	 * 
	 */
	private IIncludedFeatureReference getPerfectIncludeFeature(
		ISite site,
		IIncludedFeatureReference include)
		throws CoreException {

		// [20367] no site, cannot initialize nested references
		ISiteFeatureReference[] refs = site.getFeatureReferences();
		VersionedIdentifier identifier = include.getVersionedIdentifier();

		// too long to compute if not a file system
		// other solution would be to parse feature.xml
		// when parsing file system to create archive features/FeatureId_Ver.jar
		if ("file".equals(site.getURL().getProtocol())) { //$NON-NLS-1$
			// check if declared on the Site
			if (refs != null) {
				for (int ref = 0; ref < refs.length; ref++) {
					if (refs[ref] != null) {
						VersionedIdentifier id =
							refs[ref].getVersionedIdentifier();
						if (identifier.equals(id)) {
							// found a ISiteFeatureReference that matches our IIncludedFeatureReference
							IncludedFeatureReference newRef =
								new IncludedFeatureReference(refs[ref]);
							newRef.isOptional(include.isOptional());
							if (include instanceof FeatureReferenceModel)
								newRef.setLabel(
									((FeatureReferenceModel) include)
										.getLabel());
							newRef.setSearchLocation(
								include.getSearchLocation());
							return newRef;
						}
					}
				}
			}
		}

        // instantiate by mapping it based on the site.xml
        // in future we may ask for a factory to create the feature ref
        IncludedFeatureReference newRef = new UpdateSiteIncludedFeatureReference(include);
        newRef.setSite(getSite());
        IFeatureReference parentRef = getSite().getFeatureReference(this);
        if (parentRef instanceof FeatureReference) {
         newRef.setType(((FeatureReference) parentRef).getType());
        }
        String featureID = Site.DEFAULT_FEATURE_PATH + identifier.toString();
        if(this instanceof TargetFeature)
         featureID = featureID + "/"; //$NON-NLS-1$
        else
         featureID = featureID + ".jar"; //$NON-NLS-1$
		URL featureURL =
			getSite().getSiteContentProvider().getArchiveReference(featureID);
		newRef.setURL(featureURL);
		newRef.setFeatureIdentifier(identifier.getIdentifier());
		newRef.setFeatureVersion(identifier.getVersion().toString());
		try {
			newRef.resolve(getSite().getURL(), null);
			// no need to get the bundle
			return newRef;
		} catch (Exception e) {
			throw Utilities.newCoreException(
				NLS.bind(Messages.Feature_UnableToInitializeFeatureReference, (new String[] { identifier.toString() })),
				e);
		}
	}

	/*
	 * 
	 */
	private void debug(String trace) {
		//DEBUG
		if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) {
			UpdateCore.debug(trace);
		}
	}

	/*
	 * 
	 */
	private void setMonitorTaskName(
		IProgressMonitor monitor,
		String taskName) {
		if (monitor != null)
			monitor.setTaskName(taskName);
	}

	/*
	 *
	 */
	private void monitorWork(IProgressMonitor monitor, int tick)
		throws CoreException {
		if (monitor != null) {
			monitor.worked(tick);
			if (monitor.isCanceled()) {
				abort();
			}
		}
	}

	/*
	 * 
	 */
	private void verifyReferences(
		IVerifier verifier,
		ContentReference[] references,
		InstallMonitor monitor,
		IVerificationListener verificationListener,
		boolean isFeature)
		throws CoreException {
		IVerificationResult vr = null;
		if (verifier != null) {
			for (int j = 0; j < references.length; j++) {
				vr = verifier.verify(this, references[j], isFeature, monitor);
				if (vr != null) {
					if (verificationListener == null)
						return;

					int result = verificationListener.prompt(vr);

					if (result == IVerificationListener.CHOICE_ABORT) {
						String msg = Messages.JarVerificationService_CancelInstall; 
						Exception e = vr.getVerificationException();
						throw new InstallAbortedException(msg, e);
					}
					if (result == IVerificationListener.CHOICE_ERROR) {
						throw Utilities
							.newCoreException(
								Messages.JarVerificationService_UnsucessfulVerification,	
						vr.getVerificationException());
					}
				}
			}
		}
	}

	/*
	 * returns reference if the same feature is installed on the site
	 * [18867]
	 */
	private IFeatureReference featureAlreadyInstalled(ISite targetSite) {

		ISiteFeatureReference[] references = targetSite.getFeatureReferences();
		IFeatureReference currentReference = null;
		for (int i = 0; i < references.length; i++) {
			currentReference = references[i];
			// do not compare URL
			try {
				if (this.equals(currentReference.getFeature(null)))
					return currentReference; // 18867
			} catch (CoreException e) {
				UpdateCore.warn(null, e);
			}
		}

		UpdateCore.warn(
			"ValidateAlreadyInstalled:Feature " //$NON-NLS-1$
				+ this
				+ " not found on site:" //$NON-NLS-1$
				+ this.getURL());
		return null;
	}

	/*
	 * re initialize children of the feature, invalidate the cache
	 * @param result FeatureReference to reinitialize.
	 */
	private void reinitializeFeature(IFeatureReference referenceToReinitialize) {

		if (referenceToReinitialize == null)
			return;

		if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION)
			UpdateCore.debug(
				"Re initialize feature reference:" + referenceToReinitialize); //$NON-NLS-1$

		IFeature feature = null;
		try {
			feature = referenceToReinitialize.getFeature(null);
			if (feature != null && feature instanceof Feature) {
				((Feature) feature).initializeIncludedReferences();
			}
			// bug 24981 - recursively go into hierarchy
			// only if site if file 
			ISite site = referenceToReinitialize.getSite();
			if (site == null)
				return;
			URL url = site.getURL();
			if (url == null)
				return;
			if ("file".equals(url.getProtocol())) { //$NON-NLS-1$
				IFeatureReference[] included =
					feature.getIncludedFeatureReferences();
				for (int i = 0; i < included.length; i++) {
					reinitializeFeature(included[i]);
				}
			}
		} catch (CoreException e) {
			UpdateCore.warn("", e); //$NON-NLS-1$
		}
	}

	/**
	 * @see org.eclipse.update.core.IFeature#getRawIncludedFeatureReferences()
	 */
	public IIncludedFeatureReference[] getIncludedFeatureReferences()
		throws CoreException {
		return filterFeatures(getRawIncludedFeatureReferences());
	}

	/*
	 * Method filterFeatures.
	 * Also implemented in Site
	 * 
	 * @param list
	 * @return List
	 */
	private IIncludedFeatureReference[] filterFeatures(IIncludedFeatureReference[] allIncluded) {
		List list = new ArrayList();
		if (allIncluded != null) {
			for (int i = 0; i < allIncluded.length; i++) {
				IIncludedFeatureReference included = allIncluded[i];
				if (UpdateManagerUtils.isValidEnvironment(included))
					list.add(included);
				else {
					if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_WARNINGS) {
						UpdateCore.warn(
							"Filtered out feature reference:" + included); //$NON-NLS-1$
					}
				}
			}
		}

		IIncludedFeatureReference[] result =
			new IIncludedFeatureReference[list.size()];
		if (!list.isEmpty()) {
			list.toArray(result);
		}

		return result;
	}

	/**
	 * @see org.eclipse.update.core.IFeature#getRawNonPluginEntries()
	 */
	public INonPluginEntry[] getNonPluginEntries() {
		return filterNonPluginEntry(getRawNonPluginEntries());
	}

	/**
	 * Method filterPluginEntry.
	 * @param all
	 * @return INonPluginEntry[]
	 */
	private INonPluginEntry[] filterNonPluginEntry(INonPluginEntry[] all) {
		List list = new ArrayList();
		if (all != null) {
			for (int i = 0; i < all.length; i++) {
				if (UpdateManagerUtils.isValidEnvironment(all[i]))
					list.add(all[i]);
			}
		}

		INonPluginEntry[] result = new INonPluginEntry[list.size()];
		if (!list.isEmpty()) {
			list.toArray(result);
		}

		return result;
	}

	/**
	 * @see org.eclipse.update.core.IFeature#getRawPluginEntries()
	 */
	public IPluginEntry[] getPluginEntries() {
		return filterPluginEntry(getRawPluginEntries());
	}

	/**
	 * @see org.eclipse.update.core.IFeature#getImports()
	 */
	public IImport[] getImports() {
		return filterImports(getRawImports());
	}

	/**
	 * Method filterImports.
	 * @param all
	 * @return IImport[]
	 */
	private IImport[] filterImports(IImport[] all) {
		List list = new ArrayList();
		if (all != null) {
			for (int i = 0; i < all.length; i++) {
				if (UpdateManagerUtils.isValidEnvironment(all[i]))
					list.add(all[i]);
			}
		}

		IImport[] result = new IImport[list.size()];
		if (!list.isEmpty()) {
			list.toArray(result);
		}

		return result;
	}

}