/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     Julian Chen - fix for bug #92572, jclRM
 *     Benjamin Cabe <benjamin.cabe@anyware-tech.com> - fix for bug 265532
 *     Christoph Läubrich - remove InternalPlatform.getDefault().log (bug 55083)
 *******************************************************************************/
package org.eclipse.core.internal.runtime;

import java.io.File;
import java.net.URL;
import java.util.*;
import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences;
import org.eclipse.core.internal.preferences.exchange.IProductPreferencesService;
import org.eclipse.core.internal.preferences.legacy.InitLegacyPreferences;
import org.eclipse.core.internal.preferences.legacy.ProductPreferencesService;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.equinox.internal.app.*;
import org.eclipse.equinox.internal.app.Activator;
import org.eclipse.equinox.log.*;
import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
import org.osgi.framework.*;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.wiring.*;
import org.osgi.resource.Namespace;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Bootstrap class for the platform. It is responsible for setting up the
 * platform class loader and passing control to the actual application class
 */
public final class InternalPlatform {

	private static final String[] ARCH_LIST = { Platform.ARCH_X86, Platform.ARCH_X86_64 };

	// debug support:  set in loadOptions()
	public static boolean DEBUG = false;
	public static boolean DEBUG_PLUGIN_PREFERENCES = false;

	private boolean splashEnded = false;
	private boolean initialized;
	private static final String KEYRING = "-keyring"; //$NON-NLS-1$
	private String keyringFile;

	//XXX This is not synchronized
	private Map<Bundle,Log> logs = new HashMap<>(5);

	private static final String[] OS_LIST = { Platform.OS_LINUX, Platform.OS_MACOSX, Platform.OS_WIN32 };
	private String password = ""; //$NON-NLS-1$
	private static final String PASSWORD = "-password"; //$NON-NLS-1$

	public static final String PROP_APPLICATION = "eclipse.application"; //$NON-NLS-1$
	public static final String PROP_ARCH = "osgi.arch"; //$NON-NLS-1$
	public static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$
	public static final String PROP_CONSOLE_LOG = "eclipse.consoleLog"; //$NON-NLS-1$
	public static final String PROP_DEBUG = "osgi.debug"; //$NON-NLS-1$
	public static final String PROP_DEV = "osgi.dev"; //$NON-NLS-1$

	// OSGI system properties.  Copied from EclipseStarter
	public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
	public static final String PROP_NL = "osgi.nl"; //$NON-NLS-1$
	public static final String PROP_OS = "osgi.os"; //$NON-NLS-1$

	// Eclipse System Properties
	public static final String PROP_PRODUCT = "eclipse.product"; //$NON-NLS-1$
	public static final String PROP_WS = "osgi.ws"; //$NON-NLS-1$
	public static final String PROP_ACTIVATE_PLUGINS = "eclipse.activateRuntimePlugins"; //$NON-NLS-1$

	private static final InternalPlatform singleton = new InternalPlatform();

	private static final String[] WS_LIST = { Platform.WS_COCOA, Platform.WS_GTK, Platform.WS_WIN32, Platform.WS_WPF };
	private Path cachedInstanceLocation; // Cache the path of the instance location
	private ServiceTracker<Location,Location> configurationLocation = null;
	private BundleContext context;
	private FrameworkWiring fwkWiring;

	private Map<IBundleGroupProvider,ServiceRegistration<IBundleGroupProvider>> groupProviders = new HashMap<>(3);
	private ServiceTracker<Location,Location> installLocation = null;
	private ServiceTracker<Location,Location> instanceLocation = null;
	private ServiceTracker<Location,Location> userLocation = null;

	private Plugin runtimeInstance; // Keep track of the plugin object for runtime in case the backward compatibility is run.

	private ServiceRegistration<ILegacyPreferences> legacyPreferencesService = null;
	private ServiceRegistration<IProductPreferencesService> customPreferencesService = null;

	private ServiceTracker<EnvironmentInfo,EnvironmentInfo> environmentTracker = null;
	private ServiceTracker<FrameworkLog,FrameworkLog> logTracker = null;
	private ServiceTracker<PlatformAdmin, PlatformAdmin> platformTracker = null;
	private ServiceTracker<DebugOptions,DebugOptions> debugTracker = null;
	private ServiceTracker<IContentTypeManager,IContentTypeManager> contentTracker = null;
	private ServiceTracker<IPreferencesService,IPreferencesService> preferencesTracker = null;
	private ServiceTracker<IBundleGroupProvider,IBundleGroupProvider> groupProviderTracker = null;
	private ServiceTracker<ExtendedLogReaderService,ExtendedLogReaderService> logReaderTracker = null;
	private ServiceTracker<ExtendedLogService,ExtendedLogService> extendedLogTracker = null;

	private IProduct product;

	public static InternalPlatform getDefault() {
		return singleton;
	}

	/**
	 * Private constructor to block instance creation.
	 */
	private InternalPlatform() {
		super();
	}

	/**
	 * @see Platform#addLogListener(ILogListener)
	 */
	public void addLogListener(ILogListener listener) {
		assertInitialized();
		RuntimeLog.addLogListener(listener);
	}

	private void assertInitialized() {
		//avoid the Policy.bind if assertion is true
		if (!initialized)
			Assert.isTrue(false, Messages.meta_appNotInit);
	}

	/**
	 * @see Platform#endSplash()
	 */
	public void endSplash() {
		synchronized (this) {
			if (splashEnded)
				return; // do not do this more than once
			splashEnded = true;
		}
		IApplicationContext applicationContext = getApplicationContext();
		if (applicationContext != null)
			applicationContext.applicationRunning();
	}

	/**
	 * @see Platform#getAdapterManager()
	 */
	public IAdapterManager getAdapterManager() {
		assertInitialized();
		return AdapterManager.getDefault();
	}

	/**
	 * XXX Use the Environment info service. Need to see how to set the value of the app args.
	 */
	public String[] getApplicationArgs() {
		return CommandLineArgs.getApplicationArgs();
	}

	public boolean getBooleanOption(String option, boolean defaultValue) {
		String value = getOption(option);
		if (value == null)
			return defaultValue;
		return value.equalsIgnoreCase("true"); //$NON-NLS-1$
	}

	public BundleContext getBundleContext() {
		return context;
	}

	/**
	 * Returns the bundle id of the bundle that contains the provided object, or
	 * <code>null</code> if the bundle could not be determined.
	 */
	public String getBundleId(Object object) {
		if (object == null)
			return null;
		Bundle source = FrameworkUtil.getBundle(object.getClass());
		if (source != null && source.getSymbolicName() != null)
			return source.getSymbolicName();

		return null;
	}

	public IBundleGroupProvider[] getBundleGroupProviders() {
		return groupProviderTracker.getServices(new IBundleGroupProvider[0]);
	}

	public void registerBundleGroupProvider(IBundleGroupProvider provider) {
		// get the bundle context and register the provider as a service
		ServiceRegistration<IBundleGroupProvider> registration = getBundleContext().registerService(IBundleGroupProvider.class, provider, null);
		// store the service registration (map provider -> registration)
		synchronized (groupProviders) {
			groupProviders.put(provider, registration);
		}
	}

	public void unregisterBundleGroupProvider(IBundleGroupProvider provider) {
		// get the service reference (map provider -> reference)
		ServiceRegistration<IBundleGroupProvider> registration;
		synchronized (groupProviders) {
			registration = groupProviders.remove(provider);
		}
		if (registration == null)
			return;
		// unregister the provider
		registration.unregister();
	}

	public Bundle getBundle(String symbolicName) {
		Bundle[] bundles = getBundles(symbolicName, null);
		return bundles != null && bundles.length > 0 ? bundles[0] : null;
	}

	public Bundle[] getBundles(String symbolicName, String versionRange) {
		if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) {
			symbolicName = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getSymbolicName();
		}
		Map<String, String> directives = Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE,
				getRequirementFilter(symbolicName, versionRange));
		Collection<BundleCapability> matchingBundleCapabilities = fwkWiring.findProviders(ModuleContainer
				.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, directives, Collections.emptyMap()));

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

		Bundle[] results = matchingBundleCapabilities.stream().map(c -> c.getRevision().getBundle())
				// Remove all the bundles that are installed or uninstalled
				.filter(bundle -> (bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0)
				.sorted((b1, b2) -> b2.getVersion().compareTo(b1.getVersion())) // highest version first
				.toArray(Bundle[]::new);

		return results.length > 0 ? results : null;
	}

	private String getRequirementFilter(String symbolicName, String versionRange) {
		VersionRange range = versionRange == null ? null : new VersionRange(versionRange);
		StringBuilder filter = new StringBuilder();
		if (range != null) {
			filter.append("(&"); //$NON-NLS-1$
		}
		filter.append('(').append(IdentityNamespace.IDENTITY_NAMESPACE).append('=').append(symbolicName).append(')');

		if (range != null) {
			filter.append(range.toFilterString(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE)).append(')');
		}
		return filter.toString();
	}

	public String[] getCommandLineArgs() {
		return CommandLineArgs.getAllArgs();
	}

	public Location getConfigurationLocation() {
		assertInitialized();
		return configurationLocation.getService();
	}

	/**
	 * Lazy initialize ContentTypeManager - it can only be used after the registry is up and running
	 */
	public IContentTypeManager getContentTypeManager() {
		return contentTracker == null ? null : (IContentTypeManager) contentTracker.getService();
	}

	public EnvironmentInfo getEnvironmentInfoService() {
		return environmentTracker == null ? null : (EnvironmentInfo) environmentTracker.getService();
	}

	public FrameworkLog getFrameworkLog() {
		return logTracker == null ? null : (FrameworkLog) logTracker.getService();
	}

	public Bundle[] getFragments(Bundle bundle) {
		BundleWiring wiring = bundle.adapt(BundleWiring.class);
		if (wiring == null) {
			return null;
		}
		List<BundleWire> hostWires = wiring.getProvidedWires(HostNamespace.HOST_NAMESPACE);
		if (hostWires == null) {
			// we don't hold locks while checking the graph, just return if no longer valid
			return null;
		}
		Bundle[] result = hostWires.stream().map(wire -> wire.getRequirer().getBundle()).filter(Objects::nonNull)
				.toArray(Bundle[]::new);
		return result.length > 0 ? result : null;
	}

	public Bundle[] getHosts(Bundle bundle) {
		BundleWiring wiring = bundle.adapt(BundleWiring.class);
		if (wiring == null) {
			return null;
		}
		List<BundleWire> hostWires = wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE);
		if (hostWires == null) {
			// we don't hold locks while checking the graph, just return if no longer valid
			return null;
		}
		Bundle[] result = hostWires.stream().map(wire -> wire.getProvider().getBundle()).filter(Objects::nonNull)
				.toArray(Bundle[]::new);
		return result.length > 0 ? result : null;
	}

	public Location getInstallLocation() {
		assertInitialized();
		return installLocation.getService();
	}

	public URL getInstallURL() {
		Location location = getInstallLocation();
		// it is pretty much impossible for the install location to be null.  If it is, the
		// system is in a bad way so throw and exception and get the heck outta here.
		if (location == null)
			throw new IllegalStateException("The installation location must not be null"); //$NON-NLS-1$
		return location.getURL();
	}

	public Location getInstanceLocation() {
		assertInitialized();
		return instanceLocation.getService();
	}

	/**
	 * @see Platform#getLocation()
	 */
	public IPath getLocation() throws IllegalStateException {
		if (cachedInstanceLocation == null) {
			Location location = getInstanceLocation();
			if (location == null)
				return null;
			//	This makes the assumption that the instance location is a file: URL
			File file = new File(location.getURL().getFile());
			cachedInstanceLocation = new Path(file.toString());
		}
		return cachedInstanceLocation;
	}

	/**
	 * Returns a log for the given plugin. Creates a new one if needed.
	 * XXX change this into a LogMgr service that would keep track of the map. See if it can be a service factory.
	 * It would contain all the logging methods that are here.
	 * Relate to RuntimeLog if appropriate.
	 * The system log listener needs to be optional: turned on or off. What about a system property? :-)
	 */
	public ILog getLog(Bundle bundle) {
		Log result = logs.get(bundle);
		if (result != null)
			return result;
		ExtendedLogService logService = extendedLogTracker.getService();
		Logger logger = logService == null ? null : logService.getLogger(bundle, PlatformLogWriter.EQUINOX_LOGGER_NAME);
		result = new Log(bundle, logger);
		ExtendedLogReaderService logReader = logReaderTracker.getService();
		logReader.addLogListener(result, result);
		logs.put(bundle, result);
		return result;
	}

	public String getNL() {
		return getBundleContext().getProperty(PROP_NL);
	}

	/**
	 * Unicode locale extensions are defined using command line parameter -nlExtensions,
	 * or the system property "osgi.nl.extensions".
	 */
	public String getNLExtensions() {
		String nlExtensions = PlatformActivator.getContext().getProperty("osgi.nl.extensions"); //$NON-NLS-1$
		if (nlExtensions == null)
			return ""; //$NON-NLS-1$
		if (!nlExtensions.startsWith("@")) //$NON-NLS-1$
			nlExtensions = '@' + nlExtensions;
		return nlExtensions;
	}

	/**
	 * @see Platform
	 */
	public String getOption(String option) {
		DebugOptions options = getDebugOptions();
		if (options != null)
			return options.getOption(option);
		return null;
	}

	public String getOS() {
		return getBundleContext().getProperty(PROP_OS);
	}

	public String getOSArch() {
		return getBundleContext().getProperty(PROP_ARCH);
	}

	public PlatformAdmin getPlatformAdmin() {
		return platformTracker == null ? null : platformTracker.getService();
	}


	public IPreferencesService getPreferencesService() {
		return preferencesTracker == null ? null : (IPreferencesService) preferencesTracker.getService();
	}

	/*
	 * XXX move this into the app model.
	 */
	public IProduct getProduct() {
		if (product != null)
			return product;
		EclipseAppContainer container = Activator.getContainer();
		IBranding branding = container == null ? null : container.getBranding();
		if (branding == null)
			return null;
		Object brandingProduct = branding.getProduct();
		if (!(brandingProduct instanceof IProduct))
			brandingProduct = new Product(branding);
		product = (IProduct) brandingProduct;
		return product;
	}

	public IExtensionRegistry getRegistry() {
		return RegistryFactory.getRegistry();
	}

	/**
	 * XXX deprecate and use NLS or BundleFinder.find()
	 */
	public ResourceBundle getResourceBundle(Bundle bundle) {
		return ResourceTranslator.getResourceBundle(bundle);
	}

	/**
	 * XXX deprecate and use NLS or BundleFinder.find()
	 */
	public String getResourceString(Bundle bundle, String value) {
		return ResourceTranslator.getResourceString(bundle, value);
	}

	/**
	 * XXX deprecate and use NLS or BundleFinder.find()
	 */
	public String getResourceString(Bundle bundle, String value, ResourceBundle resourceBundle) {
		return ResourceTranslator.getResourceString(bundle, value, resourceBundle);
	}

	/**
	 * This method is only used to register runtime once compatibility has been started.
	 */
	public Plugin getRuntimeInstance() {
		return runtimeInstance;
	}

	private IApplicationContext getApplicationContext() {
		Collection<ServiceReference<IApplicationContext>> references;
		try {
			references = context.getServiceReferences(IApplicationContext.class, "(eclipse.application.type=main.thread)"); //$NON-NLS-1$
		} catch (InvalidSyntaxException e) {
			return null;
		}
		if (references == null || references.isEmpty())
			return null;
		// assumes the application context is available as a service
		ServiceReference<IApplicationContext> firstRef = references.iterator().next();
		IApplicationContext result = context.getService(firstRef);
		if (result != null) {
			context.ungetService(firstRef);
			return result;
		}
		return null;
	}

	/**
	 * XXX Investigate the usage of a service factory
	 */
	public IPath getStateLocation(Bundle bundle) {
		return getStateLocation(bundle, true);
	}

	public IPath getStateLocation(Bundle bundle, boolean create) throws IllegalStateException {
		assertInitialized();
		IPath result = MetaDataKeeper.getMetaArea().getStateLocation(bundle);
		if (create)
			result.toFile().mkdirs();
		return result;
	}

	public long getStateTimeStamp() {
		PlatformAdmin admin = getPlatformAdmin();
		return admin == null ? -1 : admin.getState(false).getTimeStamp();
	}

	public Location getUserLocation() {
		assertInitialized();
		return userLocation.getService();
	}

	public String getWS() {
		return getBundleContext().getProperty(PROP_WS);
	}

	private void initializeAuthorizationHandler() {
		try {
			AuthorizationHandler.setKeyringFile(keyringFile);
			AuthorizationHandler.setPassword(password);
		} catch (NoClassDefFoundError e) {
			// The authorization fragment is not available. If someone tries to use that API, an error will be logged
		}
	}

	/*
	 * Finds and loads the options file
	 */
	void initializeDebugFlags() {
		// load runtime options
		DEBUG = getBooleanOption(Platform.PI_RUNTIME + "/debug", false); //$NON-NLS-1$
		if (DEBUG) {
			DEBUG_PLUGIN_PREFERENCES = getBooleanOption(Platform.PI_RUNTIME + "/preferences/plugin", false); //$NON-NLS-1$
		}
	}

	public boolean isFragment(Bundle bundle) {
		BundleRevisions bundleRevisions = bundle.adapt(BundleRevisions.class);
		List<BundleRevision> revisions = bundleRevisions.getRevisions();
		if (revisions.isEmpty()) {
			// bundle is uninstalled and not current users; just return false
			return false;
		}
		return (revisions.get(0).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
	}

	/*
	 *XXX do what you want to do. track osgi, track runtime, or whatever.
	 */
	public boolean isRunning() {
		try {
			return initialized && context != null && context.getBundle().getState() == Bundle.ACTIVE;
		} catch (IllegalStateException e) {
			return false;
		}
	}

	/**
	 * Returns a list of known system architectures.
	 *
	 * @return the list of system architectures known to the system
	 * XXX This is useless
	 */
	public String[] knownOSArchValues() {
		return ARCH_LIST;
	}

	/**
	 * Returns a list of known operating system names.
	 *
	 * @return the list of operating systems known to the system
	 * XXX This is useless
	 */
	public String[] knownOSValues() {
		return OS_LIST;
	}

	/**
	 * Returns a list of known windowing system names.
	 *
	 * @return the list of window systems known to the system
	 * XXX This is useless
	 */
	public String[] knownWSValues() {
		return WS_LIST;
	}

	private void processCommandLine(String[] args) {
		if (args == null || args.length == 0)
			return;

		for (int i = 0; i < args.length; i++) {
			// check for args with parameters
			if (i == args.length - 1 || args[i + 1].startsWith("-")) //$NON-NLS-1$
				continue;
			String arg = args[++i];

			// look for the keyring file
			if (args[i - 1].equalsIgnoreCase(KEYRING))
				keyringFile = arg;
			// look for the user password.
			if (args[i - 1].equalsIgnoreCase(PASSWORD))
				password = arg;
		}
	}

	/**
	 * @see Platform#removeLogListener(ILogListener)
	 */
	public void removeLogListener(ILogListener listener) {
		assertInitialized();
		RuntimeLog.removeLogListener(listener);
	}

	/**
	 * This method is only used to register runtime once compatibility has been started.
	 */
	public void setRuntimeInstance(Plugin runtime) {
		runtimeInstance = runtime;
	}

	/**
	 * Internal method for starting up the platform.  The platform is not started with any location
	 * and should not try to access the instance data area.
	 *
	 * Note: the content type manager must be initialized only after the registry has been created
	 */
	public void start(BundleContext runtimeContext) {
		this.context = runtimeContext;
		this.fwkWiring = runtimeContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class);
		openOSGiTrackers();
		splashEnded = false;
		processCommandLine(getEnvironmentInfoService().getNonFrameworkArgs());
		initializeDebugFlags();
		initialized = true;
		initializeAuthorizationHandler();
		startServices();
	}

	/**
	 * Shutdown runtime pieces in this order:
	 * Content[auto shutdown] -> Preferences[auto shutdown] -> Registry -> Jobs
	 * The "auto" shutdown takes place before this code is executed
	 */
	public void stop(BundleContext bundleContext) {
		assertInitialized();
		stopServices(); // should be done after preferences shutdown
		initialized = false;
		closeOSGITrackers();
		context = null;
	}

	private void openOSGiTrackers() {
		Filter filter = null;
		try {
			filter = context.createFilter(Location.INSTANCE_FILTER);
		} catch (InvalidSyntaxException e) {
			// ignore this.  It should never happen as we have tested the above format.
		}
		instanceLocation = new ServiceTracker<>(context, filter, null);
		instanceLocation.open();

		try {
			filter = context.createFilter(Location.USER_FILTER);
		} catch (InvalidSyntaxException e) {
			// ignore this.  It should never happen as we have tested the above format.
		}
		userLocation = new ServiceTracker<>(context, filter, null);
		userLocation.open();

		try {
			filter = context.createFilter(Location.CONFIGURATION_FILTER);
		} catch (InvalidSyntaxException e) {
			// ignore this.  It should never happen as we have tested the above format.
		}
		configurationLocation = new ServiceTracker<>(context, filter, null);
		configurationLocation.open();

		try {
			filter = context.createFilter(Location.INSTALL_FILTER);
		} catch (InvalidSyntaxException e) {
			// ignore this.  It should never happen as we have tested the above format.
		}
		installLocation = new ServiceTracker<>(context, filter, null);
		installLocation.open();

		if (context != null) {
			logTracker = new ServiceTracker<>(context, FrameworkLog.class, null);
			logTracker.open();
		}

		if (context != null) {
			platformTracker = new ServiceTracker<>(context, PlatformAdmin.class, null);
			platformTracker.open();
		}

		if (context != null) {
			contentTracker = new ServiceTracker<>(context, IContentTypeManager.class, null);
			contentTracker.open();
		}

		if (context != null) {
			preferencesTracker = new ServiceTracker<>(context, IPreferencesService.class, null);
			preferencesTracker.open();
		}

		try {
			filter = context.createFilter("(objectClass=" + IBundleGroupProvider.class.getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
		} catch (InvalidSyntaxException e) {
			// ignore this, it should never happen
		}
		groupProviderTracker = new ServiceTracker<>(context, filter, null);
		groupProviderTracker.open();

		logReaderTracker = new ServiceTracker<>(context, ExtendedLogReaderService.class, null);
		logReaderTracker.open();

		extendedLogTracker = new ServiceTracker<>(context, ExtendedLogService.class, null);
		extendedLogTracker.open();

		environmentTracker = new ServiceTracker<>(context, EnvironmentInfo.class, null);
		environmentTracker.open();

		debugTracker = new ServiceTracker<>(context, DebugOptions.class, null);
		debugTracker.open();
	}

	private void startServices() {
		// The check for getProduct() is relatively expensive (about 3% of the headless startup),
		// so we don't want to enforce it here.
		customPreferencesService = context.registerService(IProductPreferencesService.class, new ProductPreferencesService(), new Hashtable<>());

		legacyPreferencesService = context.registerService(ILegacyPreferences.class, new InitLegacyPreferences(), new Hashtable<>());
	}

	private void stopServices() {
		if (legacyPreferencesService != null) {
			legacyPreferencesService.unregister();
			legacyPreferencesService = null;
		}
		if (customPreferencesService != null) {
			customPreferencesService.unregister();
			customPreferencesService = null;
		}
	}

	private DebugOptions getDebugOptions() {
		return debugTracker == null ? null : debugTracker.getService();
	}

	private void closeOSGITrackers() {
		if (preferencesTracker != null) {
			preferencesTracker.close();
			preferencesTracker = null;
		}
		if (contentTracker != null) {
			contentTracker.close();
			contentTracker = null;
		}
		if (debugTracker != null) {
			debugTracker.close();
			debugTracker = null;
		}
		if (platformTracker != null) {
			platformTracker.close();
			platformTracker = null;
		}
		if (logTracker != null) {
			logTracker.close();
			logTracker = null;
		}
		if (groupProviderTracker != null) {
			groupProviderTracker.close();
			groupProviderTracker = null;
		}
		if (environmentTracker != null) {
			environmentTracker.close();
			environmentTracker = null;
		}
		if (logReaderTracker != null) {
			logReaderTracker.close();
			logReaderTracker = null;
		}
		if (extendedLogTracker != null) {
			extendedLogTracker.close();
			extendedLogTracker = null;
		}
		if (installLocation != null) {
			installLocation.close();
			installLocation = null;
		}
		if (userLocation != null) {
			userLocation.close();
			userLocation = null;
		}
		if (configurationLocation != null) {
			configurationLocation.close();
			configurationLocation = null;
		}
		if (instanceLocation != null) {
			instanceLocation.close();
			instanceLocation = null;
		}
	}

	/**
	 * Print a debug message to the console.
	 * Pre-pend the message with the current date and the name of the current thread.
	 */
	public static void message(String message) {
		StringBuilder buffer = new StringBuilder();
		buffer.append(new Date(System.currentTimeMillis()));
		buffer.append(" - ["); //$NON-NLS-1$
		buffer.append(Thread.currentThread().getName());
		buffer.append("] "); //$NON-NLS-1$
		buffer.append(message);
		System.out.println(buffer.toString());
	}

	public static void start(Bundle bundle) throws BundleException {
		int originalState = bundle.getState();
		if ((originalState & Bundle.ACTIVE) != 0)
			return; // bundle is already active
		try {
			// attempt to activate the bundle
			bundle.start(Bundle.START_TRANSIENT);
		} catch (BundleException e) {
			if ((originalState & Bundle.STARTING) != 0 && (bundle.getState() & Bundle.STARTING) != 0)
				// This can happen if the bundle was in the process of being activated on this thread, just return
				return;
			throw e;
		}
	}
}
