/*******************************************************************************
 * 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.configurator;

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.*;

import org.eclipse.core.runtime.*;
import org.eclipse.osgi.service.environment.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.configurator.*;
import org.eclipse.update.configurator.IPlatformConfiguration.*;
import org.w3c.dom.*;
import org.xml.sax.*;


public class SiteEntry implements IPlatformConfiguration.ISiteEntry, IConfigurationConstants{	
	private static final String MAC_OS_MARKER = ".DS_Store"; //$NON-NLS-1$
	
	private URL url; // this is the external URL for the site
	private URL resolvedURL; // this is the resolved URL used internally
	private ISitePolicy policy;
	private boolean updateable = true;
	private Map featureEntries;
	private ArrayList pluginEntries;
	private long changeStamp;
	private long featuresChangeStamp;
	private long pluginsChangeStamp;
	private String linkFileName;
	private boolean enabled = true;
	private Configuration config;
	
	private static FeatureParser featureParser = new FeatureParser();
	private static PluginParser pluginParser = new PluginParser();
	private static boolean isMacOS = Utils.getOS().equals(Constants.OS_MACOSX);

	public SiteEntry(URL url) {
		this(url,null);
	}
	
	public SiteEntry(URL url, ISitePolicy policy) {
		if (url == null)
			try {
				url = new URL("platform:/base/"); //$NON-NLS-1$ try using platform-relative URL
			} catch (MalformedURLException e) {
				url = PlatformConfiguration.getInstallURL(); // ensure we come up ... use absolute file URL
			}
			
		if (policy == null)
			policy = new SitePolicy(PlatformConfiguration.getDefaultPolicy(), DEFAULT_POLICY_LIST);

		if (url.getProtocol().equals("file")) { //$NON-NLS-1$
			try {
				// TODO remove this when platform fixes local file url's
				this.url = new File(url.getFile()).toURL(); 
			} catch (MalformedURLException e1) {
				this.url = url;
			}
		} else
			this.url = url;
		
		this.policy = policy;
		this.resolvedURL = this.url;
	}

	public void setConfig(Configuration config) {
		this.config = config;
		if (url.getProtocol().equals("platform")) { //$NON-NLS-1$
			try {
				// resolve the config location relative to the configURL
				if (url.getPath().startsWith("/config")) {	
					URL configURL = config.getURL();
					URL config_loc = new URL(configURL, "..");
					resolvedURL = PlatformConfiguration.resolvePlatformURL(url, config_loc); // 19536
				}
				else 
					resolvedURL = PlatformConfiguration.resolvePlatformURL(url, config.getInstallURL()); // 19536
			} catch (IOException e) {
				// will use the baseline URL ...
			}
		}
	}
	
	public Configuration getConfig() {
		return config;
	}
	
	/*
	 * @see ISiteEntry#getURL()
	 */
	public URL getURL() {
		return url;
	}

	/*
	* @see ISiteEntry#getSitePolicy()
	*/
	public ISitePolicy getSitePolicy() {
		return policy;
	}

	/*
	 * @see ISiteEntry#setSitePolicy(ISitePolicy)
	 */
	public synchronized void setSitePolicy(ISitePolicy policy) {
		if (policy == null)
			throw new IllegalArgumentException();
		this.policy = policy;
	}

	/*
	 * @see ISiteEntry#getFeatures()
	 */
	public String[] getFeatures() {
		return getDetectedFeatures();
	}

	/*
	 * @see ISiteEntry#getPlugins()
	 */
	public String[] getPlugins() {

		ISitePolicy policy = getSitePolicy();

		if (policy.getType() == ISitePolicy.USER_INCLUDE)
			return policy.getList();

		if (policy.getType() == ISitePolicy.USER_EXCLUDE) {
			ArrayList detectedPlugins = new ArrayList(Arrays.asList(getDetectedPlugins()));
			String[] excludedPlugins = policy.getList();
			for (int i = 0; i < excludedPlugins.length; i++) {
				if (detectedPlugins.contains(excludedPlugins[i]))
					detectedPlugins.remove(excludedPlugins[i]);
			}
			return (String[]) detectedPlugins.toArray(new String[0]);
		}
		
		if (policy.getType() == ISitePolicy.MANAGED_ONLY) {
			PluginEntry[] managedPlugins = getManagedPlugins();
			String[] managedPluginsURLs = new String[managedPlugins.length];
			for (int i=0; i<managedPlugins.length; i++)
				managedPluginsURLs[i] = managedPlugins[i].getURL();
			
			return managedPluginsURLs;
		}

		// bad policy type
		return new String[0];
	}

	private PluginEntry[] getManagedPlugins() {
		// Note:
		// We detect all the plugins on the site, but it would be faster
		// to just lookup the plugins that correspond to the entries found in each feature.
		// TODO fix the above
		if (pluginEntries == null)
			detectPlugins();
		if (featureEntries == null)
			detectFeatures();
		
		// cache all the plugin entries for faster lookup later
		Map cachedPlugins = new HashMap(pluginEntries.size());
		for (int i=0; i<pluginEntries.size(); i++) {
			PluginEntry p = (PluginEntry)pluginEntries.get(i);
			cachedPlugins.put(p.getVersionedIdentifier(), p);
		}
		
		ArrayList managedPlugins = new ArrayList();
		for (Iterator iterator=featureEntries.values().iterator(); iterator.hasNext();) {
			Object feature = iterator.next();
			if (!(feature instanceof FeatureEntry))
				continue;
			
			PluginEntry[] plugins = ((FeatureEntry)feature).getPluginEntries();
			for (int i=0; i<plugins.length; i++)
				if (cachedPlugins.containsKey(plugins[i].getVersionedIdentifier()))
					managedPlugins.add(cachedPlugins.get(plugins[i].getVersionedIdentifier()));
					
		}
		return (PluginEntry[])managedPlugins.toArray(new PluginEntry[managedPlugins.size()]);
	}
	
	public PluginEntry[] getPluginEntries() {
		String[] pluginURLs = getPlugins();
		// hash the array, for faster lookups
		HashMap map = new HashMap(pluginURLs.length);
		for (int i=0; i<pluginURLs.length; i++)
			map.put(pluginURLs[i], pluginURLs[i]);
		
		if (pluginEntries == null)
				detectPlugins();
		
		ArrayList plugins = new ArrayList(pluginURLs.length);
		for (int i=0; i<pluginEntries.size(); i++) {
			PluginEntry p = (PluginEntry)pluginEntries.get(i);
			if (map.containsKey(p.getURL()))
				plugins.add(p);
		}
		return (PluginEntry[])plugins.toArray(new PluginEntry[plugins.size()]);
	}
	
	/*
	 * @see ISiteEntry#getChangeStamp()
	 */
	public long getChangeStamp() {
		if (changeStamp == 0)
			computeChangeStamp();
		return changeStamp;
	}

	/*
	 * @see ISiteEntry#getFeaturesChangeStamp()
	 */
	public long getFeaturesChangeStamp() {
		if (featuresChangeStamp == 0)
			computeFeaturesChangeStamp();
		return featuresChangeStamp;
	}

	/*
	 * @see ISiteEntry#getPluginsChangeStamp()
	 */
	public long getPluginsChangeStamp() {
		if (pluginsChangeStamp == 0)
			computePluginsChangeStamp();
		return pluginsChangeStamp;
	}

	/*
	 * @see ISiteEntry#isUpdateable()
	 */
	public boolean isUpdateable() {
		return updateable;
	}
	
	public void setUpdateable(boolean updateable) {
		this.updateable = updateable;
	}

	/*
	 * @see ISiteEntry#isNativelyLinked()
	 */
	public boolean isNativelyLinked() {
		return isExternallyLinkedSite();
	}

	public URL getResolvedURL() {
		return resolvedURL;
	}
	
	/**
	 * Detect new features (timestamp > current site timestamp)
	 * and validates existing features (they might have been removed)
	 */
	private void detectFeatures() {

		if (featureEntries != null)
			validateFeatureEntries();
		else
			featureEntries = new HashMap();

		if (!PlatformConfiguration.supportsDetection(resolvedURL, config.getInstallURL()))
			return;

		// locate feature entries on site
		File siteRoot = new File(resolvedURL.getFile().replace('/', File.separatorChar));
		File featuresDir = new File(siteRoot, FEATURES);
		if (featuresDir.exists()) {
			// handle the installed features under the features directory
			File[] dirs = featuresDir.listFiles(new FileFilter() {
				public boolean accept(File f) {
					// mac os folders contain a file .DS_Store in each folder, and we need to skip it (bug 76869) 
					if (isMacOS && f.getName().equals(MAC_OS_MARKER))
						return false;
					boolean valid = f.isDirectory() && (new File(f,FEATURE_XML).exists());
					if (!valid)
						Utils.log(NLS.bind(Messages.SiteEntry_cannotFindFeatureInDir, (new String[] { f.getAbsolutePath() })));
					return valid;
				}
			});
		
			for (int index = 0; index < dirs.length; index++) {
				try {
					File featureXML = new File(dirs[index], FEATURE_XML);
					if (featureXML.lastModified() <= featuresChangeStamp &&
						dirs[index].lastModified() <= featuresChangeStamp)
						continue;
					URL featureURL = featureXML.toURL();
					FeatureEntry featureEntry = featureParser.parse(featureURL);
					if (featureEntry != null)
						addFeatureEntry(featureEntry);
				} catch (MalformedURLException e) {
					Utils.log(NLS.bind(Messages.InstalledSiteParser_UnableToCreateURLForFile, (new String[] { featuresDir.getAbsolutePath() })));
				}
			}
		}
		
		Utils.debug(resolvedURL.toString() + " located  " + featureEntries.size() + " feature(s)"); //$NON-NLS-1$ //$NON-NLS-2$
	}
	
	/**
	 * Detect new plugins (timestamp > current site timestamp)
	 * and validates existing plugins (they might have been removed)
	 */
	private void detectPlugins() {
		boolean compareTimeStamps = false;
		if (pluginEntries != null) {
			validatePluginEntries();
			compareTimeStamps = true; // only pick up newer plugins
		} else
			pluginEntries = new ArrayList();

		if (!PlatformConfiguration.supportsDetection(resolvedURL, config.getInstallURL()))
			return;

		// locate plugin entries on site
		File pluginsDir = new File(resolvedURL.getFile(), PLUGINS);
		
		if (pluginsDir.exists() && pluginsDir.isDirectory()) {
			File[] files = pluginsDir.listFiles();
			for (int i = 0; i < files.length; i++) {
				if(files[i].isDirectory()){
					detectUnpackedPlugin(files[i], compareTimeStamps);
				}else if(files[i].getName().endsWith(".jar")){ //$NON-NLS-1$
					detectPackedPlugin(files[i], compareTimeStamps);
				}else{
					// not bundle file
				}
			}
		} 
		
		Utils.debug(resolvedURL.toString() + " located  " + pluginEntries.size() + " plugin(s)"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * @param file a plugin jar
	 * @param compareTimeStamps set to true when looking for plugins changed since last time they were detected
	 */
	private void detectPackedPlugin(File file, boolean compareTimeStamps) {
		// plugin to run directly from jar
		if (compareTimeStamps && file.lastModified() <= pluginsChangeStamp) {
			return;
		}
		String entryName = META_MANIFEST_MF;
		ZipFile z = null;
		InputStream bundleManifestIn = null;
		InputStream pluginManifestIn = null;
		String pluginURL = PLUGINS + "/" + file.getName(); //$NON-NLS-1$
		try {
			// First, check if has valid bundle manifest
			z = new ZipFile(file);
			if (z.getEntry(entryName) != null) {
				bundleManifestIn = z.getInputStream(new ZipEntry(entryName));
				BundleManifest manifest = new BundleManifest(bundleManifestIn,
						pluginURL);
				if (manifest.exists()) {
					addPluginEntry(manifest.getPluginEntry());
					return;
				}
			}
			// no bundle manifest, check for plugin.xml or fragment.xml
			entryName = PLUGIN_XML;
			if (z.getEntry(entryName) == null) {
				entryName = FRAGMENT_XML;
			}
			if (z.getEntry(entryName) != null) {
				pluginManifestIn = z.getInputStream(new ZipEntry(entryName));
				PluginEntry entry1 = pluginParser.parse(pluginManifestIn,
						pluginURL);
				addPluginEntry(entry1);
			}
		} catch (IOException e5) {
			String pluginFileString2 = pluginURL + "!" + entryName; //$NON-NLS-1$
			Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorAccessing, (new String[] { pluginFileString2 })));
		} catch (SAXException e3) {
			String pluginFileString1 = pluginURL + "!" + entryName; //$NON-NLS-1$
			Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String[] { pluginFileString1 })));
		} finally {
			if (bundleManifestIn != null) {
				try {
					bundleManifestIn.close();
				} catch (IOException e4) {
				}
			}
			if (pluginManifestIn != null) {
				try {
					pluginManifestIn.close();
				} catch (IOException e2) {
				}
			}
			if (z != null) {
				try {
					z.close();
				} catch (IOException e1) {
				}
			}
		}
	}
	/**
	 * @param file a plugin directory
	 * @param compareTimeStamps set to true when looking for plugins changed since last time they were detected
	 */
	private void detectUnpackedPlugin(File file, boolean compareTimeStamps) {
		// unpacked plugin
		long dirTimestamp = file.lastModified();
		File pluginFile = new File(file, META_MANIFEST_MF);
		try {
			// First, check if has valid bundle manifest
			BundleManifest bundleManifest = new BundleManifest(pluginFile);
			if (bundleManifest.exists()) {
				if (compareTimeStamps
						&& dirTimestamp <= pluginsChangeStamp
						&& pluginFile.lastModified() <= pluginsChangeStamp)
					return;
				PluginEntry entry = bundleManifest.getPluginEntry();
				addPluginEntry(entry);
			} else {
				// no bundle manifest, check for plugin.xml or fragment.xml
				pluginFile = new File(file, PLUGIN_XML);
				if (!pluginFile.exists()) { 
					pluginFile = new File(file, FRAGMENT_XML); 
				}
				if (pluginFile.exists() && !pluginFile.isDirectory()) {
					// TODO in the future, assume that the timestamps are not
					// reliable,
					// or that the user manually modified an existing plugin,
					// so
					// the apparently modifed plugin may actually be configured
					// already.
					// We will need to double check for this. END to do.
					if (compareTimeStamps 
							&& dirTimestamp <= pluginsChangeStamp
							&& pluginFile.lastModified() <= pluginsChangeStamp)
						return;
					PluginEntry entry = pluginParser.parse(pluginFile);
					addPluginEntry(entry);
				}
			}
		} catch (IOException e) {
			String pluginFileString = pluginFile.getAbsolutePath();
			if (ConfigurationActivator.DEBUG)
				Utils.log(Utils.newStatus(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String[] { pluginFileString })), e));
			else
				Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorAccessing, (new String[] { pluginFileString })));
		} catch (SAXException e) {
			String pluginFileString = pluginFile.getAbsolutePath();
			Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String[] { pluginFileString })));
        }
	}

	/**
	 * @return list of feature url's (relative to site)
	 */
	private synchronized String[] getDetectedFeatures() {
		if (featureEntries == null)
			detectFeatures();
		String[] features = new String[featureEntries.size()];
		Iterator iterator = featureEntries.values().iterator();
		for (int i=0; i<features.length; i++)
			features[i] = ((FeatureEntry)iterator.next()).getURL();
		return features;
	}

	/**
	 * @return list of plugin url's (relative to site)
	 */
	private synchronized String[] getDetectedPlugins() {
		if (pluginEntries == null)
			detectPlugins();
		
		String[] plugins = new String[pluginEntries.size()];
		for (int i=0; i<plugins.length; i++)
			plugins[i] = ((PluginEntry)pluginEntries.get(i)).getURL();
		return plugins;
	}

	private void computeChangeStamp() {
		changeStamp = Math.max(computeFeaturesChangeStamp(), computePluginsChangeStamp());
//		changeStampIsValid = true;
	}

	private synchronized long computeFeaturesChangeStamp() {
		if (featuresChangeStamp > 0)
			return featuresChangeStamp;
		
		long start = 0;
		if (ConfigurationActivator.DEBUG)
			start = (new Date()).getTime();
		String[] features = getFeatures();
	
		// compute stamp for the features directory
		long dirStamp = 0;
		if (PlatformConfiguration.supportsDetection(resolvedURL, config.getInstallURL())) {
			File root = new File(resolvedURL.getFile().replace('/', File.separatorChar));
			File featuresDir = new File(root, FEATURES);
			dirStamp = featuresDir.lastModified();
		}
		featuresChangeStamp = Math.max(dirStamp, computeStamp(features));
		if (ConfigurationActivator.DEBUG) {
			long end = (new Date()).getTime();
			Utils.debug(resolvedURL.toString() + " feature stamp: " + featuresChangeStamp + " in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$   
		}
		return featuresChangeStamp;
	}

	private synchronized long computePluginsChangeStamp() {
		if (pluginsChangeStamp > 0)
			return pluginsChangeStamp;
		
		if (!PlatformConfiguration.supportsDetection(resolvedURL, config.getInstallURL())) {
			Utils.log(NLS.bind(Messages.SiteEntry_computePluginStamp, (new String[] { resolvedURL.toExternalForm() })));
			return 0;
		}

		// compute stamp for the plugins directory
		File root = new File(resolvedURL.getFile().replace('/', File.separatorChar));
		File pluginsDir = new File(root, PLUGINS);
		if (!pluginsDir.exists() || !pluginsDir.isDirectory()) {
			Utils.debug(NLS.bind(Messages.SiteEntry_pluginsDir, (new String[] { pluginsDir.getAbsolutePath() })));
			return 0;
		}

		pluginsChangeStamp = pluginsDir.lastModified();
		return pluginsChangeStamp;
	}

	private long computeStamp(String[] targets) {

		long result = 0;
		if (!PlatformConfiguration.supportsDetection(resolvedURL, config.getInstallURL())) {
			// NOTE:  this path should not be executed until we support running
			//        from an arbitrary URL (in particular from http server). For
			//        now just compute stamp across the list of names. Eventually
			//        when general URLs are supported we need to do better (factor
			//        in at least the existence of the target). However, given this
			//        code executes early on the startup sequence we need to be
			//        extremely mindful of performance issues.
			// In fact, we should get the last modified from the connection
			for (int i = 0; i < targets.length; i++)
				result ^= targets[i].hashCode();
			Utils.debug("*WARNING* computing stamp using URL hashcodes only"); //$NON-NLS-1$
		} else {
			// compute stamp across local targets
			File rootFile = new File(resolvedURL.getFile().replace('/', File.separatorChar));
			if (rootFile.exists()) {
				File f = null;
				for (int i = 0; i < targets.length; i++) {
					f = new File(rootFile, targets[i]);
					if (f.exists())
						result = Math.max(result, f.lastModified());
				}
			}
		}

		return result;
	}
	
	public void setLinkFileName(String linkFileName) {
		this.linkFileName = linkFileName;
	}
	
	public String getLinkFileName() {
		return linkFileName;
	}

	public boolean isExternallyLinkedSite() {
		return (linkFileName != null && !linkFileName.trim().equals("")); //$NON-NLS-1$
	}

	public synchronized void refresh() {
		// reset computed values. Will be updated on next access.
		featuresChangeStamp = 0;
		pluginsChangeStamp = 0;
		changeStamp = 0;
		featureEntries = null;
		pluginEntries = null;
	}
	
	public void refreshPlugins() {
		// reset computed values. Will be updated on next access.
		pluginsChangeStamp = 0;
		changeStamp = 0;
		pluginEntries = null;
	}
	
	public void addFeatureEntry(IFeatureEntry feature) {
		if (featureEntries == null)
			featureEntries = new HashMap();
		// Make sure we keep the larger version of same feature
		IFeatureEntry existing = (FeatureEntry)featureEntries.get(feature.getFeatureIdentifier());
		if (existing != null) {
			VersionedIdentifier existingVersion = new VersionedIdentifier(existing.getFeatureIdentifier(), existing.getFeatureVersion());
			VersionedIdentifier newVersion = new VersionedIdentifier(feature.getFeatureIdentifier(), feature.getFeatureVersion());
			if (existingVersion.getVersion().compareTo(newVersion.getVersion()) < 0) {
				featureEntries.put(feature.getFeatureIdentifier(), feature);
				pluginsChangeStamp = 0;
			} else if (existingVersion.equals(newVersion)) {
				// log error if same feature version/id but a different url
				if (feature instanceof FeatureEntry && existing instanceof FeatureEntry &&
						!((FeatureEntry)feature).getURL().equals(((FeatureEntry)existing).getURL()))
				Utils.log(NLS.bind(Messages.SiteEntry_duplicateFeature, (new String[] { getURL().toExternalForm(), existing.getFeatureIdentifier() })));
			}
		} else {
			featureEntries.put(feature.getFeatureIdentifier(), feature);
			pluginsChangeStamp = 0;
		}
		if (feature instanceof FeatureEntry)
			((FeatureEntry)feature).setSite(this);
	}
	
	public FeatureEntry[] getFeatureEntries() {
		if (featureEntries == null)
			detectFeatures();
		
		if (featureEntries == null)
			return new FeatureEntry[0];
		return (FeatureEntry[])featureEntries.values().toArray(new FeatureEntry[featureEntries.size()]);
	}
	
	public void addPluginEntry(PluginEntry plugin) {
		if (pluginEntries == null)
			pluginEntries = new ArrayList();
		// Note: we could use the latest version of the same plugin, like we do for features, but we let the runtime figure it out
		pluginEntries.add(plugin);
	}
	
	public PluginEntry[] getAllPluginEntries() {
		if (pluginEntries == null)
			detectPlugins();
		return (PluginEntry[])pluginEntries.toArray(new PluginEntry[pluginEntries.size()]);
	}
	
	public void loadFromDisk(long lastChange) throws CoreException{
		featuresChangeStamp = lastChange;
		pluginsChangeStamp = lastChange;
		detectFeatures();
		detectPlugins();
	}
	
	/**
	 * Saves state as xml content in a given parent element
	 * @param doc
	 */
	public Element toXML(Document doc) {

		Element siteElement = doc.createElement(CFG_SITE);
		
		if (getURL() != null) {
			URL toPersist = (config == null || config.isTransient()) ? getURL() : Utils.makeRelative(Utils.getInstallURL(), getURL());
			siteElement.setAttribute(CFG_URL, toPersist.toString());
		}
		
		siteElement.setAttribute(CFG_ENABLED, isEnabled() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
		siteElement.setAttribute(CFG_UPDATEABLE, isUpdateable() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
		if (isExternallyLinkedSite()) 
			siteElement.setAttribute(CFG_LINK_FILE, getLinkFileName().trim().replace(File.separatorChar, '/')); 

		int type = getSitePolicy().getType();
		String typeString = CFG_POLICY_TYPE_UNKNOWN;
		try {
			typeString = CFG_POLICY_TYPE[type];
		} catch (IndexOutOfBoundsException e) {
			// ignore bad attribute ...
		}
		siteElement.setAttribute(CFG_POLICY, typeString); 
		String[] list = getSitePolicy().getList();
		if (list.length > 0) {
			StringBuffer sb = new StringBuffer(256);
			for (int i=0; i<list.length-1; i++) {
				sb.append(list[i]);
				sb.append(',');
			}
			sb.append(list[list.length-1]);
			siteElement.setAttribute(CFG_LIST, sb.toString());
		}
//		// note: we don't save features inside the site element.
		
		// collect feature entries
//		configElement.setAttribute(CFG_FEATURE_ENTRY_DEFAULT, defaultFeature);
		FeatureEntry[] feats = getFeatureEntries();
		for (int i = 0; i < feats.length; i++) {
			Element featureElement = feats[i].toXML(doc);
			siteElement.appendChild(featureElement);
		}
		
		return siteElement;
	}
	
	private void validateFeatureEntries() {
		File root = new File(resolvedURL.getFile().replace('/', File.separatorChar));
		Iterator iterator = featureEntries.values().iterator();
		Collection deletedFeatures = new ArrayList();
		while(iterator.hasNext()) {
			FeatureEntry feature = (FeatureEntry)iterator.next();
			// Note: in the future, we can check for absolute url as well.
			//       For now, feature url is features/org.eclipse.foo/feature.xml
			File featureXML = new File(root, feature.getURL());
			if (!featureXML.exists())
				deletedFeatures.add(feature.getFeatureIdentifier());
		}
		for(Iterator it=deletedFeatures.iterator(); it.hasNext();){
			featureEntries.remove(it.next());
		}
	}
	
	private void validatePluginEntries() {
		File root = new File(resolvedURL.getFile().replace('/', File.separatorChar));
		Collection deletedPlugins = new ArrayList();
		for (int i=0; i<pluginEntries.size(); i++) {
			PluginEntry plugin = (PluginEntry)pluginEntries.get(i);
			// Note: in the future, we can check for absolute url as well.
			//       For now, feature url is plugins/org.eclipse.foo/plugin.xml
			File pluginLocation = new File(root, plugin.getURL());
			if (!pluginLocation.exists())
				deletedPlugins.add(plugin);
		}
		for(Iterator it=deletedPlugins.iterator(); it.hasNext();){
			pluginEntries.remove(it.next());
		}
	}
	
	public boolean isEnabled() {
		return enabled;
	}
	
	public void setEnabled(boolean enable) {
		this.enabled = enable;
	}
	
	public FeatureEntry getFeatureEntry(String id) {
		FeatureEntry[] features = getFeatureEntries();
		for (int i=0; i<features.length; i++)
			if (features[i].getFeatureIdentifier().equals(id)) 
				return features[i];
		return null;
	}
	
	
	public boolean unconfigureFeatureEntry(IFeatureEntry feature) {
		FeatureEntry existingFeature = getFeatureEntry(feature.getFeatureIdentifier());
		if (existingFeature != null)
			featureEntries.remove(existingFeature.getFeatureIdentifier());
		return existingFeature != null;
	}
	
	/*
	 * This is a bit of a hack.
	 * When no features were added to the site, but the site is initialized from platform.xml 
	 * we need to set the feature set to empty, so we don't try to detect them.
	 */
	public void initialized() { 
		if (featureEntries == null)
			featureEntries = new HashMap();
	}
}
