/*******************************************************************************
 * Copyright (c) 2004, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.internal.serviceregistry;

import java.security.*;
import java.util.*;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.framework.eventmgr.*;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.BundleContextImpl;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.framework.hooks.service.*;
import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;

/**
 * The Service Registry. This class is the main control point for service 
 * layer operations in the framework.
 * 
 * @ThreadSafe
 */
public class ServiceRegistry {
	public static final int SERVICEEVENT = 3;

	static final String findHookName = FindHook.class.getName();
	@SuppressWarnings("deprecation")
	static final String eventHookName = EventHook.class.getName();
	static final String eventListenerHookName = EventListenerHook.class.getName();
	static final String listenerHookName = ListenerHook.class.getName();

	/** Published services by class name. 
	 * The {@literal List<ServiceRegistrationImpl<?>>}s are both sorted 
	 * in the natural order of ServiceRegistrationImpl and also are sets in that
	 * there must be no two entries in a List which are equal.
	 */
	/* @GuardedBy("this") */
	private final Map<String, List<ServiceRegistrationImpl<?>>> publishedServicesByClass;

	/** All published services. 
	 * The List is both sorted in the natural order of ServiceRegistrationImpl and also is a
	 * set in that there must be no two entries in the List which are equal.
	 */
	/* @GuardedBy("this") */
	private final List<ServiceRegistrationImpl<?>> allPublishedServices;

	/** Published services by BundleContextImpl.  
	 * The {@literal List<ServiceRegistrationImpl<?>>}s are NOT sorted 
	 * and also are sets in that
	 * there must be no two entries in a List which are equal.
	 */
	/* @GuardedBy("this") */
	private final Map<BundleContextImpl, List<ServiceRegistrationImpl<?>>> publishedServicesByContext;

	/** next free service id. */
	/* @GuardedBy("this") */
	private long serviceid;

	/** Active Service Listeners.
	 * {@literal Map<BundleContextImpl,CopyOnWriteIdentityMap<ServiceListener,FilteredServiceListener>>}.
	 */
	/* @GuardedBy("serviceEventListeners") */
	private final Map<BundleContextImpl, CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener>> serviceEventListeners;

	/** initial capacity of the main data structure */
	private static final int initialCapacity = 50;
	/** initial capacity of the nested data structure */
	private static final int initialSubCapacity = 10;
	/** container which created this service registry */
	private final EquinoxContainer container;
	private final BundleContextImpl systemBundleContext;
	final Debug debug;

	/**
	 * Initializes the internal data structures of this ServiceRegistry.
	 *
	 */
	public ServiceRegistry(EquinoxContainer container) {
		this.container = container;
		this.debug = container.getConfiguration().getDebug();
		serviceid = 1;
		publishedServicesByClass = new HashMap<>(initialCapacity);
		publishedServicesByContext = new HashMap<>(initialCapacity);
		allPublishedServices = new ArrayList<>(initialCapacity);
		serviceEventListeners = new HashMap<>(initialCapacity);
		Module systemModule = container.getStorage().getModuleContainer().getModule(0);
		systemBundleContext = (BundleContextImpl) systemModule.getBundle().getBundleContext();
		systemBundleContext.provisionServicesInUseMap();
	}

	/**
	 * Registers the specified service object with the specified properties
	 * under the specified class names into the Framework. A
	 * <code>ServiceRegistrationImpl</code> object is returned. The
	 * <code>ServiceRegistrationImpl</code> 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.
	 * Other bundles can locate the service by using either the
	 * {@link #getServiceReferences} or {@link #getServiceReference} method.
	 * 
	 * <p>
	 * A bundle can register a service object that implements the
	 * {@link ServiceFactory} interface to have more flexibility in providing
	 * service objects to other bundles.
	 * 
	 * <p>
	 * The following steps are required to register a service:
	 * <ol>
	 * <li>If <code>service</code> is not a <code>ServiceFactory</code>,
	 * an <code>IllegalArgumentException</code> is thrown if
	 * <code>service</code> is not an <code>instanceof</code> all the
	 * classes named.
	 * <li>The Framework adds these service properties to the specified
	 * <code>Dictionary</code> (which may be <code>null</code>): a property
	 * named {@link Constants#SERVICE_ID} identifying the registration number of
	 * the service and a property named {@link Constants#OBJECTCLASS} containing
	 * all the specified classes. If any of these properties have already been
	 * specified by the registering bundle, their values will be overwritten by
	 * the Framework.
	 * <li>The service is added to the Framework service registry and may now
	 * be used by other bundles.
	 * <li>A service event of type {@link ServiceEvent#REGISTERED} is fired.
	 * <li>A <code>ServiceRegistration</code> object for this registration is
	 * returned.
	 * </ol>
	 * 
	 * @param context The BundleContext of the registering bundle.
	 * @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 {@link Constants#OBJECTCLASS}.
	 * @param service The service object or a <code>ServiceFactory</code>
	 *        object.
	 * @param properties The properties for this service. The keys in the
	 *        properties object must all be <code>String</code> objects. See
	 *        {@link Constants} for a list of standard service property keys.
	 *        Changes should not be made to this object after calling this
	 *        method. To update the service's properties the
	 *        {@link ServiceRegistration#setProperties} method must be called.
	 *        The set of properties may be <code>null</code> if the service
	 *        has no properties.
	 * 
	 * @return A <code>ServiceRegistrationImpl</code> object for use by the bundle
	 *         registering the service to update the service's properties or to
	 *         unregister the service.
	 * 
	 * @throws java.lang.IllegalArgumentException If one of the following is
	 *         true:
	 *         <ul>
	 *         <li><code>service</code> is <code>null</code>.
	 *         <li><code>service</code> is not a <code>ServiceFactory</code>
	 *         object and is not an instance of all the named classes in
	 *         <code>clazzes</code>.
	 *         <li><code>properties</code> contains case variants of the same
	 *         key name.
	 *         </ul>
	 * 
	 * @throws java.lang.SecurityException If the caller does not have the
	 *         <code>ServicePermission</code> to register the service for all
	 *         the named classes and the Java Runtime Environment supports
	 *         permissions.
	 * 
	 * @throws java.lang.IllegalStateException If this BundleContext is no
	 *         longer valid.
	 * 
	 * @see ServiceRegistration
	 * @see ServiceFactory
	 */
	public ServiceRegistrationImpl<?> registerService(BundleContextImpl context, String[] clazzes, Object service, Dictionary<String, ?> properties) {
		if (service == null) {
			if (debug.DEBUG_SERVICES) {
				Debug.println("Service object is null"); //$NON-NLS-1$
			}

			throw new IllegalArgumentException(Msg.SERVICE_ARGUMENT_NULL_EXCEPTION);
		}

		int size = clazzes.length;

		if (size == 0) {
			if (debug.DEBUG_SERVICES) {
				Debug.println("Classes array is empty"); //$NON-NLS-1$
			}

			throw new IllegalArgumentException(Msg.SERVICE_EMPTY_CLASS_LIST_EXCEPTION);
		}

		/* copy the array so that changes to the original will not affect us. */
		List<String> copy = new ArrayList<>(size);
		// intern the strings and remove duplicates
		for (int i = 0; i < size; i++) {
			String clazz = clazzes[i].intern();
			if (!copy.contains(clazz)) {
				copy.add(clazz);
			}
		}
		size = copy.size();
		clazzes = copy.toArray(new String[size]);

		/* check for ServicePermissions. */
		checkRegisterServicePermission(clazzes);

		if (!(service instanceof ServiceFactory<?>)) {
			String invalidService = checkServiceClass(clazzes, service);
			if (invalidService != null) {
				if (debug.DEBUG_SERVICES) {
					Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
				}
				throw new IllegalArgumentException(NLS.bind(Msg.SERVICE_NOT_INSTANCEOF_CLASS_EXCEPTION, invalidService));
			}
		}

		ServiceRegistrationImpl<?> registration = new ServiceRegistrationImpl<>(this, context, clazzes, service);
		registration.register(properties);
		if (copy.contains(listenerHookName)) {
			notifyNewListenerHook(registration);
		}
		return registration;
	}

	/**
	 * Returns an array of <code>ServiceReferenceImpl</code> objects. The returned
	 * array of <code>ServiceReferenceImpl</code> objects contains services that
	 * were registered under the specified class, match the specified filter
	 * criteria, and the packages for the class names under which the services
	 * were registered match the context bundle's packages as defined in
	 * {@link ServiceReference#isAssignableTo(Bundle, String)}.
	 * 
	 * <p>
	 * The list is valid at the time of the call to this method, however since
	 * the Framework is a very dynamic environment, services can be modified or
	 * unregistered at anytime.
	 * 
	 * <p>
	 * <code>filter</code> 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 <code>filter</code> is <code>null</code>, all registered services
	 * are considered to match the filter. If <code>filter</code> 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 set of
	 * <code>ServiceReferenceImpl</code> objects:
	 * <ol>
	 * <li>If the filter string is not <code>null</code>, the filter string
	 * is parsed and the set <code>ServiceReferenceImpl</code> objects of
	 * registered services that satisfy the filter is produced. If the filter
	 * string is <code>null</code>, then all registered services are
	 * considered to satisfy the filter.
	 * <li>If the Java Runtime Environment supports permissions, the set of
	 * <code>ServiceReferenceImpl</code> objects produced by the previous step is
	 * reduced by checking that the caller has the
	 * <code>ServicePermission</code> to get at least one of the class names
	 * under which the service was registered. If the caller does not have the
	 * correct permission for a particular <code>ServiceReferenceImpl</code>
	 * object, then it is removed from the set.
	 * <li>If <code>clazz</code> is not <code>null</code>, the set is
	 * further reduced to those services that are an <code>instanceof</code>
	 * 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>The set is reduced one final time by cycling through each
	 * <code>ServiceReference</code> object and calling
	 * {@link ServiceReference#isAssignableTo(Bundle, String)} with the context
	 * bundle and each class name under which the <code>ServiceReference</code>
	 * object was registered. For any given <code>ServiceReferenceImpl</code>
	 * object, if any call to
	 * {@link ServiceReference#isAssignableTo(Bundle, String)} returns
	 * <code>false</code>, then it is removed from the set of
	 * <code>ServiceReferenceImpl</code> objects.
	 * <li>An array of the remaining <code>ServiceReferenceImpl</code> objects is
	 * returned.
	 * </ol>
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @param clazz The class name with which the service was registered or
	 *        <code>null</code> for all services.
	 * @param filterstring The filter criteria.
	 * @param allservices True if the bundle called getAllServiceReferences.
	 * @return An array of <code>ServiceReferenceImpl</code> objects or
	 *         <code>null</code> if no services are registered which satisfy
	 *         the search.
	 * @throws InvalidSyntaxException If <code>filter</code> contains an
	 *         invalid filter string that cannot be parsed.
	 * @throws java.lang.IllegalStateException If this BundleContext is no
	 *         longer valid.
	 */
	public ServiceReferenceImpl<?>[] getServiceReferences(final BundleContextImpl context, final String clazz, final String filterstring, final boolean allservices) throws InvalidSyntaxException {
		if (debug.DEBUG_SERVICES) {
			Debug.println((allservices ? "getAllServiceReferences(" : "getServiceReferences(") + clazz + ", \"" + filterstring + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		}
		Filter filter = (filterstring == null) ? null : context.createFilter(filterstring);
		List<ServiceRegistrationImpl<?>> registrations = lookupServiceRegistrations(clazz, filter);
		List<ServiceReferenceImpl<?>> references = new ArrayList<>(registrations.size());
		for (ServiceRegistrationImpl<?> registration : registrations) {
			ServiceReferenceImpl<?> reference;
			try {
				reference = registration.getReferenceImpl();
			} catch (IllegalStateException e) {
				continue; // got unregistered, don't return reference
			}
			if (allservices || isAssignableTo(context, reference)) {
				try { /* test for permission to get the service */
					checkGetServicePermission(reference);
				} catch (SecurityException se) {
					continue; // don't return reference
				}
			} else {
				continue; // don't return reference
			}
			references.add(reference);
		}

		Collection<ServiceReferenceImpl<?>> copyReferences = references;
		if (context.getBundleImpl().getBundleId() == 0) {
			// Make a copy for the purposes of calling the hooks;
			// The the removals from the hooks are ignored for the system bundle
			copyReferences = new ArrayList<>(references);
		}
		Collection<ServiceReference<?>> shrinkable = new ShrinkableCollection<ServiceReference<?>>(copyReferences);
		notifyFindHooks(context, clazz, filterstring, allservices, shrinkable);

		int size = references.size();
		if (size == 0) {
			return null;
		}
		return references.toArray(new ServiceReferenceImpl[size]);
	}

	/**
	 * Returns a <code>ServiceReference</code> object for a service that
	 * implements and was registered under the specified class.
	 * 
	 * <p>
	 * This <code>ServiceReference</code> object 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>
	 * This method is the same as calling
	 * {@link BundleContext#getServiceReferences(String, String)} with a
	 * <code>null</code> filter string. It is provided as a convenience for
	 * when the caller is interested in any service that implements the
	 * specified class.
	 * <p>
	 * If multiple such services exist, the service with the highest ranking (as
	 * specified in its {@link Constants#SERVICE_RANKING} property) is returned.
	 * <p>
	 * If there is a tie in ranking, the service with the lowest service ID (as
	 * specified in its {@link Constants#SERVICE_ID} property); that is, the
	 * service that was registered first is returned.
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @param clazz The class name with which the service was registered.
	 * @return A <code>ServiceReference</code> object, or <code>null</code>
	 *         if no services are registered which implement the named class.
	 * @throws java.lang.IllegalStateException If this BundleContext is no
	 *         longer valid.
	 */
	public ServiceReferenceImpl<?> getServiceReference(BundleContextImpl context, String clazz) {
		if (debug.DEBUG_SERVICES) {
			Debug.println("getServiceReference(" + clazz + ")"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		try {
			ServiceReferenceImpl<?>[] references = getServiceReferences(context, clazz, null, false);

			if (references != null) {
				// Since we maintain the registrations in a sorted List, the first element is always the
				// correct one to return.
				return references[0];
			}
		} catch (InvalidSyntaxException e) {
			if (debug.DEBUG_GENERAL) {
				Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
				Debug.printStackTrace(e);
			}
		}

		return null;
	}

	/**
	 * Returns the specified service object for a service.
	 * <p>
	 * A bundle's use of a service is tracked by the bundle's use count of that
	 * service. Each time a service's service object is returned by
	 * {@link #getService(BundleContextImpl, ServiceReferenceImpl)} the context bundle's use count for
	 * that service is incremented by one. Each time the service is released by
	 * {@link #ungetService(BundleContextImpl, ServiceReferenceImpl)} the context bundle's use count
	 * for that service is decremented by one.
	 * <p>
	 * When a bundle's use count for a service drops to zero, the bundle should
	 * no longer use that service.
	 * 
	 * <p>
	 * This method will always return <code>null</code> when the service
	 * associated with this <code>reference</code> has been unregistered.
	 * 
	 * <p>
	 * The following steps are required 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 currently one
	 * and the service was registered with an object implementing the
	 * <code>ServiceFactory</code> interface, the
	 * {@link ServiceFactory#getService(Bundle, ServiceRegistration)} 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 <code>ServiceFactory</code>
	 * object is not an <code>instanceof</code> all the classes named when the
	 * service was registered or the <code>ServiceFactory</code> object throws
	 * an exception, <code>null</code> is returned and a Framework event of
	 * type {@link FrameworkEvent#ERROR} containing a {@link ServiceException}
	 * describing the error is fired.
	 * <li>The service object for the service is returned.
	 * </ol>
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @param reference A reference to the service.
	 * @return A service object for the service associated with
	 *         <code>reference</code> or <code>null</code> if the service is
	 *         not registered, the service object returned by a
	 *         <code>ServiceFactory</code> does not implement the classes
	 *         under which it was registered or the <code>ServiceFactory</code>
	 *         threw an exception.
	 * @throws java.lang.SecurityException If the caller does not have the
	 *         <code>ServicePermission</code> to get the service using at
	 *         least one of the named classes the service was registered under
	 *         and the Java Runtime Environment supports permissions.
	 * @throws java.lang.IllegalStateException If this BundleContext is no
	 *         longer valid.
	 * @see #ungetService(BundleContextImpl, ServiceReferenceImpl)
	 * @see ServiceFactory
	 */
	public <S> S getService(BundleContextImpl context, ServiceReferenceImpl<S> reference) {
		/* test for permission to get the service */
		checkGetServicePermission(reference);
		return reference.getRegistration().getService(context, ServiceConsumer.singletonConsumer);
	}

	/**
	 * Returns the {@link ServiceObjects} object for the service referenced by
	 * the specified {@code ServiceReference} object.
	 * 
	 * <p>
	 * The {@link ServiceObjects} object can be used to obtain multiple
	 * service objects for services with {@link Constants#SCOPE_PROTOTYPE
	 * prototype} scope. For services with {@link Constants#SCOPE_SINGLETON
	 * singleton} or {@link Constants#SCOPE_BUNDLE bundle} scope, the
	 * {@link ServiceObjects#getService()} method behaves the same as the
	 * {@link BundleContext#getService(ServiceReference)} method and the
	 * {@link ServiceObjects#ungetService(Object)} method behaves the same as
	 * the {@link BundleContext#ungetService(ServiceReference)} method. That is, only one,
	 * use-counted service object is available from the {@link ServiceObjects}
	 * object.
	 * 
	 * <p>
	 * This method will always return {@code null} when the service associated
	 * with the specified {@code reference} has been unregistered.
	 * 
	 * @param <S> Type of Service.
	 * @param context The BundleContext of the requesting bundle.
	 * @param reference A reference to the service.
	 * @return A {@link ServiceObjects} object for the service associated with
	 *         the specified {@code reference} or {@code null} if the service is
	 *         not registered.
	 * @throws SecurityException If the caller does not have the
	 *         {@code ServicePermission} to get the service using at least one
	 *         of the named classes the service was registered under and the
	 *         Java Runtime Environment supports permissions.
	 */
	public <S> ServiceObjectsImpl<S> getServiceObjects(BundleContextImpl context, ServiceReferenceImpl<S> reference) {
		checkGetServicePermission(reference);
		return reference.getRegistration().getServiceObjects(context);
	}

	/**
	 * Releases the service object referenced by the specified
	 * <code>ServiceReference</code> object. 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.
	 * 
	 * <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 required 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 currently zero
	 * and the service was registered with a <code>ServiceFactory</code>
	 * object, the
	 * {@link ServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
	 * method is called to release the service object for the context bundle.
	 * <li><code>true</code> is returned.
	 * </ol>
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @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;
	 *         <code>true</code> otherwise.
	 * @throws java.lang.IllegalStateException If this BundleContext is no
	 *         longer valid.
	 * @see #getService
	 * @see ServiceFactory
	 */
	public boolean ungetService(BundleContextImpl context, ServiceReferenceImpl<?> reference) {
		ServiceRegistrationImpl<?> registration = reference.getRegistration();

		return registration.ungetService(context, ServiceConsumer.singletonConsumer, null);
	}

	/**
	 * Returns this bundle's <code>ServiceReference</code> list for all
	 * services it has registered or <code>null</code> if this bundle has no
	 * registered services.
	 * 
	 * <p>
	 * If the Java runtime supports permissions, a <code>ServiceReference</code>
	 * object to a service is included in the returned list only if the caller
	 * has the <code>ServicePermission</code> to get the service using at
	 * least one of the named classes the service was registered under.
	 * 
	 * <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.
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @return An array of <code>ServiceReference</code> objects or
	 *         <code>null</code>.
	 * @throws java.lang.IllegalStateException If this bundle has been
	 *         uninstalled.
	 * @see ServiceRegistration
	 * @see ServiceReference
	 * @see ServicePermission
	 */
	public ServiceReferenceImpl<?>[] getRegisteredServices(BundleContextImpl context) {
		List<ServiceRegistrationImpl<?>> registrations = lookupServiceRegistrations(context);
		List<ServiceReferenceImpl<?>> references = new ArrayList<>(registrations.size());
		for (ServiceRegistrationImpl<?> registration : registrations) {
			ServiceReferenceImpl<?> reference;
			try {
				reference = registration.getReferenceImpl();
			} catch (IllegalStateException e) {
				continue; // got unregistered, don't return reference
			}
			try {
				/* test for permission to get the service */
				checkGetServicePermission(reference);
			} catch (SecurityException se) {
				continue; // don't return reference
			}
			references.add(reference);
		}

		int size = references.size();
		if (size == 0) {
			return null;
		}
		return references.toArray(new ServiceReferenceImpl[size]);
	}

	/**
	 * Returns this bundle's <code>ServiceReference</code> list for all
	 * services it is using or returns <code>null</code> if this bundle is not
	 * using any services. A bundle is considered to be using a service if its
	 * use count for that service is greater than zero.
	 * 
	 * <p>
	 * If the Java Runtime Environment supports permissions, a
	 * <code>ServiceReference</code> object to a service is included in the
	 * returned list only if the caller has the <code>ServicePermission</code>
	 * to get the service using at least one of the named classes the service
	 * was registered under.
	 * <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.
	 * 
	 * @param context The BundleContext of the requesting bundle.
	 * @return An array of <code>ServiceReference</code> objects or
	 *         <code>null</code>.
	 * @throws java.lang.IllegalStateException If this bundle has been
	 *         uninstalled.
	 * @see ServiceReference
	 * @see ServicePermission
	 */
	public ServiceReferenceImpl<?>[] getServicesInUse(BundleContextImpl context) {
		Map<ServiceRegistrationImpl<?>, ServiceUse<?>> servicesInUse = context.getServicesInUseMap();
		if (servicesInUse == null) {
			return null;
		}

		List<ServiceRegistrationImpl<?>> registrations;
		synchronized (servicesInUse) {
			if (servicesInUse.isEmpty()) {
				return null;
			}
			registrations = new ArrayList<>(servicesInUse.keySet());
		}
		List<ServiceReferenceImpl<?>> references = new ArrayList<>(registrations.size());
		for (ServiceRegistrationImpl<?> registration : registrations) {
			ServiceReferenceImpl<?> reference;
			try {
				reference = registration.getReferenceImpl();
			} catch (IllegalStateException e) {
				continue; // got unregistered, don't return reference
			}
			try {
				/* test for permission to get the service */
				checkGetServicePermission(reference);
			} catch (SecurityException se) {
				continue; // don't return reference
			}
			references.add(reference);
		}

		int size = references.size();
		if (size == 0) {
			return null;
		}
		return references.toArray(new ServiceReferenceImpl[size]);
	}

	/**
	 * Called when the BundleContext is closing to unregister all services
	 * currently registered by the bundle.
	 * 
	 * @param context The BundleContext of the closing bundle.
	 */
	public void unregisterServices(BundleContextImpl context) {
		for (ServiceRegistrationImpl<?> registration : lookupServiceRegistrations(context)) {
			try {
				registration.unregister();
			} catch (IllegalStateException e) {
				/* already unregistered */
			}
		}
		removeServiceRegistrations(context); // remove empty list
	}

	/**
	 * Called when the BundleContext is closing to unget all services
	 * currently used by the bundle.
	 * 
	 * @param context The BundleContext of the closing bundle.
	 */
	public void releaseServicesInUse(BundleContextImpl context) {
		Map<ServiceRegistrationImpl<?>, ServiceUse<?>> servicesInUse = context.getServicesInUseMap();
		if (servicesInUse == null) {
			return;
		}
		List<ServiceRegistrationImpl<?>> registrations;
		synchronized (servicesInUse) {
			if (servicesInUse.isEmpty()) {
				return;
			}
			registrations = new ArrayList<>(servicesInUse.keySet());
		}
		if (debug.DEBUG_SERVICES) {
			Debug.println("Releasing services"); //$NON-NLS-1$
		}
		for (ServiceRegistrationImpl<?> registration : registrations) {
			registration.releaseService(context);
		}
	}

	/**
	 * Add a new Service Listener for a bundle.
	 * 
	 * @param context Context of bundle adding listener.
	 * @param listener Service Listener to be added.
	 * @param filter Filter string for listener or null.
	 * @throws InvalidSyntaxException If the filter string is invalid.
	 */
	public void addServiceListener(BundleContextImpl context, ServiceListener listener, String filter) throws InvalidSyntaxException {
		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("addServiceListener[" + context.getBundleImpl() + "](" + listenerName + ", \"" + filter + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		}

		FilteredServiceListener filteredListener = new FilteredServiceListener(context, listener, filter);
		FilteredServiceListener oldFilteredListener;
		synchronized (serviceEventListeners) {
			CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener> listeners = serviceEventListeners.get(context);
			if (listeners == null) {
				listeners = new CopyOnWriteIdentityMap<>();
				serviceEventListeners.put(context, listeners);
			}
			oldFilteredListener = listeners.put(listener, filteredListener);
		}

		if (oldFilteredListener != null) {
			oldFilteredListener.markRemoved();
			Collection<ListenerInfo> removedListeners = Collections.<ListenerInfo> singletonList(oldFilteredListener);
			notifyListenerHooks(removedListeners, false);
		}

		Collection<ListenerInfo> addedListeners = Collections.<ListenerInfo> singletonList(filteredListener);
		notifyListenerHooks(addedListeners, true);
	}

	/**
	 * Remove a Service Listener for a bundle.
	 * 
	 * @param context Context of bundle removing listener.
	 * @param listener Service Listener to be removed.
	 */
	public void removeServiceListener(BundleContextImpl context, ServiceListener listener) {
		if (debug.DEBUG_EVENTS) {
			String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
			Debug.println("removeServiceListener[" + context.getBundleImpl() + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		FilteredServiceListener oldFilteredListener;
		synchronized (serviceEventListeners) {
			Map<ServiceListener, FilteredServiceListener> listeners = serviceEventListeners.get(context);
			if (listeners == null) {
				return; // this context has no listeners to begin with
			}
			oldFilteredListener = listeners.remove(listener);
		}

		if (oldFilteredListener == null) {
			return;
		}
		oldFilteredListener.markRemoved();
		Collection<ListenerInfo> removedListeners = Collections.<ListenerInfo> singletonList(oldFilteredListener);
		notifyListenerHooks(removedListeners, false);
	}

	/**
	 * Remove all Service Listener for a bundle.
	 * 
	 * @param context Context of bundle removing all listeners.
	 */
	public void removeAllServiceListeners(BundleContextImpl context) {
		Map<ServiceListener, FilteredServiceListener> removedListenersMap;
		synchronized (serviceEventListeners) {
			removedListenersMap = serviceEventListeners.remove(context);
		}
		if ((removedListenersMap == null) || removedListenersMap.isEmpty()) {
			return;
		}
		Collection<FilteredServiceListener> removedListeners = removedListenersMap.values();
		for (FilteredServiceListener oldFilteredListener : removedListeners) {
			oldFilteredListener.markRemoved();
		}
		notifyListenerHooks(asListenerInfos(removedListeners), false);
	}

	/**
	 * Coerce the generic type of a collection from Collection<FilteredServiceListener>
	 * to Collection<ListenerInfo>
	 * @param c Collection to be coerced.
	 * @return c coerced to Collection<ListenerInfo>
	 */
	@SuppressWarnings("unchecked")
	private static Collection<ListenerInfo> asListenerInfos(Collection<? extends ListenerInfo> c) {
		return (Collection<ListenerInfo>) c;
	}

	/**
	 * Deliver a ServiceEvent.
	 * 
	 * @param event The ServiceEvent to deliver.
	 */
	public void publishServiceEvent(final ServiceEvent event) {
		if (System.getSecurityManager() == null) {
			publishServiceEventPrivileged(event);
		} else {
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				public Void run() {
					publishServiceEventPrivileged(event);
					return null;
				}
			});
		}
	}

	void publishServiceEventPrivileged(final ServiceEvent event) {
		/* Build the listener snapshot */
		Map<BundleContextImpl, Set<Map.Entry<ServiceListener, FilteredServiceListener>>> listenerSnapshot;
		Set<Map.Entry<ServiceListener, FilteredServiceListener>> systemServiceListenersOrig = null;
		BundleContextImpl systemContext = null;
		synchronized (serviceEventListeners) {
			listenerSnapshot = new HashMap<>(serviceEventListeners.size());
			for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener>> entry : serviceEventListeners.entrySet()) {
				Map<ServiceListener, FilteredServiceListener> listeners = entry.getValue();
				if (!listeners.isEmpty()) {
					if (entry.getKey().getBundleImpl().getBundleId() == 0) {
						systemContext = entry.getKey();
						// make a copy that we can use to discard hook removals later
						systemServiceListenersOrig = listeners.entrySet();
					}
					listenerSnapshot.put(entry.getKey(), listeners.entrySet());
				}
			}
		}

		/* shrink the snapshot.
		 * keySet returns a Collection which cannot be added to and
		 * removals from that collection will result in removals of the
		 * entry from the snapshot.
		 */
		Collection<BundleContext> contexts = asBundleContexts(listenerSnapshot.keySet());
		notifyEventHooksPrivileged(event, contexts);
		if (!listenerSnapshot.isEmpty()) {
			Map<BundleContext, Collection<ListenerInfo>> listeners = new ShrinkableValueCollectionMap<BundleContext, ListenerInfo>(listenerSnapshot);
			notifyEventListenerHooksPrivileged(event, listeners);
		}
		// always add back the system service listeners if they were removed
		if (systemServiceListenersOrig != null) {
			// No contains key check is done because hooks may have removed
			// a single listener from the value instead of the whole context key.
			// It is more simple to just replace with the original snapshot.
			listenerSnapshot.put(systemContext, systemServiceListenersOrig);
		}
		if (listenerSnapshot.isEmpty()) {
			return;
		}

		/* deliver the event to the snapshot */
		ListenerQueue<ServiceListener, FilteredServiceListener, ServiceEvent> queue = container.newListenerQueue();
		for (Map.Entry<BundleContextImpl, Set<Map.Entry<ServiceListener, FilteredServiceListener>>> entry : listenerSnapshot.entrySet()) {
			@SuppressWarnings({"unchecked", "rawtypes"})
			EventDispatcher<ServiceListener, FilteredServiceListener, ServiceEvent> dispatcher = (EventDispatcher) entry.getKey();
			Set<Map.Entry<ServiceListener, FilteredServiceListener>> listenerSet = entry.getValue();
			queue.queueListeners(listenerSet, dispatcher);
		}
		queue.dispatchEventSynchronous(SERVICEEVENT, event);
	}

	/**
	 * Coerce the generic type of a collection from Collection<BundleContextImpl>
	 * to Collection<BundleContext>
	 * @param c Collection to be coerced.
	 * @return c coerced to Collection<BundleContext>
	 */
	@SuppressWarnings("unchecked")
	private static Collection<BundleContext> asBundleContexts(Collection<? extends BundleContext> c) {
		return (Collection<BundleContext>) c;
	}

	/**
	 * Return the next available service id.
	 * 
	 * @return next service id.
	 */
	synchronized long getNextServiceId() {
		long id = serviceid;
		serviceid = id + 1;
		return id;
	}

	/**
	 * Add the ServiceRegistrationImpl to the data structure.
	 * 
	 * @param context The BundleContext of the bundle registering the service.
	 * @param registration The new ServiceRegistration.
	 */
	/* @GuardedBy("this") */
	void addServiceRegistration(BundleContextImpl context, ServiceRegistrationImpl<?> registration) {
		assert Thread.holdsLock(this);
		// Add the ServiceRegistrationImpl to the list of Services published by BundleContextImpl.
		List<ServiceRegistrationImpl<?>> contextServices = publishedServicesByContext.get(context);
		if (contextServices == null) {
			contextServices = new ArrayList<>(initialSubCapacity);
			publishedServicesByContext.put(context, contextServices);
		}
		// The list is NOT sorted, so we just add
		contextServices.add(registration);

		// Add the ServiceRegistrationImpl to the list of Services published by Class Name.
		int insertIndex;
		for (String clazz : registration.getClasses()) {
			List<ServiceRegistrationImpl<?>> services = publishedServicesByClass.get(clazz);

			if (services == null) {
				services = new ArrayList<>(initialSubCapacity);
				publishedServicesByClass.put(clazz, services);
			}

			// The list is sorted, so we must find the proper location to insert
			insertIndex = -Collections.binarySearch(services, registration) - 1;
			services.add(insertIndex, registration);
		}

		// Add the ServiceRegistrationImpl to the list of all published Services.
		// The list is sorted, so we must find the proper location to insert
		insertIndex = -Collections.binarySearch(allPublishedServices, registration) - 1;
		allPublishedServices.add(insertIndex, registration);
	}

	/**
	 * Modify the ServiceRegistrationImpl in the data structure.
	 * 
	 * @param context The BundleContext of the bundle registering the service.
	 * @param registration The modified ServiceRegistration.
	 */
	/* @GuardedBy("this") */
	void modifyServiceRegistration(BundleContextImpl context, ServiceRegistrationImpl<?> registration) {
		assert Thread.holdsLock(this);
		// The list of Services published by BundleContextImpl is not sorted, so
		// we do not need to modify it.

		// Remove the ServiceRegistrationImpl from the list of Services published by Class Name
		// and then add at the correct index.
		int insertIndex;
		for (String clazz : registration.getClasses()) {
			List<ServiceRegistrationImpl<?>> services = publishedServicesByClass.get(clazz);
			services.remove(registration);
			// The list is sorted, so we must find the proper location to insert
			insertIndex = -Collections.binarySearch(services, registration) - 1;
			services.add(insertIndex, registration);
		}

		// Remove the ServiceRegistrationImpl from the list of all published Services
		// and then add at the correct index.
		allPublishedServices.remove(registration);
		// The list is sorted, so we must find the proper location to insert
		insertIndex = -Collections.binarySearch(allPublishedServices, registration) - 1;
		allPublishedServices.add(insertIndex, registration);
	}

	/**
	 * Remove the ServiceRegistrationImpl from the data structure.
	 * 
	 * @param context The BundleContext of the bundle registering the service.
	 * @param registration The ServiceRegistration to remove.
	 */
	/* @GuardedBy("this") */
	void removeServiceRegistration(BundleContextImpl context, ServiceRegistrationImpl<?> registration) {
		assert Thread.holdsLock(this);
		// Remove the ServiceRegistrationImpl from the list of Services published by BundleContextImpl.
		List<ServiceRegistrationImpl<?>> contextServices = publishedServicesByContext.get(context);
		if (contextServices != null) {
			contextServices.remove(registration);
		}

		// Remove the ServiceRegistrationImpl from the list of Services published by Class Name.
		for (String clazz : registration.getClasses()) {
			List<ServiceRegistrationImpl<?>> services = publishedServicesByClass.get(clazz);
			services.remove(registration);
			if (services.isEmpty()) { // remove empty list
				publishedServicesByClass.remove(clazz);
			}
		}

		// Remove the ServiceRegistrationImpl from the list of all published Services.
		allPublishedServices.remove(registration);
	}

	/**
	 * Lookup Service Registrations in the data structure by class name and filter.
	 * 
	 * @param clazz The class name with which the service was registered or
	 *        <code>null</code> for all services.
	 * @param filter The filter criteria.
	 * @return List<ServiceRegistrationImpl>
	 */
	private List<ServiceRegistrationImpl<?>> lookupServiceRegistrations(String clazz, Filter filter) {
		List<ServiceRegistrationImpl<?>> result;
		synchronized (this) {
			if (clazz == null) { /* all services */
				result = allPublishedServices;
			} else {
				/* services registered under the class name */
				result = publishedServicesByClass.get(clazz);
			}

			if ((result == null) || result.isEmpty()) {
				List<ServiceRegistrationImpl<?>> empty = Collections.<ServiceRegistrationImpl<?>> emptyList();
				return empty;
			}

			result = new LinkedList<>(result); /* make a new list since we don't want to change the real list */
		}

		if (filter == null) {
			return result;
		}

		for (Iterator<ServiceRegistrationImpl<?>> iter = result.iterator(); iter.hasNext();) {
			ServiceRegistrationImpl<?> registration = iter.next();
			ServiceReferenceImpl<?> reference;
			try {
				reference = registration.getReferenceImpl();
			} catch (IllegalStateException e) {
				iter.remove(); /* service was unregistered after we left the synchronized block above */
				continue;
			}
			if (!filter.match(reference)) {
				iter.remove();
			}
		}
		return result;
	}

	/**
	 * Lookup Service Registrations in the data structure by BundleContext.
	 * 
	 * @param context The BundleContext for which to return Service Registrations.
	 * @return List<ServiceRegistrationImpl>
	 */
	private synchronized List<ServiceRegistrationImpl<?>> lookupServiceRegistrations(BundleContextImpl context) {
		List<ServiceRegistrationImpl<?>> result = publishedServicesByContext.get(context);

		if ((result == null) || result.isEmpty()) {
			List<ServiceRegistrationImpl<?>> empty = Collections.<ServiceRegistrationImpl<?>> emptyList();
			return empty;
		}

		return new ArrayList<>(result); /* make a new list since we don't want to change the real list */
	}

	/**
	 * Remove Service Registrations in the data structure by BundleContext.
	 * 
	 * @param context The BundleContext for which to remove Service Registrations.
	 */
	private synchronized void removeServiceRegistrations(BundleContextImpl context) {
		publishedServicesByContext.remove(context);
	}

	/**
	 * Check for permission to register a service.
	 * 
	 * The caller must have permission for ALL names.
	 */
	private static void checkRegisterServicePermission(String[] names) {
		SecurityManager sm = System.getSecurityManager();
		if (sm == null) {
			return;
		}
		for (int i = 0, len = names.length; i < len; i++) {
			sm.checkPermission(new ServicePermission(names[i], ServicePermission.REGISTER));
		}
	}

	/**
	 * Check for permission to get a service.
	 */
	private static void checkGetServicePermission(ServiceReference<?> reference) {
		SecurityManager sm = System.getSecurityManager();
		if (sm == null) {
			return;
		}
		sm.checkPermission(new ServicePermission(reference, ServicePermission.GET));
	}

	/**
	 * Check for permission to listen to a service.
	 */
	static boolean hasListenServicePermission(ServiceEvent event, BundleContextImpl context) {
		ModuleRevision revision = context.getBundleImpl().getModule().getCurrentRevision();
		if (revision == null) {
			return false;
		}
		ProtectionDomain domain = ((Generation) revision.getRevisionInfo()).getDomain();
		if (domain == null) {
			return true;
		}

		return domain.implies(new ServicePermission(event.getServiceReference(), ServicePermission.GET));
	}

	/** 
	 * Return the name of the class that is not satisfied by the service object. 
	 * @param clazzes Array of class names.
	 * @param serviceObject Service object.
	 * @return The name of the class that is not satisfied by the service object.
	 */
	static String checkServiceClass(final String[] clazzes, final Object serviceObject) {
		ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
			public ClassLoader run() {
				return serviceObject.getClass().getClassLoader();
			}
		});
		for (int i = 0, len = clazzes.length; i < len; i++) {
			try {
				Class<?> serviceClazz = cl == null ? Class.forName(clazzes[i]) : cl.loadClass(clazzes[i]);
				if (!serviceClazz.isInstance(serviceObject))
					return clazzes[i];
			} catch (ClassNotFoundException e) {
				//This check is rarely done
				if (extensiveCheckServiceClass(clazzes[i], serviceObject.getClass()))
					return clazzes[i];
			}
		}
		return null;
	}

	private static boolean extensiveCheckServiceClass(String clazz, Class<?> serviceClazz) {
		if (clazz.equals(serviceClazz.getName()))
			return false;
		Class<?>[] interfaces = serviceClazz.getInterfaces();
		for (int i = 0, len = interfaces.length; i < len; i++)
			if (!extensiveCheckServiceClass(clazz, interfaces[i]))
				return false;
		Class<?> superClazz = serviceClazz.getSuperclass();
		if (superClazz != null)
			if (!extensiveCheckServiceClass(clazz, superClazz))
				return false;
		return true;
	}

	static boolean isAssignableTo(BundleContextImpl context, ServiceReferenceImpl<?> reference) {
		Bundle bundle = context.getBundleImpl();
		String[] clazzes = reference.getClasses();
		for (int i = 0, len = clazzes.length; i < len; i++)
			if (!reference.isAssignableTo(bundle, clazzes[i]))
				return false;
		return true;
	}

	/**
	 * Call the registered FindHook services to allow them to inspect and possibly shrink the result.
	 * The FindHook must be called in order: descending by service.ranking, then ascending by service.id.
	 * This is the natural order for ServiceReference.
	 * 
	 * @param context The context of the bundle getting the service references.
	 * @param clazz The class name used to search for the service references.
	 * @param filterstring The filter used to search for the service references.
	 * @param allservices True if getAllServiceReferences called.
	 * @param result The result to return to the caller which may have been shrunk by the FindHooks.
	 */
	private void notifyFindHooks(final BundleContextImpl context, final String clazz, final String filterstring, final boolean allservices, final Collection<ServiceReference<?>> result) {
		if (System.getSecurityManager() == null) {
			notifyFindHooksPrivileged(context, clazz, filterstring, allservices, result);
		} else {
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				public Void run() {
					notifyFindHooksPrivileged(context, clazz, filterstring, allservices, result);
					return null;
				}
			});
		}
	}

	void notifyFindHooksPrivileged(final BundleContextImpl context, final String clazz, final String filterstring, final boolean allservices, final Collection<ServiceReference<?>> result) {
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyServiceFindHooks(" + context.getBundleImpl() + "," + clazz + "," + filterstring + "," + allservices + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
		}
		notifyHooksPrivileged(new HookContext() {
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
				if (hook instanceof FindHook) {
					((FindHook) hook).find(context, clazz, filterstring, allservices, result);
				}
			}

			public String getHookClassName() {
				return findHookName;
			}

			public String getHookMethodName() {
				return "find"; //$NON-NLS-1$
			}

			@Override
			public boolean skipRegistration(ServiceRegistration<?> hookRegistration) {
				return false;
			}
		});
	}

	/**
	 * Call the registered EventHook services to allow them to inspect and possibly shrink the result.
	 * The EventHooks must be called in order: descending by service.ranking, then ascending by service.id.
	 * This is the natural order for ServiceReference.
	 * 
	 * @param event The service event to be delivered.
	 * @param result The result to return to the caller which may have been shrunk by the EventHooks.
	 */
	private void notifyEventHooksPrivileged(final ServiceEvent event, final Collection<BundleContext> result) {
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyServiceEventHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 
		}
		notifyHooksPrivileged(new HookContext() {
			@SuppressWarnings("deprecation")
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
				if (hook instanceof EventHook) {
					((EventHook) hook).event(event, result);
				}
			}

			public String getHookClassName() {
				return eventHookName;
			}

			public String getHookMethodName() {
				return "event"; //$NON-NLS-1$
			}

			@Override
			public boolean skipRegistration(ServiceRegistration<?> hookRegistration) {
				return false;
			}
		});
	}

	/**
	 * Call the registered EventListenerHook services to allow them to inspect and possibly shrink the result.
	 * The EventListenerHooks must be called in order: descending by service.ranking, then ascending by service.id.
	 * This is the natural order for ServiceReference.
	 * 
	 * @param event The service event to be delivered.
	 * @param result The result to return to the caller which may have been shrunk by the EventListenerHooks.
	 */
	private void notifyEventListenerHooksPrivileged(final ServiceEvent event, final Map<BundleContext, Collection<ListenerInfo>> result) {
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyServiceEventListenerHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 
		}
		notifyHooksPrivileged(new HookContext() {
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
				if (hook instanceof EventListenerHook) {
					((EventListenerHook) hook).event(event, result);
				}
			}

			public String getHookClassName() {
				return eventListenerHookName;
			}

			public String getHookMethodName() {
				return "event"; //$NON-NLS-1$
			}

			@Override
			public boolean skipRegistration(ServiceRegistration<?> hookRegistration) {
				return false;
			}
		});
	}

	/**
	 * Calls all hook services of the type specified by the hook context.
	 * 
	 * @param hookContext Context to use when calling the hook services.
	 */
	public void notifyHooksPrivileged(HookContext hookContext) {
		List<ServiceRegistrationImpl<?>> hooks = lookupServiceRegistrations(hookContext.getHookClassName(), null);
		// Since the list is already sorted, we don't need to sort the list to call the hooks
		// in the proper order.

		for (ServiceRegistrationImpl<?> registration : hooks) {
			notifyHookPrivileged(systemBundleContext, registration, hookContext);
		}
	}

	/**
	 * Call a hook service via a hook context.
	 * 
	 * @param context Context of the bundle to get the hook service.
	 * @param registration Hook service to call.
	 * @param hookContext Context to use when calling the hook service.
	 */
	private void notifyHookPrivileged(BundleContextImpl context, ServiceRegistrationImpl<?> registration, HookContext hookContext) {
		if (hookContext.skipRegistration(registration)) {
			return;
		}
		Object hook = registration.getSafeService(context, ServiceConsumer.singletonConsumer);
		if (hook == null) { // if the hook is null
			return;
		}
		try {
			hookContext.call(hook, registration);
		} catch (Throwable t) {
			if (debug.DEBUG_HOOKS) {
				Debug.println(hook.getClass().getName() + "." + hookContext.getHookMethodName() + "() exception: " + t.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
				Debug.printStackTrace(t);
			}
			// allow the adaptor to handle this unexpected error
			container.handleRuntimeError(t);
			ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, hook.getClass().getName(), hookContext.getHookMethodName()), t);
			container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
		} finally {
			registration.ungetService(context, ServiceConsumer.singletonConsumer, null);
		}
	}

	/**
	 * Call a newly registered ListenerHook service to provide the current collection of
	 * service listeners.
	 * 
	 * @param registration The newly registered ListenerHook service.
	 */
	private void notifyNewListenerHook(final ServiceRegistrationImpl<?> registration) {
		if (System.getSecurityManager() == null) {
			notifyNewListenerHookPrivileged(registration);
		} else {
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				public Void run() {
					notifyNewListenerHookPrivileged(registration);
					return null;
				}
			});
		}

	}

	void notifyNewListenerHookPrivileged(ServiceRegistrationImpl<?> registration) {
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyServiceNewListenerHook(" + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ 
		}

		// snapshot the listeners
		Collection<ListenerInfo> addedListeners = new ArrayList<>(initialCapacity);
		synchronized (serviceEventListeners) {
			for (CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener> listeners : serviceEventListeners.values()) {
				if (!listeners.isEmpty()) {
					addedListeners.addAll(listeners.values());
				}
			}
		}

		final Collection<ListenerInfo> listeners = Collections.unmodifiableCollection(addedListeners);
		notifyHookPrivileged(systemBundleContext, registration, new HookContext() {
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
				if (hook instanceof ListenerHook) {
					((ListenerHook) hook).added(listeners);
				}
			}

			public String getHookClassName() {
				return listenerHookName;
			}

			public String getHookMethodName() {
				return "added"; //$NON-NLS-1$
			}

			@Override
			public boolean skipRegistration(ServiceRegistration<?> hookRegistration) {
				return false;
			}
		});
	}

	/**
	 * Call the registered ListenerHook services to notify them of newly added or removed service listeners.
	 * The ListenerHook must be called in order: descending by service.ranking, then ascending by service.id.
	 * This is the natural order for ServiceReference.
	 * 
	 * @param listeners A non-empty, unmodifiable collection of ListenerInfo objects. 
	 * All elements in the list must be for the same bundle. 
	 * @param added <code>true</code> if the specified listeners are being added. <code>false</code>
	 * if they are being removed.
	 */
	private void notifyListenerHooks(final Collection<ListenerInfo> listeners, final boolean added) {
		if (System.getSecurityManager() == null) {
			notifyListenerHooksPrivileged(listeners, added);
		} else {
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				public Void run() {
					notifyListenerHooksPrivileged(listeners, added);
					return null;
				}
			});
		}

	}

	void notifyListenerHooksPrivileged(final Collection<ListenerInfo> listeners, final boolean added) {
		assert !listeners.isEmpty();
		if (debug.DEBUG_HOOKS) {
			Debug.println("notifyServiceListenerHooks(" + listeners + "," + (added ? "added" : "removed") + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		}

		notifyHooksPrivileged(new HookContext() {
			public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
				if (hook instanceof ListenerHook) {
					if (added) {
						((ListenerHook) hook).added(listeners);
					} else {
						((ListenerHook) hook).removed(listeners);
					}
				}
			}

			public String getHookClassName() {
				return listenerHookName;
			}

			public String getHookMethodName() {
				return added ? "added" : "removed"; //$NON-NLS-1$ //$NON-NLS-2$
			}

			@Override
			public boolean skipRegistration(ServiceRegistration<?> hookRegistration) {
				return false;
			}
		});
	}

	final EquinoxContainer getContainer() {
		return container;
	}
}
