/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     James D Miles (IBM Corp.) - bug 176250, Configurator needs to handle more platform urls
 *******************************************************************************/
package org.eclipse.update.internal.configurator;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.SyncFailedException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * This class is responsible for providing the features and plugins (bundles) to
 * the runtime. Configuration data is stored in the configuration/org.eclipse.update/platform.xml file.
 * When eclipse starts, it tries to load the config info from platform.xml.
 * If the file does not exist, then it also tries to read it from a temp or backup file.
 * If this does not succeed, a platform.xml is created by inspecting the eclipse
 * installation directory (its features and plugin folders).
 * If platform.xml already exists, a check is made to see when it was last modified
 * and whether there are any file system changes that are newer (users may manually unzip
 * features and plugins). In this case, the newly added features and plugins are picked up.
 * A check for existence of features and plugins is also performed, to detect deletions.
 */
public class PlatformConfiguration implements IPlatformConfiguration, IConfigurationConstants {

	private static PlatformConfiguration currentPlatformConfiguration = null;
	//private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
	//	private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
	private static final String XML_ENCODING = "UTF-8"; //$NON-NLS-1$

	private Configuration config;
	private URL configLocation;
	private long changeStamp;
	private long featuresChangeStamp;
	private boolean featuresChangeStampIsValid;
	private long pluginsChangeStamp;
	private boolean pluginsChangeStampIsValid;
	//PAL nio optional
	//private FileLock lock;
	private Locker lock = null;
	private static int defaultPolicy = DEFAULT_POLICY_TYPE;

	private static final String CONFIG_HISTORY = "history"; //$NON-NLS-1$
	private static final String PLATFORM_XML = "platform.xml"; //$NON-NLS-1$
	private static final String CONFIG_NAME = ConfigurationActivator.NAME_SPACE + "/" + PLATFORM_XML; //$NON-NLS-1$
	private static final String CONFIG_INI = "config.ini"; //NON-NLS-1$ //$NON-NLS-1$
	private static final String CONFIG_FILE_LOCK_SUFFIX = ".lock"; //$NON-NLS-1$
	private static final String CONFIG_FILE_TEMP_SUFFIX = ".tmp"; //$NON-NLS-1$
	private static final String[] BOOTSTRAP_PLUGINS = {};

	private static final String DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.ide.workbench"; //$NON-NLS-1$

	private static URL installURL;

	private PlatformConfiguration(Location platformConfigLocation) throws CoreException, IOException {

		this.config = null;

		// initialize configuration
		initializeCurrent(platformConfigLocation);
		if (config != null)
			setDefaultPolicy();

		// compute differences between configuration and actual content of the sites
		// (base sites and link sites)
		// Note: when the config is transient (generated by PDE, etc.) we don't reconcile
		if (isTransient())
			return;

		// for 'osgi.clean' or osgi.checkConfiguration', force a refresh
		boolean osgiClean = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.clean")); //$NON-NLS-1$ //$NON-NLS-2$
		boolean osgiCheckConfiguration = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.checkConfiguration")); //$NON-NLS-1$ //$NON-NLS-2$

		if (osgiClean || osgiCheckConfiguration) {
			// We have to call refresh() for features to be rescanned correctly
			refresh();
			reconcile();
		} else {
			changeStamp = computeChangeStamp();
			if (changeStamp > config.getDate().getTime())
				reconcile();
		}
	}

	PlatformConfiguration(URL url) throws Exception {
		URL installLocation = Utils.getInstallURL();
		// Retrieve install location with respect to given url if possible
		try {
			if (url != null && url.getProtocol().equals("file") && url.getPath().endsWith("configuration/org.eclipse.update/platform.xml")) {
				installLocation = new Path(url.getPath()).removeLastSegments(3).toFile().toURL();
			}
		} catch (Exception e) {
			//
		}
		initialize(url, installLocation);
	}

	public PlatformConfiguration(URL url, URL installLocation) throws Exception {
		initialize(url, installLocation);
	}

	private void setDefaultPolicy() {
		// Assumption: If the configuration that we initialize with
		// has a MANAGED_ONLY policy, then all sites should have default policy
		// of MANAGED_ONLY.
		ISiteEntry[] sentries = getConfiguredSites();
		if (sentries != null && sentries.length > 0) {
			int policyType = sentries[0].getSitePolicy().getType();
			if (policyType == ISitePolicy.MANAGED_ONLY) {
				defaultPolicy = policyType;
			}
		}
	}

	public static int getDefaultPolicy() {
		return defaultPolicy;
	}

	@Override
	public ISiteEntry createSiteEntry(URL url, ISitePolicy policy) {
		return new SiteEntry(url, policy);
	}

	@Override
	public ISitePolicy createSitePolicy(int type, String[] list) {
		return new SitePolicy(type, list);
	}

	@Override
	public IFeatureEntry createFeatureEntry(String id, String version, String pluginVersion, boolean primary, String application, URL[] root) {
		return new FeatureEntry(id, version, pluginVersion, primary, application, root);
	}

	@Override
	public IFeatureEntry createFeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) {
		return new FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root);
	}

	@Override
	public void configureSite(ISiteEntry entry) {
		configureSite(entry, false);
	}

	@Override
	public synchronized void configureSite(ISiteEntry entry, boolean replace) {

		if (entry == null)
			return;

		URL url = entry.getURL();
		if (url == null)
			return;

		String key = url.toExternalForm();
		if (config.getSiteEntry(key) != null && !replace)
			return;

		if (entry instanceof SiteEntry)
			config.addSiteEntry(key, (SiteEntry) entry);
	}

	@Override
	public synchronized void unconfigureSite(ISiteEntry entry) {
		if (entry == null)
			return;

		URL url = entry.getURL();
		if (url == null)
			return;

		String key = url.toExternalForm();
		if (entry instanceof SiteEntry)
			config.removeSiteEntry(key);
	}

	@Override
	public ISiteEntry[] getConfiguredSites() {
		if (config == null)
			return new ISiteEntry[0];

		SiteEntry[] sites = config.getSites();
		ArrayList<ISiteEntry> enabledSites = new ArrayList<>(sites.length);
		for (int i = 0; i < sites.length; i++) {
			if (sites[i].isEnabled())
				enabledSites.add(sites[i]);
		}
		return enabledSites.toArray(new ISiteEntry[enabledSites.size()]);
	}

	@Override
	public ISiteEntry findConfiguredSite(URL url) {
		return findConfiguredSite(url, true);
	}

	/**
	 *
	 * @param url site url
	 * @param checkPlatformURL if true, check for url format that is platform:/...
	 * @return
	 */
	public SiteEntry findConfiguredSite(URL url, boolean checkPlatformURL) {
		if (url == null)
			return null;
		String key = url.toExternalForm();

		SiteEntry result = config.getSiteEntry(key);
		if (result == null) { // retry with decoded URL string
			try {
				//PAL foundation
				//key = URLDecoder.decode(key, "UTF-8"); //$NON-NLS-1$
				key = URLDecoder.decode(key, "UTF-8"); //$NON-NLS-1$
			} catch (UnsupportedEncodingException e) {
				// ignore
			}
			result = config.getSiteEntry(key);
		}

		if (result == null && checkPlatformURL) {
			try {
				result = findConfiguredSite(config.asPlatformURL(url), false);
			} catch (Exception e) {
				//ignore
			}
		}
		return result;
	}

	@Override
	public synchronized void configureFeatureEntry(IFeatureEntry entry) {
		if (entry == null)
			return;

		String key = entry.getFeatureIdentifier();
		if (key == null)
			return;

		// we should check each site and find where the feature is
		// located and then configure it
		if (config == null)
			config = new Configuration();

		SiteEntry[] sites = config.getSites();
		for (int i = 0; i < sites.length; i++) {
			// find out what site contains the feature and configure it
			try {
				URL url = new URL(sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier() + "_" + entry.getFeatureVersion() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				try {
					url = resolvePlatformURL(url, getBasePathLocation(url, config.getInstallURL(), config.getURL()));
				} catch (IOException e) {
				}
				if (new File(url.getFile()).exists())
					sites[i].addFeatureEntry(entry);
				else {
					url = new URL(sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
					if (new File(url.getFile()).exists())
						sites[i].addFeatureEntry(entry);
				}
			} catch (MalformedURLException e) {
			}
		}
	}

	@Override
	public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) {
		if (entry == null)
			return;

		String key = entry.getFeatureIdentifier();
		if (key == null)
			return;

		config.unconfigureFeatureEntry(entry);
	}

	@Override
	public IFeatureEntry[] getConfiguredFeatureEntries() {
		ArrayList<IFeatureEntry> configFeatures = new ArrayList<>();
		SiteEntry[] sites = config.getSites();
		for (int i = 0; i < sites.length; i++) {
			FeatureEntry[] features = sites[i].getFeatureEntries();
			for (int j = 0; j < features.length; j++)
				configFeatures.add(features[j]);
		}
		return configFeatures.toArray(new FeatureEntry[configFeatures.size()]);
	}

	@Override
	public IFeatureEntry findConfiguredFeatureEntry(String id) {
		if (id == null)
			return null;

		SiteEntry[] sites = config.getSites();
		for (int i = 0; i < sites.length; i++) {
			FeatureEntry f = sites[i].getFeatureEntry(id);
			if (f != null)
				return f;
		}
		return null;
	}

	@Override
	public URL getConfigurationLocation() {
		return configLocation;
	}

	@Override
	public long getChangeStamp() {
		if (config.getLinkedConfig() == null)
			return config.getDate().getTime();
		return Math.max(config.getDate().getTime(), config.getLinkedConfig().getDate().getTime());
	}

	@Override
	@Deprecated
	public long getFeaturesChangeStamp() {
		return 0;
	}

	@Override
	@Deprecated
	public long getPluginsChangeStamp() {
		return 0;
	}

	public String getApplicationIdentifier() {
		// Return the app if defined in system properties
		String application = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_APPLICATION);
		if (application != null)
			return application;

		// Otherwise, try to get it from the primary feature (aka product)
		String feature = getPrimaryFeatureIdentifier();

		// lookup application for feature (specified or defaulted)
		if (feature != null) {
			IFeatureEntry fe = findConfiguredFeatureEntry(feature);
			if (fe != null) {
				if (fe.getFeatureApplication() != null)
					return fe.getFeatureApplication();
			}
		}

		// return hardcoded default if we failed
		return DEFAULT_FEATURE_APPLICATION;
	}

	@Override
	public String getPrimaryFeatureIdentifier() {
		// Return the product if defined in system properties
		String primaryFeatureId = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_PRODUCT);
		if (primaryFeatureId != null) {
			// check if feature exists
			IFeatureEntry feature = findConfiguredFeatureEntry(primaryFeatureId);
			if (feature != null && feature.canBePrimary())
				return primaryFeatureId;
		}
		return null;
	}

	@Override
	public URL[] getPluginPath() {
		ArrayList<URL> path = new ArrayList<>();
		Utils.debug("computed plug-in path:"); //$NON-NLS-1$

		ISiteEntry[] sites = getConfiguredSites();
		URL pathURL;
		for (int i = 0; i < sites.length; i++) {
			String[] plugins = sites[i].getPlugins();
			for (int j = 0; j < plugins.length; j++) {
				try {
					pathURL = new URL(((SiteEntry) sites[i]).getResolvedURL(), plugins[j]);
					path.add(pathURL);
					Utils.debug("   " + pathURL.toString()); //$NON-NLS-1$
				} catch (MalformedURLException e) {
					// skip entry ...
					Utils.debug("   bad URL: " + e); //$NON-NLS-1$
				}
			}
		}
		return path.toArray(new URL[0]);
	}

	public Set<String> getPluginPaths() {

		HashSet<String> paths = new HashSet<>();
		ISiteEntry[] sites = getConfiguredSites();

		for (int i = 0; i < sites.length; i++) {
			String[] plugins = sites[i].getPlugins();
			for (int j = 0; j < plugins.length; j++) {
				paths.add(plugins[j]);
			}
		}

		return paths;
	}

	/*
	 * A variation of the getPluginPath, but it returns the actual plugin entries
	 */
	public PluginEntry[] getPlugins() {
		ArrayList<PluginEntry> allPlugins = new ArrayList<>();
		Utils.debug("computed plug-ins:"); //$NON-NLS-1$

		ISiteEntry[] sites = getConfiguredSites();
		for (int i = 0; i < sites.length; i++) {
			if (!(sites[i] instanceof SiteEntry)) {
				Utils.debug("Site " + sites[i].getURL() + " is not a SiteEntry"); //$NON-NLS-1$ //$NON-NLS-2$
				continue;
			}
			PluginEntry[] plugins = ((SiteEntry) sites[i]).getPluginEntries();
			for (int j = 0; j < plugins.length; j++) {
				allPlugins.add(plugins[j]);
				Utils.debug("   " + plugins[j].getURL()); //$NON-NLS-1$
			}
		}
		return allPlugins.toArray(new PluginEntry[0]);
	}

	@Override
	public String[] getBootstrapPluginIdentifiers() {
		return BOOTSTRAP_PLUGINS;
	}

	@Override
	public void setBootstrapPluginLocation(String id, URL location) {
	}

	@Override
	public boolean isUpdateable() {
		return true;
	}

	@Override
	public boolean isTransient() {
		return (config != null) ? config.isTransient() : false;
	}

	@Override
	public void isTransient(boolean value) {
		if (this != getCurrent() && config != null)
			config.setTransient(value);
	}

	@Override
	public synchronized void refresh() {
		// Reset computed values. Will be lazily refreshed
		// on next access
		ISiteEntry[] sites = getConfiguredSites();
		for (int i = 0; i < sites.length; i++) {
			if (sites[i].isUpdateable() && sites[i].getSitePolicy().getType() != ISitePolicy.MANAGED_ONLY) {
				// reset site entry
				((SiteEntry) sites[i]).refresh();
			}
		}
	}

	@Override
	public void save() throws IOException {
		if (isUpdateable())
			save(configLocation);
	}

	@Override
	public synchronized void save(URL url) throws IOException {
		if (url == null)
			throw new IOException(Messages.cfig_unableToSave_noURL);

		if (!url.getProtocol().equals("file")) { //$NON-NLS-1$
			// not a file protocol - attempt to save to the URL
			URLConnection uc = url.openConnection();
			uc.setDoOutput(true);
			
			try(OutputStream os = uc.getOutputStream()) {
				saveAsXML(os);
				config.setDirty(false);
			} catch (CoreException e) {
				Utils.log(e.getMessage());
				Utils.log(e.getStatus());
				throw new IOException(NLS.bind(Messages.cfig_unableToSave, (new String[] {url.toExternalForm()})));
			}
		} else {
			// file protocol - do safe i/o
			File cfigFile = new File(url.getFile().replace('/', File.separatorChar));
			if (!cfigFile.getName().equals(PLATFORM_XML)) {
				if (cfigFile.exists() && cfigFile.isFile()) {
					Utils.log(Messages.PlatformConfiguration_expectingPlatformXMLorDirectory + cfigFile.getName());
					cfigFile = cfigFile.getParentFile();
				}
				cfigFile = new File(cfigFile, CONFIG_NAME);
			}
			File workingDir = cfigFile.getParentFile();
			if (workingDir != null && !workingDir.exists())
				workingDir.mkdirs();

			// Do safe i/o:
			//    - backup current config, by moving it to the history folder
			//    - write new config to platform.xml.tmp file
			//    - rename the temp file to platform.xml
			File cfigFileOriginal = new File(cfigFile.getAbsolutePath());
			File cfigTmp = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_TEMP_SUFFIX);

			// Backup old file
			if (cfigFile.exists()) {
				File backupDir = new File(workingDir, CONFIG_HISTORY);
				if (!backupDir.exists())
					backupDir.mkdir();
				long timestamp = cfigFile.lastModified();
				File preservedFile = new File(backupDir, String.valueOf(timestamp) + ".xml"); //$NON-NLS-1$
				// If the target file exists, increment the timestamp. Try at most 100 times.
				long increment = 1;
				while (preservedFile.exists() && increment < 100) {
					preservedFile = new File(backupDir, String.valueOf(timestamp + increment++) + ".xml"); //$NON-NLS-1$
				}
				if (!preservedFile.exists()) {
					// try renaming current config to backup copy
					if (!cfigFile.renameTo(preservedFile))
						Utils.log(Messages.PlatformConfiguration_cannotBackupConfig);
				}
			}

			// first save the file as temp
			try (FileOutputStream os = new FileOutputStream(cfigTmp)){
				saveAsXML(os);
				// Try flushing any internal buffers, and synchronize with the disk
				try {
					os.flush();
					os.getFD().sync();
				} catch (SyncFailedException e2) {
					Utils.log(e2.getMessage());
				} catch (IOException e2) {
					Utils.log(e2.getMessage());
				}
				try {
					os.close();
				} catch (IOException e1) {
					Utils.log(Messages.PlatformConfiguration_cannotCloseStream + cfigTmp);
					Utils.log(e1.getMessage());
				}
				// set file time stamp to match that of the config element
				cfigTmp.setLastModified(config.getDate().getTime());
				// set this on config, in case the value was rounded off
				config.setLastModified(cfigTmp.lastModified());
				// make the change stamp to be the same as the config file
				changeStamp = config.getDate().getTime();
				config.setDirty(false);
			} catch (CoreException e) {
				throw new IOException(NLS.bind(Messages.cfig_unableToSave, (new String[] {cfigTmp.getAbsolutePath()})));
			}

			// at this point we have old config (if existed) as "bak" and the
			// new config as "tmp".
			boolean ok = cfigTmp.renameTo(cfigFileOriginal);
			if (!ok) {
				// this codepath represents a tiny failure window. The load processing
				// on startup will detect missing config and will attempt to start
				// with "tmp" (latest), then "bak" (the previous). We can also end up
				// here if we failed to rename the current config to "bak". In that
				// case we will restart with the previous state.
				Utils.log(Messages.PlatformConfiguration_cannotRenameTempFile);

				throw new IOException(NLS.bind(Messages.cfig_unableToSave, (new String[] {cfigTmp.getAbsolutePath()})));
			}
		}
	}

	public static PlatformConfiguration getCurrent() {
		return currentPlatformConfiguration;
	}

	/**
	 * Starts a platform installed at specified installURL using configuration located at platformConfigLocation.
	 */
	public static synchronized void startup(URL installURL, Location platformConfigLocation) throws Exception {
		PlatformConfiguration.installURL = installURL;

		// create current configuration
		if (currentPlatformConfiguration == null) {
			currentPlatformConfiguration = new PlatformConfiguration(platformConfigLocation);
			if (currentPlatformConfiguration.config == null)
				throw new Exception(Messages.PlatformConfiguration_cannotLoadConfig + platformConfigLocation.getURL());
			if (currentPlatformConfiguration.config.isDirty())
				// If this is a transient config (generated by PDE),do nothing
				// otherwise, save the configuration with proper date
				if (!currentPlatformConfiguration.isTransient())
					currentPlatformConfiguration.save();
		}
	}

	public static synchronized void shutdown() throws IOException {

		// save platform configuration
		PlatformConfiguration config = getCurrent();
		if (config != null) {
			// only save if there are changes in the config
			if (config.config.isDirty() && !config.isTransient()) {
				try {
					config.save();
				} catch (IOException e) {
					Utils.debug("Unable to save configuration " + e.toString()); //$NON-NLS-1$
					// will recover on next startup
				}
			}
		}
	}

	private synchronized void initializeCurrent(Location platformConfigLocation) throws IOException {

		// Configuration URL was is specified by the OSGi layer.
		// Default behavior is to look
		// for configuration in the specified meta area. If not found, look
		// for pre-initialized configuration in the installation location.
		// If it is found it is used as the initial configuration. Otherwise
		// a new configuration is created. In either case the resulting
		// configuration is written into the specified configuration area.

		URL configFileURL = new URL(platformConfigLocation.getURL(), CONFIG_NAME);
		try {
			// check concurrent use lock
			getConfigurationLock(platformConfigLocation.getURL());

			// try loading the configuration
			try {
				config = loadConfig(configFileURL, installURL);
				Utils.debug("Using configuration " + configFileURL.toString()); //$NON-NLS-1$
			} catch (Exception e) {
				// failed to load, see if we can find pre-initialized configuration.
				try {
					Location parentLocation = platformConfigLocation.getParentLocation();
					if (parentLocation == null)
						throw new IOException(); // no platform.xml found, need to create default site

					URL sharedConfigFileURL = new URL(parentLocation.getURL(), CONFIG_NAME);
					config = loadConfig(sharedConfigFileURL, installURL);

					// pre-initialized config loaded OK ... copy any remaining update metadata
					// Only copy if the default config location is not the install location
					if (!sharedConfigFileURL.equals(configFileURL)) {
						// need to link config info instead of using a copy
						linkInitializedState(config, parentLocation, platformConfigLocation);
						Utils.debug("Configuration initialized from    " + sharedConfigFileURL.toString()); //$NON-NLS-1$
					}
					return;
				} catch (Exception ioe) {
					Utils.debug("Creating default configuration from " + configFileURL.toExternalForm()); //$NON-NLS-1$
					createDefaultConfiguration(configFileURL, installURL);
				}
			} finally {
				// if config == null an unhandled exception has been thrown and we allow it to propagate
				if (config != null) {
					configLocation = configFileURL;
					if (config.getURL() == null)
						config.setURL(configFileURL);
					verifyPath(configLocation, config.getInstallURL());
					Utils.debug("Creating configuration " + configFileURL.toString()); //$NON-NLS-1$
				}
			}
		} finally {
			// releaes concurrent use lock
			clearConfigurationLock();
		}
	}

	private synchronized void initialize(URL url, URL installLocation) throws Exception {
		if (url != null) {
			config = loadConfig(url, installLocation);
			Utils.debug("Using configuration " + url.toString()); //$NON-NLS-1$
		}
		if (config == null) {
			config = new Configuration();
			Utils.debug("Creating empty configuration object"); //$NON-NLS-1$
		}
		config.setURL(url);
		config.setInstallLocation(installLocation);
		configLocation = url;
	}

	private void createDefaultConfiguration(URL url, URL installLocation) throws IOException {
		// we are creating new configuration
		config = new Configuration();
		config.setURL(url);
		config.setInstallLocation(installLocation);
		SiteEntry defaultSite = (SiteEntry) getRootSite();
		configureSite(defaultSite);
		try {
			// parse the site directory to discover features
			defaultSite.loadFromDisk(0);
		} catch (CoreException e1) {
			Utils.log(Messages.PlatformConfiguration_cannotLoadDefaultSite + defaultSite.getResolvedURL());
			return;
		}
	}

	private ISiteEntry getRootSite() {
		// create default site entry for the root
		ISitePolicy defaultPolicy = createSitePolicy(getDefaultPolicy(), DEFAULT_POLICY_LIST);
		URL siteURL = null;
		try {
			siteURL = new URL("platform:/base/"); //$NON-NLS-1$  // try using platform-relative URL
		} catch (MalformedURLException e) {
			siteURL = getInstallURL(); // ensure we come up ... use absolute file URL
		}
		ISiteEntry defaultSite = createSiteEntry(siteURL, defaultPolicy);
		return defaultSite;
	}

	/**
	 * Gets the configuration lock
	 * @param url configuration directory
	 */
	private void getConfigurationLock(URL url) {
		if (!url.getProtocol().equals("file")) //$NON-NLS-1$
			return;

		File lockFile = new File(url.getFile(), ConfigurationActivator.NAME_SPACE + File.separator + CONFIG_FILE_LOCK_SUFFIX);
		verifyPath(url, config == null ? null : config.getInstallURL());
		// PAL nio optional
		lock = new Locker_JavaNio(lockFile);
		try {
			lock.lock();
		} catch (IOException ioe) {
			lock = null;
		}
	}

	private void clearConfigurationLock() {
		// PAL nio optional
		if (lock != null) {
			lock.release();
		}
	}

	private long computeChangeStamp() {
		featuresChangeStamp = computeFeaturesChangeStamp();
		pluginsChangeStamp = computePluginsChangeStamp();
		changeStamp = Math.max(featuresChangeStamp, pluginsChangeStamp);
		// round off to seconds
		changeStamp = (changeStamp / 1000) * 1000;
		return changeStamp;
	}

	private long computeFeaturesChangeStamp() {
		if (featuresChangeStampIsValid)
			return featuresChangeStamp;

		long result = 0;
		ISiteEntry[] sites = config.getSites();
		for (int i = 0; i < sites.length; i++) {
			if (sites[i].getSitePolicy().getType() != ISitePolicy.MANAGED_ONLY) {
				result = Math.max(result, sites[i].getFeaturesChangeStamp());
			}
		}
		featuresChangeStamp = result;
		featuresChangeStampIsValid = true;
		return featuresChangeStamp;
	}

	private long computePluginsChangeStamp() {
		if (pluginsChangeStampIsValid)
			return pluginsChangeStamp;

		long result = 0;
		ISiteEntry[] sites = config.getSites();
		for (int i = 0; i < sites.length; i++) {
			if (sites[i].getSitePolicy().getType() != ISitePolicy.MANAGED_ONLY) {
				result = Math.max(result, sites[i].getPluginsChangeStamp());
			}
		}
		pluginsChangeStamp = result;
		pluginsChangeStampIsValid = true;
		return pluginsChangeStamp;
	}

	private void linkInitializedState(Configuration sharedConfig, Location sharedConfigLocation, Location newConfigLocation) {
		try {
			URL newConfigIniURL = new URL(newConfigLocation.getURL(), CONFIG_INI);
			if (!newConfigIniURL.getProtocol().equals("file")) //$NON-NLS-1$
				return; // need to be able to do write

			// modify config.ini and platform.xml to only link original files
			File configIni = new File(newConfigIniURL.getFile());
			Properties props = new Properties();
			String externalForm = Utils.makeRelative(config.getInstallURL(), sharedConfigLocation.getURL()).toExternalForm();
			props.put("osgi.sharedConfiguration.area", externalForm); //$NON-NLS-1$
			props.store(new FileOutputStream(configIni), "Linked configuration"); //$NON-NLS-1$

			config = new Configuration(new Date());
			config.setURL(new URL(newConfigLocation.getURL(), CONFIG_NAME));
			config.setLinkedConfig(sharedConfig);
			config.setDirty(true);
		} catch (IOException e) {
			// this is an optimistic copy. If we fail, the state will be reconciled
			// when the update manager is triggered.
			System.out.println(e);
		}
	}

	private Configuration loadConfig(URL url, URL installLocation) throws Exception {
		if (url == null)
			throw new IOException(Messages.cfig_unableToLoad_noURL);

		// try to load saved configuration file (watch for failed prior save())
		ConfigurationParser parser = null;
		try {
			parser = new ConfigurationParser();
		} catch (InvocationTargetException e) {
			throw (Exception) e.getTargetException();
		}

		config = null;
		Exception originalException = null;
		try {
			config = parser.parse(url, installLocation);
			if (config == null)
				throw new Exception(Messages.PlatformConfiguration_cannotFindConfigFile);
		} catch (Exception e1) {
			// check for save failures, so open temp and backup configurations
			originalException = e1;
			try {
				URL tempURL = new URL(url.toExternalForm() + CONFIG_FILE_TEMP_SUFFIX);
				config = parser.parse(tempURL, installLocation);
				if (config == null)
					throw new Exception();
				config.setDirty(true); // force saving to platform.xml
			} catch (Exception e2) {
				try {
					// check the backup
					if ("file".equals(url.getProtocol())) { //$NON-NLS-1$
						File cfigFile = new File(url.getFile().replace('/', File.separatorChar));
						File workingDir = cfigFile.getParentFile();
						if (workingDir != null && workingDir.exists()) {
							File[] backups = workingDir.listFiles((FileFilter) pathname -> pathname.isFile() && pathname.getName().endsWith(".xml"));
							if (backups != null && backups.length > 0) {
								URL backupUrl = backups[backups.length - 1].toURL();
								config = parser.parse(backupUrl, installLocation);
							}
						}
					}
					if (config == null)
						throw originalException; // we tried, but no config here ...
					config.setDirty(true); // force saving to platform.xml
				} catch (IOException e3) {
					throw originalException; // we tried, but no config here ...
				}
			}
		}

		return config;
	}

	public static boolean supportsDetection(URL url, URL installLocation) {
		String protocol = url.getProtocol();
		if (protocol.equals("file")) //$NON-NLS-1$
			return true;
		else if (protocol.equals("platform")) { //$NON-NLS-1$
			URL resolved = null;
			try {
				resolved = resolvePlatformURL(url, installLocation); // 19536
			} catch (IOException e) {
				return false; // we tried but failed to resolve the platform URL
			}
			return resolved.getProtocol().equals("file"); //$NON-NLS-1$
		} else
			return false;
	}

	private static void verifyPath(URL url, URL installLocation) {
		String protocol = url.getProtocol();
		String path = null;
		if (protocol.equals("file")) //$NON-NLS-1$
			path = url.getFile();
		else if (protocol.equals("platform")) { //$NON-NLS-1$
			URL resolved = null;
			try {
				resolved = resolvePlatformURL(url, installLocation); // 19536
				if (resolved.getProtocol().equals("file")) //$NON-NLS-1$
					path = resolved.getFile();
			} catch (IOException e) {
				// continue ...
			}
		}

		if (path != null) {
			File dir = new File(path).getParentFile();
			if (dir != null)
				dir.mkdirs();
		}
	}

	public static URL resolvePlatformURL(URL url, URL base_path_Location) throws IOException {
		if (url.getProtocol().equals("platform")) { //$NON-NLS-1$
			if (base_path_Location == null) {
				url = FileLocator.toFileURL(url);
				File f = new File(url.getFile());
				url = f.toURL();
			} else {
				final String BASE = "platform:/base/";
				final String CONFIG = "platform:/config/";
				String toResolve = url.toExternalForm();
				if (toResolve.startsWith(BASE))
					url = new URL(base_path_Location, toResolve.substring(BASE.length()));
				else if (toResolve.startsWith(CONFIG)) {
					url = new URL(base_path_Location, toResolve.substring(CONFIG.length()));
				} else
					url = base_path_Location;
			}
		}
		return url;
	}

	private URL getBasePathLocation(URL url, URL installLocation, URL configLocation) {
		final String BASE = "platform:/base/";
		final String CONFIG = "platform:/config/";
		String toResolve = url.toExternalForm();
		if (toResolve.startsWith(BASE)) {
			return installLocation;
		} else if (toResolve.startsWith(CONFIG)) {
			URL config_loc;
			try {
				config_loc = new URL(configLocation, "..");
			} catch (MalformedURLException e) {
				return configLocation;
			}
			return config_loc;
		}
		return url;
	}

	public static URL getInstallURL() {
		return installURL;
	}

	private void saveAsXML(OutputStream stream) throws CoreException, IOException {
		BufferedWriter xmlWriter = new BufferedWriter(new OutputStreamWriter(stream, XML_ENCODING));
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setExpandEntityReferences(false);
			factory.setValidating(false);
			factory.setIgnoringComments(true);
			DocumentBuilder docBuilder = factory.newDocumentBuilder();
			Document doc = docBuilder.newDocument();

			if (config == null)
				throw Utils.newCoreException(Messages.PlatformConfiguration_cannotSaveNonExistingConfig, null);

			config.setDate(new Date());
			Element configElement = config.toXML(doc);
			doc.appendChild(configElement);

			// This is not DBCS friendly... PAL
			//XMLPrintHandler.printComment(xmlWriter,"Created on " + config.getDate().toString());
			XMLPrintHandler.printNode(xmlWriter, doc, XML_ENCODING);

		} catch (Exception e) {
			throw Utils.newCoreException("", e); //$NON-NLS-1$
		} finally {
			xmlWriter.flush();
			// will close the stream in the caller
			//xmlWriter.close();
		}
	}

	private void reconcile() throws CoreException {
		long lastChange = config.getDate().getTime();
		SiteEntry[] sites = config.getSites();
		for (int s = 0; s < sites.length; s++) {
			if (sites[s].isUpdateable() && sites[s].getSitePolicy().getType() != ISitePolicy.MANAGED_ONLY) {
				long siteTimestamp = sites[s].getChangeStamp();
				if (siteTimestamp > lastChange)
					sites[s].loadFromDisk(lastChange);
			}
		}
		config.setDirty(true);
	}

	public Configuration getConfiguration() {
		return config;
	}
}
