/*******************************************************************************
 * Copyright (c) 2009, 2019 Xored Software Inc 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:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.launching.internal.target;

import static com.google.common.base.Charsets.UTF_8;
import static java.util.Collections.emptyList;
import static org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchingPlugin.PLUGIN_ID;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.launcher.Constants;
import org.eclipse.equinox.internal.simpleconfigurator.utils.SimpleConfiguratorUtils;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.osgi.service.resolver.ResolverError;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.core.target.ITargetPlatformService;
import org.eclipse.pde.core.target.TargetBundle;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.PDEExtensionRegistry;
import org.eclipse.pde.internal.core.PDEState;
import org.eclipse.pde.internal.core.target.IUBundleContainer;
import org.eclipse.pde.internal.core.target.P2TargetUtils;
import org.eclipse.pde.internal.core.target.ProfileBundleContainer;
import org.eclipse.pde.internal.launching.launcher.LaunchValidationOperation;
import org.eclipse.rcptt.internal.launching.Q7LaunchingPlugin;
import org.eclipse.rcptt.internal.launching.ext.AJConstants;
import org.eclipse.rcptt.internal.launching.ext.OSArchitecture;
import org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchingPlugin;
import org.eclipse.rcptt.launching.ext.AUTInformation;
import org.eclipse.rcptt.launching.ext.OriginalOrderProperties;
import org.eclipse.rcptt.launching.ext.Q7LaunchDelegateUtils;
import org.eclipse.rcptt.launching.injection.Directory;
import org.eclipse.rcptt.launching.injection.Entry;
import org.eclipse.rcptt.launching.injection.InjectionConfiguration;
import org.eclipse.rcptt.launching.injection.UpdateSite;
import org.eclipse.rcptt.launching.internal.target.Q7Target.AutInstall;
import org.eclipse.rcptt.launching.p2utils.P2Utils;
import org.eclipse.rcptt.launching.target.ITargetPlatformHelper;
import org.eclipse.rcptt.launching.target.TargetPlatformManager;
import org.eclipse.rcptt.util.FileUtil;
import org.osgi.framework.Version;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;

@SuppressWarnings("restriction")
public class TargetPlatformHelper implements ITargetPlatformHelper {
	private static final boolean DEBUG = "true"
			.equals(Platform.getDebugOption("org.eclipse.rcptt.launching.ext/debug"));
	private static final boolean DEBUG_BUNDLES = "true"
			.equals(Platform.getDebugOption("org.eclipse.rcptt.launching.ext/debug/bundles"));
	public static final String IDE_APPLICATION = "org.eclipse.ui.ide.workbench";
	public static final String APPLICATION_PROPERTY = "eclipse.application"; //$NON-NLS-1$
	public static final String PRODUCT_PROPERTY = "eclipse.product"; //$NON-NLS-1$
	private static final String ID_PROPERTY = "id"; //$NON-NLS-1$
	private static final String OSGI_BUNDLES = "osgi.bundles";
	public static final String SIMPLECONFIGURATOR = "org.eclipse.equinox.simpleconfigurator"; //$NON-NLS-1$
	private static final String SC_BUNDLES_PATH = "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info"; //$NON-NLS-1$
	private IStatus status = Status.OK_STATUS;
	private final ITargetDefinition target;
	private final ArrayList<ITargetLocation> extra = new ArrayList<ITargetLocation>();
	private IPluginModelBase[] models;
	private PDEExtensionRegistry registry;

	private Q7Target q7target = new Q7Target();

	public TargetPlatformHelper(ITargetDefinition target) {
		Preconditions.checkNotNull(target);
		this.target = target;
		initialize();
	}

	public Q7Target getQ7Target() {
		return q7target;
	}

	public String getUserArea() {
		final AutInstall install = getAutInstall();
		if (install == null) {
			return null;
		}
		return install.userArea;
	}

	@Deprecated
	/** Use getStatus().isOK() instead */
	public boolean isValid() {
		return getStatus().isOK();
	}

	public boolean isResolved() {
		if (target != null) {
			return target.isResolved();
		}
		return false;
	}

	public boolean isInstanceContainerValid() {
		return getInstanceContainer() != null
				&& getInstanceContainer().getStatus().isOK();
	}

	public IStatus getStatus() {
		if (status == null) {
			return new Status(IStatus.ERROR, PLUGIN_ID, "Target platform is unset");
		}
		return status;
	}

	@Deprecated
	public String getErrorMessage() {
		return getNonMultiStatusMessage(getStatus());
	}

	public String getWarningMessage() {
		if (target != null) {
			IStatus bundleStatus = getBundleWarningStatus();
			return getNonMultiStatusMessage(bundleStatus);
		}
		return null;
	}

	public IStatus getBundleStatus() {
		ITargetLocation[] containers = getBundleContainers();
		if (containers != null) {
			// Check if the containers have any resolution problems
			MultiStatus result = new MultiStatus(
					PDECore.PLUGIN_ID,
					0,
					org.eclipse.pde.internal.core.target.Messages.TargetDefinition_5,
					null);
			for (int i = 0; i < containers.length; i++) {
				ITargetLocation container = containers[i];
				IStatus containerStatus = container.getStatus();
				if (containerStatus != null && !containerStatus.isOK()) {
					result.add(containerStatus);
				}
			}
			if (!result.isOK()) {
				return result;
			}

			// Check if any of the included bundles have problems
			// build status from bundle list
			TargetBundle[] bundles = target.getBundles();
			for (int i = 0; i < bundles.length; i++) {
				TargetBundle bundle = bundles[i];
				if (!bundle.getStatus().isOK()) {
					BundleInfo info = bundle.getBundleInfo();
					URI uri = info.getLocation();
					if (uri != null) {
						File file = new File(uri);
						if (!file.exists()) {
							reportUnexistingFile(info);
							continue;
						}
					}
					result.add(bundle.getStatus());
				}
			}

			if (result.isOK()) {
				// Return generic ok status instead of problem multi-status with
				// no children
				return Status.OK_STATUS;
			}
			return result;
		}
		return Status.OK_STATUS;
	}

	private void reportUnexistingFile(BundleInfo info) {
		// Skip problem of nonexistent file.
		Q7LaunchingPlugin.log(Q7LaunchingPlugin.createStatus(IStatus.WARNING,
				"Skip nonexistent bundle: " + info.getSymbolicName()
						+ ", then resolve configuration.",
				null));
	}

	public IStatus getBundleWarningStatus() {
		ITargetLocation[] containers = getBundleContainers();
		if (containers != null) {
			// Check if the containers have any resolution problems
			MultiStatus result = new MultiStatus(
					PDECore.PLUGIN_ID,
					0,
					org.eclipse.pde.internal.core.target.Messages.TargetDefinition_5,
					null);

			// Check if any of the included bundles have problems
			// build status from bundle list
			TargetBundle[] bundles = target.getBundles();
			for (int i = 0; i < bundles.length; i++) {
				TargetBundle bundle = bundles[i];
				IStatus status = bundle.getStatus();
				if (!status.isOK()) {
					BundleInfo info = bundle.getBundleInfo();
					URI uri = info.getLocation();
					if (uri != null) {
						File file = new File(uri);
						if (!file.exists()) {
							// Skip problem of nonexistent file.
							IStatus st = new Status(IStatus.WARNING,
									status.getPlugin(), status.getMessage(),
									status.getException());
							result.add(st);
						}
					}

				}
			}

			if (result.isOK()) {
				// Return generic ok status instead of problem multi-status with
				// no children
				return Status.OK_STATUS;
			}
			return result;
		}
		return Status.OK_STATUS;
	}

	private String getNonMultiStatusMessage(IStatus st) {
		if (st != null && st.isMultiStatus()) {
			StringBuilder buf = new StringBuilder();
			IStatus[] children = st.getChildren();
			for (IStatus iStatus : children) {
				if (iStatus.isMultiStatus()) {
					String msg = getNonMultiStatusMessage(iStatus);
					if (msg != null) {
						buf.append(msg).append('\n');
					}
				}
				if (!iStatus.isOK()) {
					buf.append(iStatus.getMessage()).append('\n');
				}
			}
			return buf.toString();
		}
		return st == null ? "" : st.getMessage();
	}

	private void initialize() {
		extra.clear();
		q7target = new Q7Target();
		if (this.target != null && this.target.getTargetLocations() != null) {
			ITargetLocation[] containers = this.target.getTargetLocations();
			for (ITargetLocation iUBundleContainer : containers) {
				if (iUBundleContainer instanceof ProfileBundleContainer) {
					getQ7Target().setInstall(iUBundleContainer);
				}
				extra.add(iUBundleContainer);
			}
		}
	}

	public void setTargetName(String name) {
		if (target != null) {
			target.setName(name);
		}
	}

	public String getName() {
		if (target != null) {
			return target.getName();
		}
		return "";
	}

	public void save() throws CoreException {
		if (!getStatus().isOK())
			throw new CoreException(getStatus());
		// Remove previous target platforms with same name.
		TargetPlatformManager.deleteTargetPlatform(target.getName());
		try {
			ITargetPlatformService service = PDEHelper.getTargetService();
			service.saveTargetDefinition(target);
		} catch (CoreException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
		}
	}

	public String getTargetPlatformProfilePath() {
		ProfileBundleContainer container = (ProfileBundleContainer) getInstanceContainer();
		if (container == null) {
			return "";
		}
		try {
			return container.getLocation(true).toString();
		} catch (CoreException e) {
			throw new RuntimeException(e);
		}
	}

	public void delete() {
		try {
			if (target != null && target.getHandle() != null) {
				PDEHelper.getTargetService().deleteTarget(target.getHandle());
			}
		} catch (CoreException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
		}
	}

	public ITargetDefinition getTarget() {
		return target;
	}

	public void update() {
		List<ITargetLocation> newContainers = new ArrayList<ITargetLocation>();
		newContainers.addAll(Arrays.asList(target.getTargetLocations()));

		if (extra != null) {
			newContainers.addAll(extra);
		}
		target.setTargetLocations(newContainers
				.toArray(new ITargetLocation[newContainers.size()]));
		models = null;
		registry = null;
	}

	private IPluginModelBase[] getTargetModels() {
		calcModels();
		return models;
	}

	@Override
	public IPluginModelBase getWeavingHook() {
		calcModels();
		return weavingHook;
	}

	private void calcModels() {
		if (models == null) {
			List<IPluginModelBase> bundles = sumBundles();
			weavingHook = filterHooks(bundles);
			models = bundles.toArray(new IPluginModelBase[0]);
		}
	}

	private List<IPluginModelBase> sumBundles() {
		TargetBundle[] bundles = getTarget().getAllBundles();
		if (bundles == null) {
			return new ArrayList<IPluginModelBase>();
		}
		List<URL> urls = new ArrayList<URL>();
		for (TargetBundle bundle : bundles) {
			try {
				urls.add(new URL("file://"
						+ bundle.getBundleInfo().getLocation().getPath()));
			} catch (MalformedURLException e) {
				Q7ExtLaunchingPlugin.getDefault().log(e);
			}
		}

		PDEState state = new PDEState(urls.toArray(new URL[urls
				.size()]), true, true, new NullProgressMonitor());
		final List<IPluginModelBase> targetModels = new ArrayList<IPluginModelBase>(Arrays.asList(state
				.getTargetModels()));

		if (DEBUG_BUNDLES) {
			final List<String> targetModelsLocations = new ArrayList<String>();
			for (final IPluginModelBase model : targetModels) {
				targetModelsLocations.add(model.getInstallLocation());
			}
			debug("Bundles: " + targetModelsLocations);
		}

		return targetModels;
	}

	private IPluginModelBase filterHooks(List<IPluginModelBase> models) {
		List<IPluginModelBase> hooks = new ArrayList<IPluginModelBase>();
		for (IPluginModelBase model : models) {
			String name = model.getBundleDescription().getSymbolicName();
			if (Objects.equal(name, AJConstants.HOOK)) {
				hooks.add(model);
			}
		}
		switch (hooks.size()) {
		case 0:
			// no weaving hook
			return null;
		case 1:
			// one weaving hook, nothing to filter
			return hooks.get(0);
		default:
			// find a hook with the latest version, remove other hooks
			IPluginModelBase maxHook = hooks.get(0);
			for (int i = 1; i < hooks.size(); i++) {
				IPluginModelBase hook = hooks.get(i);
				if (hook.getBundleDescription().getVersion()
						.compareTo(maxHook.getBundleDescription().getVersion()) > 0) {
					maxHook = hook;
				}
			}
			hooks.remove(maxHook);
			models.removeAll(hooks);
			return maxHook;
		}
	}

	private IPluginModelBase weavingHook;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private IStatus validateBundles(IProgressMonitor monitor) {
		LaunchValidationOperation validation = new LaunchValidationOperation(
				null) {
			@Override
			protected IPluginModelBase[] getModels() throws CoreException {
				return getTargetModels();
			}

			@Override
			protected IExecutionEnvironment[] getMatchingEnvironments()
					throws CoreException {
				IExecutionEnvironmentsManager manager = JavaRuntime
						.getExecutionEnvironmentsManager();
				IExecutionEnvironment[] envs = manager
						.getExecutionEnvironments();
				return envs;
			}
		};
		try {
			StringBuilder b = new StringBuilder();
			validation.run(monitor);
			Map input = validation.getInput();
			Set<Map.Entry> entrySet = input.entrySet();
			for (Map.Entry e : entrySet) {
				Object value = e.getKey();
				if (value instanceof ResolverError) {
					b.append(value.toString()).append("\n");
				}
			}
			if (b.length() > 0) {
				return new Status(IStatus.ERROR, PLUGIN_ID, "Bundle validation failed: " + b.toString());
			}
		} catch (CoreException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
			return status = e.getStatus();
		} catch (OperationCanceledException e) {
			return status = Status.CANCEL_STATUS;
		}
		return status = Status.OK_STATUS;
	}

	public String[] getProducts() {
		if (!isValid()) {
			return new String[0];
		}
		PDEExtensionRegistry reg = getRegistry();
		Set<String> result = new TreeSet<String>();
		IExtension[] extensions = reg.findExtensions("org.eclipse.core.runtime.products", false); //$NON-NLS-1$
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i]
					.getConfigurationElements();
			if (elements.length != 1)
				continue;
			if (!"product".equals(elements[0].getName())) //$NON-NLS-1$
				continue;
			String id = extensions[i].getUniqueIdentifier();
			if (id != null && id.trim().length() > 0)
				result.add(id);
		}
		return result.toArray(new String[result.size()]);
	}

	public String[] getApplications() {
		if (!isValid()) {
			return new String[0];
		}
		PDEExtensionRegistry reg = getRegistry();

		Set<String> result = new TreeSet<String>();
		IExtension[] extensions = reg.findExtensions("org.eclipse.core.runtime.applications", false); //$NON-NLS-1$
		for (int i = 0; i < extensions.length; i++) {
			String id = extensions[i].getUniqueIdentifier();
			IConfigurationElement[] elements = extensions[i]
					.getConfigurationElements();
			if (elements.length != 1)
				continue;
			String visiblity = elements[0].getAttribute("visible"); //$NON-NLS-1$
			boolean visible = visiblity == null ? true
					: Boolean.valueOf(visiblity).booleanValue();
			if (id != null && visible) {
				result.add(id);
			}
		}
		// result.add(IDE_APPLICATION); //$NON-NLS-1$
		return result.toArray(new String[result.size()]);
	}

	private PDEExtensionRegistry getRegistry() {
		if (registry == null) {
			registry = new PDEExtensionRegistry(getTargetModels());
		}
		return registry;
	}

	public IStatus resolve(IProgressMonitor monitor) {
		ITargetDefinition target = getTarget();
		if (target != null) {
			SubMonitor m = SubMonitor.convert(monitor, "Resolving " + getName(), 2);
			try {
				status = target.resolve(m.newChild(1, SubMonitor.SUPPRESS_NONE));
				if (!status.isOK())
					return status;
				status = validateBundles(m.newChild(1, SubMonitor.SUPPRESS_NONE));
				if (!status.isOK())
					return status;
				return status = getBundleStatus();
			} finally {
				m.done();
			}
		}
		return status = Status.CANCEL_STATUS;
	}

	AutInstall getAutInstall() {
		final Q7Target target = getQ7Target();
		if (target == null) {
			return null;
		}
		return target.getInstall();
	}

	public OriginalOrderProperties getConfigIniProperties() {
		return getAutInstall().getConfig();
	}

	protected String getEclipseProductFileProperty(String name) {
		Properties props = getEclipseProductFileProperties();
		return props == null ? null : props.getProperty(name);
	}

	public Properties getEclipseProductFileProperties() {
		File iniFile = new File(getTargetPlatformProfilePath(), ".eclipseproduct"); //$NON-NLS-1$
		if (!iniFile.exists())
			return null;
		Properties pini = new Properties();
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(iniFile);
			pini.load(fis);
			fis.close();
			return pini;
		} catch (IOException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
		} finally {
			try {
				if (fis != null)
					fis.close();
			} catch (IOException e) {
				Q7ExtLaunchingPlugin.getDefault().log(e);
			}
		}
		return null;
	}

	public String getDefaultApplication() {
		String app = getConfigIniProperty(APPLICATION_PROPERTY);
		debug("Application from config.ini: " + app);

		HashSet<String> apps = new HashSet<String>(
				Arrays.asList(getApplications()));
		debug("Valid applications: " + apps);

		return isValidId(app, apps) ? app
				: (isValidId(IDE_APPLICATION, apps) ? IDE_APPLICATION : null);
	}

	public String getBundlesList() {
		String bundles = getConfigIniProperty(OSGI_BUNDLES);
		return bundles == null ? org.eclipse.pde.internal.core.TargetPlatformHelper
				.getDefaultBundleList()
				: org.eclipse.pde.internal.core.TargetPlatformHelper
						.stripPathInformation(bundles);
	}

	protected String getConfigIniProperty(String name) {
		Properties config = getConfigIniProperties();
		if (config == null) {
			return null;
		}
		return config.getProperty(name);
	}

	protected boolean isValidId(String id, Set<String> available) {
		return id == null ? false : available.contains(id);
	}

	public String getDefaultProduct() {
		Set<String> values = new HashSet<String>(Arrays.asList(getProducts()));
		debug("Valid products: " + values);

		String product = null;
		String productProperty = getConfigIniProperty(PRODUCT_PROPERTY);
		if (isValidId(productProperty, values)) {
			product = productProperty;
		}
		debug(PRODUCT_PROPERTY + " from config.ini: " + productProperty);

		// Try to load .eclipseproduct file
		productProperty = getEclipseProductFileProperty(ID_PROPERTY);
		if (isValidId(productProperty, values)) {
			product = productProperty;
		}
		debug(ID_PROPERTY + " from config.ini: " + productProperty);

		// Try to load from application ini file
		List<File> iniFiles = getAppIniFiles();
		for (File file : iniFiles) {
			productProperty = readProductFromIniFile(file);
			if (isValidId(productProperty, values)) {
				product = productProperty;
			}
			debug("Product from " + file + ": " + productProperty);
		}

		return product;
	}

	public ITargetLocation[] getBundleContainers() {
		if (target == null) {
			return new ITargetLocation[0];
		}
		ITargetLocation[] bundleContainers = target.getTargetLocations();
		if (bundleContainers == null) {
			return new ITargetLocation[0];
		}
		return bundleContainers;
	}

	// Repository for all update site injections
	@SuppressWarnings("unused")
	private IFileArtifactRepository repository;

	public IStatus applyInjection(InjectionConfiguration configuration,
			IProgressMonitor monitor) {
		// remove the "host" from bundles, it is handled in a separate, special
		// way
		Iterables.removeAll(extra, Arrays.asList(getInstanceContainer()));

		EList<Entry> entries = configuration.getEntries();
		monitor.beginTask("Apply injection plugins", 20 + entries.size() * 20);
		for (Entry entry : entries) {
			SubProgressMonitor mon = new SubProgressMonitor(monitor, 20);
			if (monitor.isCanceled()) {
				return Status.CANCEL_STATUS;
			}
			IStatus result = new Status(IStatus.ERROR, PLUGIN_ID, "Unknown injection type: "
					+ entry.getClass().getName());
			if (entry instanceof UpdateSite) {
				result = processUpdateSite(mon, (UpdateSite) entry);
			} else if (entry instanceof Directory) {
				result = processDirectory((Directory) entry);
			}
			if (result.matches(IStatus.ERROR | IStatus.CANCEL)) {
				return result;
			}
		}
		update();
		IStatus resolveStatus = resolve(monitor);
		if (!resolveStatus.isOK()) {
			return resolveStatus;
		}
		if (getWeavingHook() == null) {
			return status = createError("No org.eclipse.weaving hook plugin");
		}
		try {
			save();
		} catch (CoreException e) {
			return e.getStatus();
		}
		return Status.OK_STATUS;
	}

	private IStatus processDirectory(Directory entry) {
		String path = entry.getPath();
		MultiStatus rv = new MultiStatus(PLUGIN_ID, 0, "Processing " + path, null);
		if (path.startsWith("platform:///")) {
			// if path is platform uri, lets resolve it to file
			try {
				URL resolve = FileLocator.resolve(URI.create(path).toURL());
				path = resolve.getPath();
			} catch (MalformedURLException e) {
				rv.add(new Status(IStatus.WARNING, PLUGIN_ID, e.getMessage(), e));
			} catch (IOException e) {
				rv.add(new Status(IStatus.WARNING, PLUGIN_ID, e.getMessage(), e));
			}
		}
		ITargetLocation container = PDEHelper.getTargetService()
				.newDirectoryLocation(path);
		extra.add(container);
		return Status.OK_STATUS;
	}

	private static final IStatus createError(String message) {
		return createError(message, null);
	}

	private static final IStatus createError(String message, Throwable error) {
		if (message == null && error != null) {
			message = error.getMessage();
		}
		return new Status(IStatus.ERROR, PLUGIN_ID, message, error);
	}

	private IStatus processUpdateSite(IProgressMonitor monitor, UpdateSite site) {

		try {
			URI uri = URI.create(
					Platform.getOS().equals(Platform.OS_WIN32) ? site.getUri().replace('\\', '/') : site.getUri());
			IMetadataRepository repository = PDEHelper.safeLoadRepository(uri,
					monitor);
			IArtifactRepository artifactRepository = PDEHelper
					.safeLoadArtifactRepository(uri, monitor);
			if (repository == null || artifactRepository == null) {
				if (monitor.isCanceled()) {
					return Status.CANCEL_STATUS;
				}
				return createError("Failed to load update site:" + uri);
			}

			List<IInstallableUnit> unitsToInstall = new ArrayList<IInstallableUnit>();

			// Query for all entries and then choose required.
			IQuery<IInstallableUnit> finalQuery = P2Utils.createQuery(site);

			IQueryResult<IInstallableUnit> result = repository.query(finalQuery,
					monitor);
			Set<IInstallableUnit> availableUnits = result.toSet();

			if (site.isAllUnits()) {
				unitsToInstall.addAll(availableUnits);
			} else {
				P2Utils.expandFeatures(monitor, repository, availableUnits);

				Set<String> unitIDs = P2Utils.mapUnitsToId(availableUnits);
				Set<String> missingUnits = new HashSet<String>(site.getUnits());
				missingUnits.removeAll(unitIDs);
				if (!missingUnits.isEmpty()) { // Some units are not available
					return createError("Few units are not available:"
							+ Arrays.toString(missingUnits.toArray()));
				}
				unitsToInstall.addAll(availableUnits);
			}
			if (unitsToInstall.size() > 0) {
				IInstallableUnit[] unitsAsArray = unitsToInstall
						.toArray(new IInstallableUnit[unitsToInstall.size()]);
				URI[] uriArray = new URI[] { uri };

				ITargetLocation container = PDEHelper.getTargetService()
						.newIULocation(unitsAsArray, uriArray,
								IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS);

				extra.add(container);
			}

			// Lets mirror all required artifacts into bundle pool, since we don't
			// really trust P2.

			IFileArtifactRepository filesRepository = P2TargetUtils
					.getBundlePool();

			List<IInstallableUnit> toInstall = new ArrayList<IInstallableUnit>();
			toInstall.addAll(unitsToInstall);
			P2Utils.installUnits(monitor, artifactRepository, filesRepository,
					toInstall, 10, null, false, P2Utils.getProvisioningAgent());
			MultiStatus rv = new MultiStatus(PLUGIN_ID, 0, "Failed to install next units from repository: "
					+ repository.getName(), null);
			if (toInstall.size() > 0) {
				// Not all plugins are installed.
				for (IInstallableUnit u : toInstall) {
					rv.add(createError(u.getId()));
				}
				return rv;
			}
		} catch (CoreException e) {
			return e.getStatus();
		}

		return Status.OK_STATUS;
	}

	public Map<String, String> getIniEnvironment() {
		List<File> iniFiles = getAppIniFiles();
		Map<String, String> result = new HashMap<String, String>();
		for (File file : iniFiles) {
			Map<String, String> envs = readEnvironmentFromIniFile(file);
			if (envs != null) {
				result.putAll(envs);
			}
		}
		return result;
	}

	public String getIniVMArgs() {
		List<File> iniFiles = getAppIniFiles();
		for (File file : iniFiles) {
			String vmArgs = readVMArgsFromIniFile(file);
			if (vmArgs != null) {
				return vmArgs;
			}
		}
		return null;
	}

	private List<File> getAppIniFiles() {
		List<File> iniFiles = new ArrayList<File>();
		if (getInstanceContainer() == null) {
			return iniFiles;
		}
		File installDirectory = new File(getTargetPlatformProfilePath());

		if (!installDirectory.exists()) {
			return iniFiles;
		}

		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			File[] listFiles = installDirectory.listFiles();
			for (File file : listFiles) {
				if (file.getName().contains(".app")) {
					installDirectory = new File(file, "/Contents/MacOS");
					break;
				}
			}
		}

		File eclipseIniFile = new File(installDirectory, "eclipse.ini"); //$NON-NLS-1$
		if (eclipseIniFile.exists()) {
			iniFiles.add(eclipseIniFile);
			return iniFiles;
		}
		File[] list = installDirectory.listFiles();
		if (list != null) {
			for (File file : list) {
				if (file.getName().endsWith(".ini")) {
					iniFiles.add(file);
				}
			}
		}
		return iniFiles;
	}

	private String readProductFromIniFile(File eclipseIniFile) {
		BufferedReader in = null;
		if (eclipseIniFile.exists()) {
			try {
				in = new BufferedReader(new FileReader(eclipseIniFile));
				String str;
				while ((str = in.readLine()) != null) {
					if (str.trim().equals("-product")) { //$NON-NLS-1$
						String product = in.readLine();
						if (product != null) {
							return product.trim();
						}
					}
				}
			} catch (IOException e) {
				Q7ExtLaunchingPlugin.getDefault().log(e);
			} finally {
				if (in != null)
					try {
						in.close();
					} catch (IOException e) {
						Q7ExtLaunchingPlugin.getDefault().log(e);
					}
			}
		}
		return null;
	}

	private String readLauncherLibraryFromIniFile(File eclipseIniFile) {
		BufferedReader in = null;
		try {
			if (eclipseIniFile.exists()) {
				in = new BufferedReader(new FileReader(eclipseIniFile));
				String str;
				while ((str = in.readLine()) != null) {
					if (str.trim().equals("--launcher.library")) { //$NON-NLS-1$
						String result = in.readLine();
						if (result != null) {
							return result.trim();
						}
					}
				}
			}
		} catch (IOException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
		} finally {
			FileUtil.safeClose(in);
		}
		return null;
	}

	private static final String GTK_VERSION = "--launcher.GTK_version";
	private static final String VMARGS = "-vmargs";
	private static final String VM = "-vm";

	private List<String> parseIniFile(File eclipseIni) {
		if (eclipseIni == null || !eclipseIni.exists()) {
			return emptyList();
		}

		List<String> result = new ArrayList<String>();
		try {
			for (String line : Files.readLines(eclipseIni, UTF_8)) {
				line = line.trim();
				if (line.length() > 0 && line.charAt(0) != '#') {
					result.add(line);
				}
			}
		} catch (IOException e) {
			Q7ExtLaunchingPlugin.getDefault().log(e);
		}
		return result;
	}

	private String getVmArg(File eclipseIniFile) {
		List<String> lines = parseIniFile(eclipseIniFile);
		int vmIndex = lines.indexOf("-vm") + 1;
		return vmIndex == 0 || vmIndex == lines.size() ? null
				: lines.get(vmIndex);
	}

	public String getVmFromIniFile() {
		for (File file : getAppIniFiles()) {
			String result = getVmArg(file);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	private Map<String, String> readEnvironmentFromIniFile(File eclipseIniFile) {
		if (!eclipseIniFile.exists()) {
			return null;
		}

		List<String> lines = parseIniFile(eclipseIniFile);
		Map<String, String> envs = new HashMap<String, String>();

		// mirror GTK_VERSION parameter processing
		// from org.eclipse.equinox.executable.feature / library / eclipse.c
		// see more:
		// https://git.eclipse.org/r/plugins/gitiles/equinox/rt.equinox.framework/+/master/features/org.eclipse.equinox.executable.feature/library/eclipse.c
		int gtkVersionIdx = lines.indexOf(GTK_VERSION);
		if (gtkVersionIdx != -1 && Platform.getOS().equals(Platform.OS_LINUX)) {
			String gtkVersion = lines.get(gtkVersionIdx + 1);
			if ("2".equals(gtkVersion)) {
				envs.put("SWT_GTK3", "0");
			} else {
				envs.put("SWT_GTK3", "1");
			}
		}
		return envs;
	}

	private String readVMArgsFromIniFile(File eclipseIniFile) {
		if (!eclipseIniFile.exists()) {
			return null;
		}

		List<String> lines = parseIniFile(eclipseIniFile);
		int vmargsIndex = lines.indexOf(VMARGS);
		if (vmargsIndex == -1) {
			return null;
		}
		lines = lines.subList(vmargsIndex + 1, lines.size());
		int vmIndex = lines.indexOf(VM);
		if (vmIndex != -1) {
			lines.subList(vmIndex, Math.min(vmIndex + 2, lines.size())).clear();
		}

		if (lines.isEmpty()) {
			return null;
		}

		removeUnsupportedVMArgs(lines);

		return Q7LaunchDelegateUtils.joinCommandArgs(lines);
	}

	private static final String VMARG_ADD_MODULES = "--add-modules";
	private static final String VMARG_PERMIT_ILLEGAL_ACCESS = "--permit-illegal-access";

	private void removeUnsupportedVMArgs(List<String> lines) {
		String[] javaVersions = getJavaVersions();

		// remove args was added into .ini file to support java 9
		// see more: https://bugs.eclipse.org/bugs/show_bug.cgi?id=493761
		if ((getMajorVersion(javaVersions) == 1 && getMinorVersion(javaVersions) < 9)
				|| getMajorVersion(javaVersions) < 9) {
			Iterator<String> iterator = lines.iterator();
			while (iterator.hasNext()) {
				String line = iterator.next();
				if (line.startsWith(VMARG_ADD_MODULES)
						|| line.startsWith(VMARG_PERMIT_ILLEGAL_ACCESS)) {
					iterator.remove();
				}
			}
		}
	}

	private static String[] getJavaVersions() {
		String javaVersion = System.getProperty("java.version");
		return javaVersion.split("\\.|-"); // '.' and '-' are separators
	}

	private static int getMajorVersion(String[] versions) {
		if (versions.length < 1) {
			return 0;
		}
		try {
			return Integer.valueOf(versions[0]);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	private static int getMinorVersion(String[] versions) {
		if (versions.length < 2) {
			return 0;
		}
		try {
			return Integer.valueOf(versions[1]);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	public String getTemplateConfigLocation() {
		File iniFile = new File(getTargetPlatformProfilePath(), "configuration/config.ini"); //$NON-NLS-1$
		if (!iniFile.exists())
			return null;
		return iniFile.getAbsolutePath();
	}

	public OSArchitecture detectArchitecture(
			boolean preferCurrentVmArchitecture, StringBuilder detectMsg) {

		// http://stackoverflow.com/a/808314
		final boolean isCurrentVm64 = System.getProperty("os.arch", "not null")
				.contains("64");

		boolean has32 = false;
		boolean has64 = false;

		String launcher64 = null;
		String launcher32 = null;

		List<File> iniFiles = getAppIniFiles();
		IPath targetPlatformProfilePath = new Path(
				getTargetPlatformProfilePath());
		Set<String> availableLaunchers = new HashSet<String>();
		String os = Platform.getOS();
		for (File file : iniFiles) {
			String launcherLibrary = readLauncherLibraryFromIniFile(file);
			if (launcherLibrary != null && launcherLibrary.contains(os)) {
				String configPath = new Path(file.getAbsolutePath())
						.removeFirstSegments(
								targetPlatformProfilePath.segmentCount())
						.setDevice(null).toOSString();
				if (launcherLibrary.contains("x86_64")) {
					has64 = true;
					launcher64 = "launcher library\n\t\"" + launcherLibrary
							+ "\" specified in config file: " + configPath;
				} else if (launcherLibrary.contains("x86")
						|| launcherLibrary.contains("cocoa.macosx")) {
					has32 = true;
					launcher32 = "launcher library\n\t\"" + launcherLibrary
							+ "\" specified in config file: " + configPath;
				}
			}
		}
		if (!has32 && !has64) {
			TargetBundle[] bundles = target.getAllBundles();
			for (TargetBundle b : bundles) {
				BundleInfo info = b.getBundleInfo();
				String name = info.getSymbolicName();
				if (name != null && name.startsWith("org.eclipse.equinox.launcher")) {
					URI location = info.getLocation();
					if (location == null || location.getPath() == null) {
						continue;
					}
					String pathString = new Path(info.getLocation().getPath())
							.removeFirstSegments(targetPlatformProfilePath.segmentCount()).toOSString();
					if (name.contains("x86_64")) {
						if (name.contains(os)) {
							has64 = true;
							launcher64 = "Equinox launcher\n\t- " + pathString;
						} else {
							availableLaunchers.add("\t- " + pathString);
						}
					} else if (name.contains("x86")
							|| name.contains("cocoa.macosx")) {
						if (name.contains(os)) {
							has32 = true;
							launcher32 = "Equinox launcher\n\t- " + pathString;
						} else {
							availableLaunchers.add("\t- " + pathString);
						}
					}
				}
			}
		}

		if (has32 && !has64) {
			if (detectMsg != null) {
				detectMsg.append("32bit arch is selected because AUT uses "
						+ launcher32);
			}
			return OSArchitecture.x86;
		} else if (!has32 && has64) {
			if (detectMsg != null) {
				detectMsg.append("64bit arch is selected because AUT uses "
						+ launcher64);
			}
			return OSArchitecture.x86_64;
		} else if (preferCurrentVmArchitecture && has32 && has64) {
			OSArchitecture result = isCurrentVm64 ? OSArchitecture.x86_64
					: OSArchitecture.x86;
			if (detectMsg != null && result.equals(OSArchitecture.x86)) {
				detectMsg
						.append("32bit arch is selected because\n- JVM is 32bit\n- AUT contains both launcher plugins\n\t-"
								+ launcher32 + "\n\t-" + launcher64);
			}
			if (detectMsg != null && result.equals(OSArchitecture.x86_64)) {
				detectMsg
						.append("64bit arch is selected because\n- JVM is 64bit\n- AUT contains both launcher plugins\n\t-"
								+ launcher32 + "\n\t-" + launcher64);
			}
			return result;
		} else {
			if (detectMsg != null) {
				detectMsg
						.append("Cannot find appropriate Equinox launcher library.\n");
				if (availableLaunchers.size() > 0) {
					detectMsg.append("Available launchers:\n");
					for (String s : availableLaunchers) {
						detectMsg.append(s).append("\n");
					}
				}
			}
			return OSArchitecture.Unknown;
		}
	}

	private Map<String, String> getRunlevelsFromSimpleConfigurator() {
		Map<String, String> result = new HashMap<String, String>();
		if (getTargetPlatformProfilePath() == null) {
			return result;
		}
		File infoFile = new File(getTargetPlatformProfilePath(),
				SC_BUNDLES_PATH);
		if (!infoFile.exists()) {
			return result;
		}
		InputStream input = null;
		try {
			input = new FileInputStream(infoFile);
			for (org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo bi : (List<org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo>) SimpleConfiguratorUtils
					.readConfiguration(input, infoFile.toURI())) {
				String name = bi.getSymbolicName();
				if (name != null) {
					result.put(name, String.format("%d:%b", bi.getStartLevel(), bi.isMarkedAsStarted()));
				}
			}
		} catch (Throwable e) {
			FileUtil.safeClose(input);
		}
		return result;
	}

	public Map<String, String> getRunlevelsMap() {
		Map<String, String> result = new HashMap<String, String>();
		String osgiBundles = getConfigIniProperty(OSGI_BUNDLES);
		if (osgiBundles == null) {
			return result;
		}

		if (osgiBundles.contains(SIMPLECONFIGURATOR)) {
			return getRunlevelsFromSimpleConfigurator();
		}

		// AUT uses bundles specified in osgiBundlesProperty
		StringTokenizer tokenizer = new StringTokenizer(osgiBundles, ","); //$NON-NLS-1$
		while (tokenizer.hasMoreTokens()) {
			String token = tokenizer.nextToken();
			int index = token.indexOf('@');
			String id = index != -1 ? token.substring(0, index) : token;
			String tk = token.substring(index + 1);
			if (tk.indexOf(":") == -1) {
				tk = tk + ":default";
			}
			result.put(id, tk);
		}
		return result;
	}

	public String getRuntimeVersion() {
		if (target != null && target.isResolved()) {
			String version = "";
			Version runtimeBundle = getBundleVersion("org.eclipse.rcptt.tesla.swt");
			if (runtimeBundle != null) {
				version = runtimeBundle.toString();
				if (runtimeBundle.getQualifier().equals("qualifier")) {
					// This is for development
					version = version + System.currentTimeMillis();
				}
			}
			return version;
		}
		return "unknown";
	}

	private Version getBundleVersion(String name) {
		if (target != null && target.isResolved()) {
			ITargetLocation[] containers = target.getTargetLocations();
			for (ITargetLocation iBundleContainer : containers) {
				TargetBundle[] bundles = iBundleContainer.getBundles();
				if (bundles != null) {
					for (TargetBundle iResolvedBundle : bundles) {
						BundleInfo info = iResolvedBundle.getBundleInfo();
						if (Objects.equal(info.getSymbolicName(), name)) {
							return new Version(info.getVersion());
						}
					}
				}
				if (iBundleContainer instanceof IUBundleContainer) {
					IUBundleContainer ct = (IUBundleContainer) iBundleContainer;
					try {
						Field ids = IUBundleContainer.class
								.getDeclaredField("fIds");
						Field versions = IUBundleContainer.class
								.getDeclaredField("fVersions");
						ids.setAccessible(true);
						versions.setAccessible(true);
						String[] idsValue = (String[]) ids.get(ct);
						org.eclipse.equinox.p2.metadata.Version[] versionsValue = (org.eclipse.equinox.p2.metadata.Version[]) versions
								.get(ct);
						for (int i = 0; i < idsValue.length; i++) {
							String n = idsValue[i];
							if (n != null && n.equals(name)) {
								return new Version(versionsValue[i].toString());
							}
						}
					} catch (Throwable e) {
						Q7ExtLaunchingPlugin.status(
								"Failed to check runtime version", e);
					}
				}
			}
		}
		return null;
	}

	public String getEquinoxStartupPath(String packageName) {
		IPluginModelBase[] targetModels = getTargetModels();
		for (IPluginModelBase plugin : targetModels) {
			if (plugin.getPluginBase().getId().equals(packageName)) {
				String location = plugin.getInstallLocation();
				if (new File(location).isFile()) {
					return location;
				}
			}
		}
		return null;
	}

	ProfileBundleContainer getInstanceContainer() {
		final AutInstall install = getAutInstall();
		if (install == null) {
			return null;
		}
		return install.container;
	}

	public void setBundleContainers(ITargetLocation[] containers) {
		target.setTargetLocations(containers);
		initialize();
	}

	@Override
	public String toString() {
		return (getName() == null ? "No name" : getName()) + " " + getTargetPlatformProfilePath();
	}

	@Override
	public Map<String, org.eclipse.equinox.p2.metadata.Version> getVersions() throws CoreException {
		if (!getStatus().isOK())
			throw new CoreException(getStatus());
		return AUTInformation.getInformationMap(target);
	}

	private static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$
	private static final String PROP_SHARED_CONFIG_AREA = "osgi.sharedConfiguration.area"; //$NON-NLS-1$
	private static final String PROP_CONFIG_CASCADED = "osgi.configuration.cascaded"; //$NON-NLS-1$

	// for variable substitution
	public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$
	public static final char VARIABLE_DELIM_CHAR = '$';

	private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_MARKER = ".eclipseproduct"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_ID = "id"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_VERSION = "version"; //$NON-NLS-1$

	private static final String PROP_OS = "osgi.os"; //$NON-NLS-1$
	private static final String PROP_WS = "osgi.ws"; //$NON-NLS-1$
	private static final String PROP_ARCH = "osgi.arch"; //$NON-NLS-1$

	private static final String CONFIG_DIR = "configuration/"; //$NON-NLS-1$
	private static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$
	private static final String NONE = "@none"; //$NON-NLS-1$
	private static final String NO_DEFAULT = "@noDefault"; //$NON-NLS-1$
	private static final String USER_HOME = "@user.home"; //$NON-NLS-1$
	private static final String USER_DIR = "@user.dir"; //$NON-NLS-1$
	private static final String PROP_USER_HOME = "user.home"; //$NON-NLS-1$
	private static final String PROP_USER_DIR = "user.dir"; //$NON-NLS-1$
	private static final String FILE_SCHEME = "file:"; //$NON-NLS-1$

	public static OriginalOrderProperties processConfiguration(AutInstall autInstall) {
		URL baseConfigurationLocation = null;
		OriginalOrderProperties baseConfiguration = null;
		String location = null;
		if (baseConfigurationLocation == null)
			try {
				baseConfigurationLocation = new URL(autInstall.getInstallLocationURL(), CONFIG_DIR);
			} catch (MalformedURLException e) {
				// leave baseConfigurationLocation null
			}
		baseConfiguration = loadConfiguration(baseConfigurationLocation);
		if (baseConfiguration != null) {
			// if the base sets the install area then use that value if the property. We know the
			// property is not already set.
			location = baseConfiguration.getProperty(PROP_CONFIG_AREA);
		}

		// Now we know where the base configuration is supposed to be. Go ahead and load
		// it and merge into the System properties. Then, if cascaded, read the parent configuration.
		// Note that in a cascaded situation, the user configuration may be ignored if the parent
		// configuration has changed since the user configuration has been written.
		// Note that the parent may or may not be the same parent as we read above since the
		// base can define its parent. The first parent we read was either defined by the user
		// on the command line or was the one in the install dir.
		// if the config or parent we are about to read is the same as the base config we read above,
		// just reuse the base
		OriginalOrderProperties configuration = baseConfiguration;
		final URL configUrl = getConfigurationLocation(location, autInstall.getInstallLocation());

		if (configuration == null || !configUrl.equals(baseConfigurationLocation))
			configuration = loadConfiguration(configUrl);

		if (configuration == null) {
			Q7ExtLaunchingPlugin.getDefault().info("File config.ini from folder \"" + configUrl + "\" was not read");
			return baseConfiguration;
		}

		String configurationArea = configUrl.getFile();
		int index = configurationArea.lastIndexOf("/");
		if (index == configurationArea.length() - 1) {
			configurationArea = configurationArea.substring(0, index);
			index = configurationArea.lastIndexOf("/");
		}
		autInstall.userArea = configurationArea.substring(0, index + 1);

		if ("false".equalsIgnoreCase(configuration.getProperty(PROP_CONFIG_CASCADED))) { //$NON-NLS-1$
			configuration.remove(PROP_SHARED_CONFIG_AREA);
			return configuration;
		} else {

			URL sharedConfigURL = buildLocation(configuration.getProperty(PROP_SHARED_CONFIG_AREA), null, "", //$NON-NLS-1$
					autInstall.getInstallLocation().getAbsolutePath());
			if (sharedConfigURL == null)
				try {
					// there is no shared config value so compute one
					sharedConfigURL = new URL(autInstall.getInstallLocationURL(), CONFIG_DIR);
				} catch (MalformedURLException e) {
					// leave sharedConfigurationLocation null
				}
			// if the parent location is different from the config location, read it too.
			if (sharedConfigURL != null) {
				if (sharedConfigURL.equals(configUrl)) {
					// After all we are not in a shared configuration setup.
					// - remove the property to show that we do not have a parent
					// - merge configuration with the system properties
					return configuration;
				} else {
					// if the parent we are about to read is the same as the base config we read above,
					// just reuse the base
					OriginalOrderProperties sharedConfiguration = baseConfiguration;
					if (!sharedConfigURL.equals(baseConfigurationLocation)) {
						sharedConfiguration = loadConfiguration(sharedConfigURL);
					}
					configuration.remove(PROP_SHARED_CONFIG_AREA);

					return mergeProperties(sharedConfiguration, configuration);
				}
			}
		}
		return null;
	}

	private static OriginalOrderProperties loadConfiguration(URL url) {
		OriginalOrderProperties result = null;
		try {
			url = new URL(url, CONFIG_FILE);
		} catch (MalformedURLException e) {
			return result;
		}
		try {
			if (url != null)
				result = OriginalOrderProperties.load(url);
		} catch (IOException e) {
		}
		return substituteVars(result);
	}

	private static OriginalOrderProperties substituteVars(OriginalOrderProperties result) {
		if (result == null) {
			// nothing todo.
			return null;
		}
		for (Enumeration<?> eKeys = result.keys(); eKeys.hasMoreElements();) {
			Object key = eKeys.nextElement();
			if (key instanceof String) {
				String value = result.getProperty((String) key);
				if (value != null)
					result.put(key, substituteVars(value));
			}
		}
		return result;
	}

	private static String substituteVars(String path) {
		StringBuffer buf = new StringBuffer(path.length());
		StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true);
		boolean varStarted = false; // indicates we are processing a var subtitute
		String var = null; // the current var key
		while (st.hasMoreElements()) {
			String tok = st.nextToken();
			if (VARIABLE_DELIM_STRING.equals(tok)) {
				if (!varStarted) {
					varStarted = true; // we found the start of a var
					var = ""; //$NON-NLS-1$
				} else {
					// we have found the end of a var
					String prop = null;
					// get the value of the var from system properties
					if (var != null && var.length() > 0)
						prop = System.getProperty(var);
					if (prop == null) {
						try {
							// try using the System.getenv method if it exists (bug 126921)
							Method getenv = System.class.getMethod("getenv", new Class[] { String.class }); //$NON-NLS-1$
							prop = (String) getenv.invoke(null, new Object[] { var });
						} catch (Throwable t) {
							// do nothing;
							// on 1.4 VMs this throws an error
							// on J2ME this method does not exist
						}
					}
					if (prop != null) {
						// found a value; use it
						buf.append(prop);
					} else {
						// could not find a value append the var; keep delemiters
						buf.append(VARIABLE_DELIM_CHAR);
						buf.append(var == null ? "" : var); //$NON-NLS-1$
						buf.append(VARIABLE_DELIM_CHAR);
					}
					varStarted = false;
					var = null;
				}
			} else {
				if (!varStarted)
					buf.append(tok); // the token is not part of a var
				else
					var = tok; // the token is the var key; save the key to process when we find the end token
			}
		}
		if (var != null)
			// found a case of $var at the end of the path with no trailing $; just append it as is.
			buf.append(VARIABLE_DELIM_CHAR).append(var);
		return buf.toString();
	}

	private static URL getConfigurationLocation(String configurationArea, File installLocation) {
		URL configurationLocation = buildLocation(configurationArea, null, "", installLocation.getAbsolutePath()); //$NON-NLS-1$
		if (configurationLocation == null)
			configurationLocation = buildURL(computeDefaultConfigurationLocation(installLocation), true,
					installLocation.getAbsolutePath());

		return configurationLocation;
	}

	private static URL buildLocation(String location, URL defaultLocation, String userDefaultAppendage,
			String installArea) {
		URL result = null;
		// if the instance location is not set, predict where the workspace will be and
		// put the instance area inside the workspace meta area.
		if (location == null)
			result = defaultLocation;
		else if (location.equalsIgnoreCase(NONE))
			return null;
		else if (location.equalsIgnoreCase(NO_DEFAULT))
			result = buildURL(location, true, installArea);
		else {
			if (location.startsWith(USER_HOME)) {
				String base = substituteVar(location, USER_HOME, PROP_USER_HOME);
				location = new File(base, userDefaultAppendage).getAbsolutePath();
			} else if (location.startsWith(USER_DIR)) {
				String base = substituteVar(location, USER_DIR, PROP_USER_DIR);
				location = new File(base, userDefaultAppendage).getAbsolutePath();
			}
			result = buildURL(location, true, installArea);
		}
		return result;
	}

	private static String substituteVar(String source, String var, String prop) {
		String value = System.getProperty(prop, ""); //$NON-NLS-1$
		return value + source.substring(var.length());
	}

	public static URL buildURL(String spec, boolean trailingSlash, String installArea) {
		if (spec == null)
			return null;
		if (File.separatorChar == '\\')
			spec = spec.trim();
		boolean isFile = spec.startsWith(FILE_SCHEME);
		try {
			if (isFile) {
				File toAdjust = new File(spec.substring(5));
				toAdjust = resolveFile(toAdjust, installArea);
				if (toAdjust.isDirectory())
					return adjustTrailingSlash(toAdjust.toURI().toURL(), trailingSlash);
				return toAdjust.toURI().toURL();
			}
			return new URL(spec);
		} catch (MalformedURLException e) {
			// if we failed and it is a file spec, there is nothing more we can do
			// otherwise, try to make the spec into a file URL.
			if (isFile)
				return null;
			try {
				File toAdjust = new File(spec);
				if (toAdjust.isDirectory())
					return adjustTrailingSlash(toAdjust.toURI().toURL(), trailingSlash);
				return toAdjust.toURI().toURL();
			} catch (MalformedURLException e1) {
				return null;
			}
		}
	}

	private static File resolveFile(File toAdjust, String installArea) {
		if (!toAdjust.isAbsolute()) {
			if (installArea != null) {
				if (installArea.startsWith(FILE_SCHEME))
					toAdjust = new File(installArea.substring(5), toAdjust.getPath());
				else if (new File(installArea).exists())
					toAdjust = new File(installArea, toAdjust.getPath());
			}
		}
		return toAdjust;
	}

	private static URL adjustTrailingSlash(URL url, boolean trailingSlash) throws MalformedURLException {
		String file = url.getFile();
		if (trailingSlash == (file.endsWith("/"))) //$NON-NLS-1$
			return url;
		file = trailingSlash ? file + "/" : file.substring(0, file.length() - 1); //$NON-NLS-1$
		return new URL(url.getProtocol(), url.getHost(), file);
	}

	private static String computeDefaultConfigurationLocation(File installLocation) {
		// 1) We store the config state relative to the 'eclipse' directory if possible
		// 2) If this directory is read-only
		// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
		// is unique for each local user, and <application-id> is the one
		// defined in .eclipseproduct marker file. If .eclipseproduct does not
		// exist, use "eclipse" as the application-id.

		String configurationLocation = null;
		if (canWrite(installLocation))
			configurationLocation = installLocation.getAbsolutePath();
		else
			// We can't write in the eclipse install dir so try for some place in the user's home dir
			configurationLocation = computeDefaultUserAreaLocation(installLocation);

		return configurationLocation + File.separator + CONFIG_DIR;
	}

	private static boolean canWrite(File installDir) {
		if (installDir.canWrite() == false)
			return false;

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

		File fileTest = null;
		try {
			// we use the .dll suffix to properly test on Vista virtual directories
			// on Vista you are not allowed to write executable files on virtual directories like "Program Files"
			fileTest = File.createTempFile("writableArea", ".dll", installDir); //$NON-NLS-1$ //$NON-NLS-2$
		} catch (IOException e) {
			return false;
		} finally {
			if (fileTest != null)
				fileTest.delete();
		}
		return true;
	}

	private static String computeDefaultUserAreaLocation(File installDir) {
		// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
		// is unique for each local user, and <application-id> is the one
		// defined in .eclipseproduct marker file. If .eclipseproduct does not
		// exist, use "eclipse" as the application-id.
		String installDirHash = getInstallDirHash(installDir);

		String appName = "." + ECLIPSE; //$NON-NLS-1$
		File eclipseProduct = new File(installDir, PRODUCT_SITE_MARKER);
		if (eclipseProduct.exists()) {
			Properties props = new Properties();
			try {
				props.load(new FileInputStream(eclipseProduct));
				String appId = props.getProperty(PRODUCT_SITE_ID);
				if (appId == null || appId.trim().length() == 0)
					appId = ECLIPSE;
				String appVersion = props.getProperty(PRODUCT_SITE_VERSION);
				if (appVersion == null || appVersion.trim().length() == 0)
					appVersion = ""; //$NON-NLS-1$
				appName += File.separator + appId + "_" + appVersion + "_" + installDirHash; //$NON-NLS-1$ //$NON-NLS-2$
			} catch (IOException e) {
				// Do nothing if we get an exception. We will default to a standard location
				// in the user's home dir.
				// add the hash to help prevent collisions
				appName += File.separator + installDirHash;
			}
		} else {
			// add the hash to help prevent collisions
			appName += File.separator + installDirHash;
		}
		appName += '_' + OS_WS_ARCHToString();
		String userHome = System.getProperty(PROP_USER_HOME);
		return new File(userHome, appName).getAbsolutePath(); // $NON-NLS-1$
	}

	private static String OS_WS_ARCHToString() {
		return getOS() + '_' + getWS() + '_' + getArch();
	}

	private static String getWS() {
		String osgiWs = System.getProperty(PROP_WS);
		if (osgiWs != null)
			return osgiWs;
		String osName = getOS();
		if (osName.equals(Constants.OS_WIN32))
			return Constants.WS_WIN32;
		if (osName.equals(Constants.OS_LINUX))
			return Constants.WS_GTK;
		if (osName.equals(Constants.OS_MACOSX))
			return Constants.WS_COCOA;
		if (osName.equals(Constants.OS_HPUX))
			return Constants.WS_GTK;
		if (osName.equals(Constants.OS_AIX))
			return Constants.WS_GTK;
		if (osName.equals(Constants.OS_SOLARIS))
			return Constants.WS_GTK;
		if (osName.equals(Constants.OS_QNX))
			return Constants.WS_PHOTON;
		return Constants.WS_UNKNOWN;
	}

	private static String getOS() {
		String osgiOs = System.getProperty(PROP_OS);
		if (osgiOs != null)
			return osgiOs;
		String osName = System.getProperties().getProperty("os.name"); //$NON-NLS-1$
		if (osName.regionMatches(true, 0, Constants.OS_WIN32, 0, 3))
			return Constants.OS_WIN32;
		// EXCEPTION: All mappings of SunOS convert to Solaris
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_SUNOS))
			return Constants.OS_SOLARIS;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_LINUX))
			return Constants.OS_LINUX;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_QNX))
			return Constants.OS_QNX;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_AIX))
			return Constants.OS_AIX;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_HPUX))
			return Constants.OS_HPUX;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_OS400))
			return Constants.OS_OS400;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_OS390))
			return Constants.OS_OS390;
		if (osName.equalsIgnoreCase(Constants.INTERNAL_OS_ZOS))
			return Constants.OS_ZOS;
		// os.name on Mac OS can be either Mac OS or Mac OS X
		if (osName.regionMatches(true, 0, Constants.INTERNAL_OS_MACOSX, 0, Constants.INTERNAL_OS_MACOSX.length()))
			return Constants.OS_MACOSX;
		return Constants.OS_UNKNOWN;
	}

	private static String getArch() {
		String osgiArch = System.getProperty(PROP_ARCH);
		if (osgiArch != null)
			return osgiArch;
		String name = System.getProperties().getProperty("os.arch");//$NON-NLS-1$
		// Map i386 architecture to x86
		if (name.equalsIgnoreCase(Constants.INTERNAL_ARCH_I386))
			return Constants.ARCH_X86;
		// Map amd64 architecture to x86_64
		else if (name.equalsIgnoreCase(Constants.INTERNAL_AMD64))
			return Constants.ARCH_X86_64;

		return name;
	}

	private static String getInstallDirHash(File installDir) {
		// compute an install dir hash to prevent configuration area collisions with other eclipse installs
		int hashCode;
		try {
			hashCode = installDir.getCanonicalPath().hashCode();
		} catch (IOException ioe) {
			// fall back to absolute path
			hashCode = installDir.getAbsolutePath().hashCode();
		}
		if (hashCode < 0)
			hashCode = -(hashCode);
		String installDirHash = String.valueOf(hashCode);
		return installDirHash;
	}

	private static OriginalOrderProperties mergeProperties(OriginalOrderProperties source,
			OriginalOrderProperties userConfiguration) {
		if (userConfiguration != null) {
			source.setBeginAdd(true);
			source.putAll(userConfiguration);
		}
		return source;
	}

	private static void debug(String message) {
		if (DEBUG) {
			Q7ExtLaunchingPlugin.getDefault().info(message);
		}
	}
}
