/*******************************************************************************
 * Copyright (c) 2003, 2021 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
 *******************************************************************************/

package org.eclipse.osgi.internal.framework;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.eventmgr.EventDispatcher;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl;
import org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl;
import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
import org.eclipse.osgi.internal.serviceregistry.ServiceUse;
import org.eclipse.osgi.internal.serviceregistry.ShrinkableCollection;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.bundle.FindHook;
import org.osgi.resource.Capability;

/**
 * Bundle's execution context.
 *
 * This object is given out to bundles and provides the
 * implementation to the BundleContext for a host bundle.
 * It is destroyed when a bundle is stopped.
 */

public class BundleContextImpl implements BundleContext, EventDispatcher<Object, Object, Object> {
	/** true if the bundle context is still valid */
	private volatile boolean valid;

	/** Bundle object this context is associated with. */
	// This slot is accessed directly by the Framework instead of using
	// the getBundle() method because the Framework needs access to the bundle
	// even when the context is invalid while the close method is being called.
	final EquinoxBundle bundle;

	/** Internal equinox container object. */
	final EquinoxContainer container;
	final Debug debug;

	/** Services that bundle is using. Key is ServiceRegistrationImpl,
	 Value is ServiceUse */
	/* @GuardedBy("contextLock") */
	private HashMap<ServiceRegistrationImpl<?>, ServiceUse<?>> servicesInUse;

	/** The current instantiation of the activator. */
	private BundleActivator activator;

	/** private object for locking */
	private final Object contextLock = new Object();

	/**
	 * Construct a BundleContext which wrappers the framework for a
	 * bundle
	 *
	 * @param bundle The bundle we are wrapping.
	 */
	public BundleContextImpl(EquinoxBundle bundle, EquinoxContainer container) {
		this.bundle = bundle;
		this.container = container;
		this.debug = container.getConfiguration().getDebug();
		valid = true;
		synchronized (contextLock) {
			servicesInUse = null;
		}
		activator = null;
	}

	/**
	 * Destroy the wrapper. This is called when the bundle is stopped.
	 *
	 */
	protected void close() {
		valid = false; /* invalidate context */

		final ServiceRegistry registry = container.getServiceRegistry();

		registry.removeAllServiceListeners(this);
		container.getEventPublisher().removeAllListeners(this);

		/* service's registered by the bundle, if any, are unregistered. */
		registry.unregisterServices(this);

		/* service's used by the bundle, if any, are released. */
		registry.releaseServicesInUse(this);

		synchronized (contextLock) {
			servicesInUse = null;
		}
	}

	/**
	 * Retrieve the value of the named environment property.
	 *
	 * @param key The name of the requested property.
	 * @return The value of the requested property, or <code>null</code> if
	 * the property is undefined.
	 */
	@Override
	public String getProperty(String key) {
		SecurityManager sm = System.getSecurityManager();

		if (sm != null) {
			sm.checkPropertyAccess(key);
		}

		return (container.getConfiguration().getProperty(key));
	}

	/**
	 * Retrieve the Bundle object for the context bundle.
	 *
	 * @return The context bundle's Bundle object.
	 */
	@Override
	public Bundle getBundle() {
		checkValid();

		return getBundleImpl();
	}

	public EquinoxBundle getBundleImpl() {
		return bundle;
	}

	@Override
	public Bundle installBundle(String location) throws BundleException {
		return installBundle(location, null);
	}

	@Override
	public Bundle installBundle(String location, InputStream in) throws BundleException {
		checkValid();

		Generation generation = container.getStorage().install(bundle.getModule(), location, in);
		return generation.getRevision().getBundle();
	}

	/**
	 * Retrieve the bundle that has the given unique identifier.
	 *
	 * @param id The identifier of the bundle to retrieve.
	 * @return A Bundle object, or <code>null</code>
	 * if the identifier doesn't match any installed bundle.
	 */
	@Override
	public Bundle getBundle(long id) {
		Module m = container.getStorage().getModuleContainer().getModule(id);
		if (m == null) {
			return null;
		}

		List<Bundle> bundles = new ArrayList<>(1);
		bundles.add(m.getBundle());
		notifyFindHooks(this, bundles);
		if (bundles.isEmpty()) {
			return null;
		}
		return m.getBundle();
	}

	@Override
	public Bundle getBundle(String location) {
		Module m = container.getStorage().getModuleContainer().getModule(location);
		return m == null ? null : m.getBundle();
	}

	/**
	 * Retrieve a list of all installed bundles.
	 * The list is valid at the time
	 * of the call to getBundles, but the framework is a very dynamic
	 * environment and bundles can be installed or uninstalled at anytime.
	 *
	 * @return An array of {@link Bundle} objects, one
	 * object per installed bundle.
	 */
	@Override
	public Bundle[] getBundles() {
		List<Module> modules = container.getStorage().getModuleContainer().getModules();
		List<Bundle> bundles = new ArrayList<>(modules.size());
		for (Module module : modules) {
			bundles.add(module.getBundle());
		}

		notifyFindHooks(this, bundles);
		return bundles.toArray(new Bundle[bundles.size()]);
	}

	private void notifyFindHooks(final BundleContextImpl context, List<Bundle> allBundles) {
		if (context.getBundleImpl().getBundleId() == 0) {
			// Make a copy for the purposes of calling the hooks;
			// The the removals from the hooks are ignored
			allBundles = new ArrayList<>(allBundles);
		}
		final Collection<Bundle> shrinkable = new ShrinkableCollection<>(allBundles);
		if (System.getSecurityManager() == null) {
			notifyFindHooksPriviledged(context, shrinkable);
		} else {
			AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
				notifyFindHooksPriviledged(context, shrinkable);
				return null;
			});
		}
	}

	void notifyFindHooksPriviledged(final BundleContextImpl context, final Collection<Bundle> allBundles) {
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		container.getServiceRegistry().notifyHooksPrivileged(FindHook.class, "find", (hook, hookRegistration) -> { //$NON-NLS-1$
			hook.find(context, allBundles);
		});
	}

	@Override
	public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException {
		checkValid();

		if (listener == null) {
			throw new IllegalArgumentException();
		}
		container.getServiceRegistry().addServiceListener(this, listener, filter);
	}

	/**
	 * Add a service listener.
	 *
	 * <p>This method is the same as calling
	 * {@link #addServiceListener(ServiceListener, String)}
	 * with filter set to <code>null</code>.
	 *
	 * @see #addServiceListener(ServiceListener, String)
	 */
	@Override
	public void addServiceListener(ServiceListener listener) {
		try {
			addServiceListener(listener, null);
		} catch (InvalidSyntaxException e) {
			if (debug.DEBUG_GENERAL) {
				Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
				Debug.printStackTrace(e);
			}
		}
	}

	/**
	 * Remove a service listener.
	 * The listener is removed from the context bundle's list of listeners.
	 * See {@link #getBundle() getBundle()}
	 * for a definition of context bundle.
	 *
	 * <p>If this method is called with a listener which is not registered,
	 * then this method does nothing.
	 *
	 * @param listener The service listener to remove.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 */
	@Override
	public void removeServiceListener(ServiceListener listener) {
		checkValid();

		if (listener == null) {
			throw new IllegalArgumentException();
		}
		container.getServiceRegistry().removeServiceListener(this, listener);
	}

	/**
	 * Add a bundle listener.
	 * {@link BundleListener}s are notified when a bundle has a lifecycle
	 * state change.
	 * The listener is added to the context bundle's list of listeners.
	 * See {@link #getBundle() getBundle()}
	 * for a definition of context bundle.
	 *
	 * @param listener The bundle listener to add.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 * @see BundleEvent
	 * @see BundleListener
	 */
	@Override
	public void addBundleListener(BundleListener listener) {
		checkValid();
		if (listener == null) {
			throw new IllegalArgumentException();
		}

		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("addBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		container.getEventPublisher().addBundleListener(listener, this);
	}

	/**
	 * Remove a bundle listener.
	 * The listener is removed from the context bundle's list of listeners.
	 * See {@link #getBundle() getBundle()}
	 * for a definition of context bundle.
	 *
	 * <p>If this method is called with a listener which is not registered,
	 * then this method does nothing.
	 *
	 * @param listener The bundle listener to remove.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 */
	@Override
	public void removeBundleListener(BundleListener listener) {
		checkValid();
		if (listener == null) {
			throw new IllegalArgumentException();
		}

		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("removeBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		container.getEventPublisher().removeBundleListener(listener, this);
	}

	/**
	 * Add a general framework listener.
	 * {@link FrameworkListener}s are notified of general framework events.
	 * The listener is added to the context bundle's list of listeners.
	 * See {@link #getBundle() getBundle()}
	 * for a definition of context bundle.
	 *
	 * @param listener The framework listener to add.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 * @see FrameworkEvent
	 * @see FrameworkListener
	 */
	@Override
	public void addFrameworkListener(FrameworkListener listener) {
		checkValid();
		if (listener == null) {
			throw new IllegalArgumentException();
		}

		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("addFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		container.getEventPublisher().addFrameworkListener(listener, this);
	}

	/**
	 * Remove a framework listener.
	 * The listener is removed from the context bundle's list of listeners.
	 * See {@link #getBundle() getBundle()}
	 * for a definition of context bundle.
	 *
	 * <p>If this method is called with a listener which is not registered,
	 * then this method does nothing.
	 *
	 * @param listener The framework listener to remove.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 */
	@Override
	public void removeFrameworkListener(FrameworkListener listener) {
		checkValid();
		if (listener == null) {
			throw new IllegalArgumentException();
		}

		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("removeFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		container.getEventPublisher().removeFrameworkListener(listener, this);
	}

	/**
	 * Register a service with multiple names.
	 * This method registers the given service object with the given properties
	 * under the given class names.
	 * A {@link ServiceRegistration} object is returned.
	 * The {@link ServiceRegistration} object is for the private use of the bundle
	 * registering the service and should not be shared with other bundles.
	 * The registering bundle is defined to be the context bundle.
	 * See {@link #getBundle()} for a definition of context bundle.
	 * Other bundles can locate the service by using either the
	 * {@link #getServiceReferences getServiceReferences} or
	 * {@link #getServiceReference getServiceReference} method.
	 *
	 * <p>A bundle can register a service object that implements the
	 * {@link ServiceFactory} interface to
	 * have more flexiblity in providing service objects to different
	 * bundles.
	 *
	 * <p>The following steps are followed to register a service:
	 * <ol>
	 * <li>If the service parameter is not a {@link ServiceFactory},
	 * an <code>IllegalArgumentException</code> is thrown if the
	 * service parameter is not an <code>instanceof</code>
	 * all the classes named.
	 * <li>The service is added to the framework's service registry
	 * and may now be used by other bundles.
	 * <li>A {@link ServiceEvent} of type {@link ServiceEvent#REGISTERED}
	 * is synchronously sent.
	 * <li>A {@link ServiceRegistration} object for this registration
	 * is returned.
	 * </ol>
	 *
	 * @param clazzes The class names under which the service can be located.
	 *                The class names in this array will be stored in the service's
	 *                properties under the key "objectClass".
	 * @param service The service object or a {@link ServiceFactory} object.
	 * @param properties The properties for this service.
	 *        The keys in the properties object must all be Strings.
	 *        Changes should not be made to this object after calling this method.
	 *        To update the service's properties call the
	 *        {@link ServiceRegistration#setProperties ServiceRegistration.setProperties}
	 *        method.
	 *        This parameter may be <code>null</code> if the service has no properties.
	 * @return A {@link ServiceRegistration} object for use by the bundle
	 *        registering the service to update the
	 *        service's properties or to unregister the service.
	 * @exception java.lang.IllegalArgumentException If one of the following is true:
	 * <ul>
	 * <li>The service parameter is null.
	 * <li>The service parameter is not a {@link ServiceFactory} and is not an
	 * <code>instanceof</code> all the named classes in the clazzes parameter.
	 * </ul>
	 * @exception java.lang.SecurityException If the caller does not have
	 * {@link ServicePermission} permission to "register" the service for
	 * all the named classes
	 * and the Java runtime environment supports permissions.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 * @see ServiceRegistration
	 * @see ServiceFactory
	 */
	@Override
	public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties) {
		checkValid();
		return container.getServiceRegistry().registerService(this, clazzes, service, properties);
	}

	/**
	 * Register a service with a single name.
	 * This method registers the given service object with the given properties
	 * under the given class name.
	 *
	 * <p>This method is otherwise identical to
	 * {@link #registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)}
	 * and is provided as a convenience when the service parameter will only be registered
	 * under a single class name.
	 *
	 * @see #registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
	 */
	@Override
	public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties) {
		String[] clazzes = new String[] {clazz};

		return registerService(clazzes, service, properties);
	}

	/**
	 * Returns a list of <tt>ServiceReference</tt> objects. This method returns a list of
	 * <tt>ServiceReference</tt> objects for services which implement and were registered under
	 * the specified class and match the specified filter criteria.
	 *
	 * <p>The list is valid at the time of the call to this method, however as the Framework is
	 * a very dynamic environment, services can be modified or unregistered at anytime.
	 *
	 * <p><tt>filter</tt> is used to select the registered service whose
	 * properties objects contain keys and values which satisfy the filter.
	 * See {@link Filter}for a description of the filter string syntax.
	 *
	 * <p>If <tt>filter</tt> is <tt>null</tt>, all registered services
	 * are considered to match the filter.
	 * <p>If <tt>filter</tt> cannot be parsed, an {@link InvalidSyntaxException} will
	 * be thrown with a human readable message where the filter became unparsable.
	 *
	 * <p>The following steps are required to select a service:
	 * <ol>
	 * <li>If the Java Runtime Environment supports permissions, the caller is checked for the
	 * <tt>ServicePermission</tt> to get the service with the specified class.
	 * If the caller does not have the correct permission, <tt>null</tt> is returned.
	 * <li>If the filter string is not <tt>null</tt>, the filter string is
	 * parsed and the set of registered services which satisfy the filter is
	 * produced.
	 * If the filter string is <tt>null</tt>, then all registered services
	 * are considered to satisfy the filter.
	 * <li>If <code>clazz</code> is not <tt>null</tt>, the set is further reduced to
	 * those services which are an <tt>instanceof</tt> and were registered under the specified class.
	 * The complete list of classes of which a service is an instance and which
	 * were specified when the service was registered is available from the
	 * service's {@link Constants#OBJECTCLASS}property.
	 * <li>An array of <tt>ServiceReference</tt> to the selected services is returned.
	 * </ol>
	 *
	 * @param clazz The class name with which the service was registered, or
	 * <tt>null</tt> for all services.
	 * @param filter The filter criteria.
	 * @return An array of <tt>ServiceReference</tt> objects, or
	 * <tt>null</tt> if no services are registered which satisfy the search.
	 * @exception InvalidSyntaxException If <tt>filter</tt> contains
	 * an invalid filter string which cannot be parsed.
	 */
	@Override
	public ServiceReference<?>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
		checkValid();
		return container.getServiceRegistry().getServiceReferences(this, clazz, filter, false);
	}

	@Override
	public ServiceReference<?>[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
		checkValid();
		return container.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
	}

	/**
	 * Get a service reference.
	 * Retrieves a {@link ServiceReference} for a service
	 * which implements the named class.
	 *
	 * <p>This reference is valid at the time
	 * of the call to this method, but since the framework is a very dynamic
	 * environment, services can be modified or unregistered at anytime.
	 *
	 * <p>This method is provided as a convenience for when the caller is
	 * interested in any service which implements a named class. This method is
	 * the same as calling {@link #getServiceReferences getServiceReferences}
	 * with a <code>null</code> filter string but only a single {@link ServiceReference}
	 * is returned.
	 *
	 * @param clazz The class name which the service must implement.
	 * @return A {@link ServiceReference} object, or <code>null</code>
	 * if no services are registered which implement the named class.
	 * @see #getServiceReferences
	 */
	@Override
	public ServiceReference<?> getServiceReference(String clazz) {
		checkValid();

		return container.getServiceRegistry().getServiceReference(this, clazz);
	}

	/**
	 * Get a service's service object.
	 * Retrieves the service object for a service.
	 * A bundle's use of a service is tracked by a
	 * use count. Each time a service's service object is returned by
	 * {@link #getService}, the context bundle's use count for the service
	 * is incremented by one. Each time the service is release by
	 * {@link #ungetService}, the context bundle's use count
	 * for the service is decremented by one.
	 * When a bundle's use count for a service
	 * drops to zero, the bundle should no longer use the service.
	 * See {@link #getBundle()} for a definition of context bundle.
	 *
	 * <p>This method will always return <code>null</code> when the
	 * service associated with this reference has been unregistered.
	 *
	 * <p>The following steps are followed to get the service object:
	 * <ol>
	 * <li>If the service has been unregistered,
	 * <code>null</code> is returned.
	 * <li>The context bundle's use count for this service is incremented by one.
	 * <li>If the context bundle's use count for the service is now one and
	 * the service was registered with a {@link ServiceFactory},
	 * the {@link ServiceFactory#getService ServiceFactory.getService} method
	 * is called to create a service object for the context bundle.
	 * This service object is cached by the framework.
	 * While the context bundle's use count for the service is greater than zero,
	 * subsequent calls to get the services's service object for the context bundle
	 * will return the cached service object.
	 * <br>If the service object returned by the {@link ServiceFactory}
	 * is not an <code>instanceof</code>
	 * all the classes named when the service was registered or
	 * the {@link ServiceFactory} throws an exception,
	 * <code>null</code> is returned and a
	 * {@link FrameworkEvent} of type {@link FrameworkEvent#ERROR} is broadcast.
	 * <li>The service object for the service is returned.
	 * </ol>
	 *
	 * @param reference A reference to the service whose service object is desired.
	 * @return A service object for the service associated with this
	 * reference, or <code>null</code> if the service is not registered.
	 * @exception java.lang.SecurityException If the caller does not have
	 * {@link ServicePermission} permission to "get" the service
	 * using at least one of the named classes the service was registered under
	 * and the Java runtime environment supports permissions.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 * @see #ungetService
	 * @see ServiceFactory
	 */
	@Override
	public <S> S getService(ServiceReference<S> reference) {
		checkValid();
		if (reference == null)
			throw new NullPointerException("A null service reference is not allowed."); //$NON-NLS-1$
		provisionServicesInUseMap();
		S service = container.getServiceRegistry().getService(this, (ServiceReferenceImpl<S>) reference);
		return service;
	}

	/**
	 * Unget a service's service object.
	 * Releases the service object for a service.
	 * If the context bundle's use count for the service is zero, this method
	 * returns <code>false</code>. Otherwise, the context bundle's use count for the
	 * service is decremented by one.
	 * See {@link #getBundle()} for a definition of context bundle.
	 *
	 * <p>The service's service object
	 * should no longer be used and all references to it should be destroyed
	 * when a bundle's use count for the service
	 * drops to zero.
	 *
	 * <p>The following steps are followed to unget the service object:
	 * <ol>
	 * <li>If the context bundle's use count for the service is zero or
	 * the service has been unregistered,
	 * <code>false</code> is returned.
	 * <li>The context bundle's use count for this service is decremented by one.
	 * <li>If the context bundle's use count for the service is now zero and
	 * the service was registered with a {@link ServiceFactory},
	 * the {@link ServiceFactory#ungetService ServiceFactory.ungetService} method
	 * is called to release the service object for the context bundle.
	 * <li><code>true</code> is returned.
	 * </ol>
	 *
	 * @param reference A reference to the service to be released.
	 * @return <code>false</code> if the context bundle's use count for the service
	 *         is zero or if the service has been unregistered,
	 *         otherwise <code>true</code>.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 * @see #getService
	 * @see ServiceFactory
	 */
	@Override
	public boolean ungetService(ServiceReference<?> reference) {
		checkValid();

		return container.getServiceRegistry().ungetService(this, (ServiceReferenceImpl<?>) reference);
	}

	/**
	 * Creates a <code>File</code> object for a file in the
	 * persistent storage area provided for the bundle by the framework.
	 * If the adaptor does not have file system support, this method will
	 * return <code>null</code>.
	 *
	 * <p>A <code>File</code> object for the base directory of the
	 * persistent storage area provided for the context bundle by the framework
	 * can be obtained by calling this method with the empty string ("")
	 * as the parameter.
	 * See {@link #getBundle()} for a definition of context bundle.
	 *
	 * <p>If the Java runtime environment supports permissions,
	 * the framework the will ensure that the bundle has
	 * <code>java.io.FilePermission</code> with actions
	 * "read","write","execute","delete" for all files (recursively) in the
	 * persistent storage area provided for the context bundle by the framework.
	 *
	 * @param filename A relative name to the file to be accessed.
	 * @return A <code>File</code> object that represents the requested file or
	 * <code>null</code> if the adaptor does not have file system support.
	 * @exception java.lang.IllegalStateException
	 * If the bundle context has stopped.
	 */
	@Override
	public File getDataFile(String filename) {
		checkValid();

		Generation generation = (Generation) bundle.getModule().getCurrentRevision().getRevisionInfo();
		return generation.getBundleInfo().getDataFile(filename);
	}

	/**
	 * Call bundle's BundleActivator.start()
	 * This method is called by Bundle.startWorker to start the bundle.
	 *
	 * @exception BundleException if
	 *            the bundle has a class that implements the BundleActivator interface,
	 *            but Framework couldn't instantiate it, or the BundleActivator.start()
	 *            method failed
	 */
	protected void start() throws BundleException {
		long start = 0;
		try {
			if (debug.DEBUG_BUNDLE_TIME) {
				start = System.currentTimeMillis();
			}
			activator = loadBundleActivator();
			if (debug.DEBUG_BUNDLE_TIME) {
				Debug.println((System.currentTimeMillis() - start) + " ms to load the activator of " + bundle); //$NON-NLS-1$
			}
		} catch (Exception e) {
			if (e instanceof RuntimeException) {
				throw (RuntimeException) e;
			}
			throw new BundleException(Msg.BundleContextImpl_LoadActivatorError + ' ' + bundle,
					BundleException.ACTIVATOR_ERROR, e);
		}

		if (activator != null) {
			try {
				startActivator(activator);
			} catch (BundleException be) {
				activator = null;
				throw be;
			} finally {
				if (debug.DEBUG_BUNDLE_TIME) {
					Debug.println((System.currentTimeMillis() - start) + " ms to load and start the activator of " + bundle); //$NON-NLS-1$
				}
			}
		}

		/* activator completed successfully. We must use this
		 same activator object when we stop this bundle. */
	}

	private BundleActivator loadBundleActivator() throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		ModuleWiring wiring = bundle.getModule().getCurrentRevision().getWiring();
		if (wiring == null) {
			return null;
		}
		BundleLoader loader = (BundleLoader) wiring.getModuleLoader();
		if (loader == null) {
			return null;
		}
		List<Capability> metadata = wiring.getRevision().getCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
		if (metadata.isEmpty()) {
			return null;
		}

		String activatorName = (String) metadata.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATOR);
		if (activatorName == null) {
			return null;
		}
		Class<?> activatorClass = loader.findClass(activatorName);
		return (BundleActivator) activatorClass.getConstructor().newInstance();
	}

	/**
	 * Calls the start method of a BundleActivator.
	 * @param bundleActivator that activator to start
	 */
	private void startActivator(final BundleActivator bundleActivator) throws BundleException {
		try {
			AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
				if (bundleActivator != null) {
					// make sure the context class loader is set correctly
					Object previousTCCL = setContextFinder();
					/* Start the bundle synchronously */
					try {
						bundleActivator.start(BundleContextImpl.this);
					} finally {
						if (previousTCCL != Boolean.FALSE)
							Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
					}
				}
				return null;
			});
		} catch (Throwable t) {
			if (t instanceof PrivilegedActionException) {
				t = ((PrivilegedActionException) t).getException();
			}

			if (debug.DEBUG_GENERAL) {
				Debug.printStackTrace(t);
			}

			String clazz = null;
			clazz = bundleActivator.getClass().getName();

			throw new BundleException(NLS.bind(Msg.BUNDLE_ACTIVATOR_EXCEPTION, new Object[] {clazz, "start", bundle.getSymbolicName() == null ? "" + bundle.getBundleId() : bundle.getSymbolicName()}), BundleException.ACTIVATOR_ERROR, t); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	Object setContextFinder() {
		if (!container.getConfiguration().BUNDLE_SET_TCCL)
			return Boolean.FALSE;
		Thread currentThread = Thread.currentThread();
		ClassLoader previousTCCL = currentThread.getContextClassLoader();
		ClassLoader contextFinder = container.getContextFinder();
		if (previousTCCL != contextFinder) {
			currentThread.setContextClassLoader(container.getContextFinder());
			return previousTCCL;
		}
		return Boolean.FALSE;
	}

	/**
	 * Call bundle's BundleActivator.stop()
	 * This method is called by Bundle.stopWorker to stop the bundle.
	 *
	 * @exception BundleException if
	 *            the bundle has a class that implements the BundleActivator interface,
	 *            and the BundleActivator.stop() method failed
	 */
	protected void stop() throws BundleException {
		try {
			final BundleActivator bundleActivator = activator;
			AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
				if (bundleActivator != null) {
					// make sure the context class loader is set correctly
					Object previousTCCL = setContextFinder();
					try {
						/* Stop the bundle synchronously */
						bundleActivator.stop(BundleContextImpl.this);
					} finally {
						if (previousTCCL != Boolean.FALSE)
							Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
					}
				}
				return null;
			});
		} catch (Throwable t) {
			if (t instanceof PrivilegedActionException) {
				t = ((PrivilegedActionException) t).getException();
			}

			if (debug.DEBUG_GENERAL) {
				Debug.printStackTrace(t);
			}

			String clazz = (activator == null) ? "" : activator.getClass().getName(); //$NON-NLS-1$

			throw new BundleException(NLS.bind(Msg.BUNDLE_ACTIVATOR_EXCEPTION, new Object[] {clazz, "stop", bundle.getSymbolicName() == null ? "" + bundle.getBundleId() : bundle.getSymbolicName()}), BundleException.ACTIVATOR_ERROR, t); //$NON-NLS-1$ //$NON-NLS-2$
		} finally {
			activator = null;
		}
	}

	/**
	 * Return the map of ServiceRegistrationImpl to ServiceUse for services being
	 * used by this context.
	 * @return A map of ServiceRegistrationImpl to ServiceUse for services in use by
	 * this context.
	 */
	public Map<ServiceRegistrationImpl<?>, ServiceUse<?>> getServicesInUseMap() {
		synchronized (contextLock) {
			return servicesInUse;
		}
	}

	/**
	 * Provision the map of ServiceRegistrationImpl to ServiceUse for services being
	 * used by this context.
	 */
	public void provisionServicesInUseMap() {
		synchronized (contextLock) {
			if (servicesInUse == null)
				// Cannot predict how many services a bundle will use, start with a small table.
				servicesInUse = new HashMap<>(10);
		}
	}

	/**
	 * Bottom level event dispatcher for the BundleContext.
	 *
	 * @param originalListener listener object registered under.
	 * @param l listener to call (may be filtered).
	 * @param action Event class type
	 * @param object Event object
	 */
	@Override
	public void dispatchEvent(Object originalListener, Object l, int action, Object object) {
		Object previousTCCL = setContextFinder();
		try {
			// if context still valid or the system bundle
			if (isValid() || bundle.getBundleId() == 0) {
				switch (action) {
					case EquinoxEventPublisher.BUNDLEEVENT :
					case EquinoxEventPublisher.BUNDLEEVENTSYNC : {
						BundleListener listener = (BundleListener) l;

						if (debug.DEBUG_EVENTS) {
							String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
							Debug.println("dispatchBundleEvent[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}

						listener.bundleChanged((BundleEvent) object);
						break;
					}

					case ServiceRegistry.SERVICEEVENT : {
						ServiceEvent event = (ServiceEvent) object;

						ServiceListener listener = (ServiceListener) l;
						if (debug.DEBUG_EVENTS) {
							String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
							Debug.println("dispatchServiceEvent[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}
						listener.serviceChanged(event);
						break;
					}

					case EquinoxEventPublisher.FRAMEWORKEVENT : {
						FrameworkListener listener = (FrameworkListener) l;

						if (debug.DEBUG_EVENTS) {
							String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
							Debug.println("dispatchFrameworkEvent[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}

						listener.frameworkEvent((FrameworkEvent) object);
						break;
					}
					default : {
						throw new InternalError();
					}
				}
			}
		} catch (Throwable t) {
			if (debug.DEBUG_GENERAL) {
				Debug.println("Exception in bottom level event dispatcher: " + t.getMessage()); //$NON-NLS-1$
				Debug.printStackTrace(t);
			}
			// allow the adaptor to handle this unexpected error
			container.handleRuntimeError(t);
			publisherror: {
				if (action == EquinoxEventPublisher.FRAMEWORKEVENT) {
					FrameworkEvent event = (FrameworkEvent) object;
					if (event.getType() == FrameworkEvent.ERROR) {
						break publisherror; // avoid infinite loop
					}
				}

				container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, t);
			}
		} finally {
			if (previousTCCL != Boolean.FALSE)
				Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
		}
	}

	/**
	 * Construct a Filter object. This filter object may be used
	 * to match a ServiceReference or a Dictionary.
	 * See Filter
	 * for a description of the filter string syntax.
	 *
	 * @param filter The filter string.
	 * @return A Filter object encapsulating the filter string.
	 * @exception InvalidSyntaxException If the filter parameter contains
	 * an invalid filter string which cannot be parsed.
	 */
	@Override
	public Filter createFilter(String filter) throws InvalidSyntaxException {
		checkValid();

		return FilterImpl.newInstance(filter, container.getConfiguration().getDebug().DEBUG_FILTER);
	}

	/**
	 * This method checks that the context is still valid. If the context is
	 * no longer valid, an IllegalStateException is thrown.
	 *
	 * @exception java.lang.IllegalStateException
	 * If the context bundle has stopped.
	 */
	public void checkValid() {
		if (!isValid()) {
			throw new IllegalStateException(Msg.BUNDLE_CONTEXT_INVALID_EXCEPTION + ' ' + bundle);
		}
	}

	/**
	 * This method checks that the context is still valid.
	 *
	 * @return true if the context is still valid; false otherwise
	 */
	protected boolean isValid() {
		return valid;
	}

	@Override
	public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) {
		@SuppressWarnings("unchecked")
		ServiceRegistration<S> registration = (ServiceRegistration<S>) registerService(clazz.getName(), service, properties);
		return registration;
	}

	@Override
	public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Dictionary<String, ?> properties) {
		@SuppressWarnings("unchecked")
		ServiceRegistration<S> registration = (ServiceRegistration<S>) registerService(clazz.getName(), factory, properties);
		return registration;
	}

	@Override
	public <S> ServiceReference<S> getServiceReference(Class<S> clazz) {
		@SuppressWarnings("unchecked")
		ServiceReference<S> reference = (ServiceReference<S>) getServiceReference(clazz.getName());
		return reference;
	}

	@Override
	public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException {
		@SuppressWarnings("unchecked")
		ServiceReference<S>[] refs = (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter);
		if (refs == null) {
			return Collections.emptyList();
		}
		List<ServiceReference<S>> result = new ArrayList<>(refs.length);
		Collections.addAll(result, refs);
		return result;
	}

	public EquinoxContainer getContainer() {
		return container;
	}

	@Override
	public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) {
		checkValid();
		if (reference == null)
			throw new NullPointerException("A null service reference is not allowed."); //$NON-NLS-1$
		provisionServicesInUseMap();
		ServiceObjects<S> serviceObjects = container.getServiceRegistry().getServiceObjects(this, (ServiceReferenceImpl<S>) reference);
		return serviceObjects;
	}
}
