/*
 * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.felix.scr.impl.manager;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.osgi.framework.AllServiceListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
 * The {@code ServiceTracker} class simplifies using services from the
 * Framework's service registry.
 * <p>
 * A {@code ServiceTracker} object is constructed with search criteria and a
 * {@code ServiceTrackerCustomizer} object. A {@code ServiceTracker} can use a
 * {@code ServiceTrackerCustomizer} to customize the service objects to be
 * tracked. The {@code ServiceTracker} can then be opened to begin tracking all
 * services in the Framework's service registry that match the specified search
 * criteria. The {@code ServiceTracker} correctly handles all of the details of
 * listening to {@code ServiceEvent}s and getting and ungetting services.
 * <p>
 * The {@code getServiceReferences} method can be called to get references to
 * the services being tracked. The {@code getService} and {@code getServices}
 * methods can be called to get the service objects for the tracked service.
 * <p>
 * The {@code ServiceTracker} class is thread-safe. It does not call a
 * {@code ServiceTrackerCustomizer} while holding any locks.
 * {@code ServiceTrackerCustomizer} implementations must also be thread-safe.
 * 
 * @param <S> The type of the service being tracked.
 * @param <T> The type of the tracked object.
 * @ThreadSafe
 * @version $Id: 21926ad8717a91633face6bbf570febfcd23b1c7 $
 */

/**
 * changes from osgi service tracker:
 *
 * - included AbstractTracked as an inner class.
 * - addedService method on customizer called after the object is tracked.
 * - we always track all matching services.
 *
 * @param <S>
 * @param <T>
 */
public class ServiceTracker<S, T> {
	/* set this to true to compile in debug messages */
	static final boolean					DEBUG	= false;
	/**
	 * The Bundle Context used by this {@code ServiceTracker}.
	 */
	protected final BundleContext			context;
	/**
	 * The Filter used by this {@code ServiceTracker} which specifies the search
	 * criteria for the services to track.
	 * 
	 * @since 1.1
	 */
	protected final Filter					filter;
    /**
     * The {@code ServiceTrackerCustomizer} for this tracker.
     */
    final ServiceTrackerCustomizer<S, T> customizer;
	/**
	 * Filter string for use when adding the ServiceListener. If this field is
	 * set, then certain optimizations can be taken since we don't have a user
	 * supplied filter.
	 */
	final String							listenerFilter;
	/**
	 * Class name to be tracked. If this field is set, then we are tracking by
	 * class name.
	 */
	private final String					trackClass;
	/**
	 * Reference to be tracked. If this field is set, then we are tracking a
	 * single ServiceReference.
	 */
	private final ServiceReference<S>		trackReference;
	/**
	 * Tracked services: {@code ServiceReference} -> customized Object and
	 * {@code ServiceListener} object
	 */
	private volatile Tracked				tracked;


    /**
     * whether the DependencyManager is getting the service immediately.
     */
    private boolean active;

	/**
	 * Accessor method for the current Tracked object. This method is only
	 * intended to be used by the unsynchronized methods which do not modify the
	 * tracked field.
	 * 
	 * @return The current Tracked object.
	 */
	public Tracked tracked() {
		return tracked;
	}

	/**
	 * Cached ServiceReference for getServiceReference.
	 * 
	 * This field is volatile since it is accessed by multiple threads.
	 */
	private volatile ServiceReference<S>	cachedReference;
	/**
	 * Cached service object for getService.
	 * 
	 * This field is volatile since it is accessed by multiple threads.
	 */
	private volatile T						cachedService;

	/**
	 * Create a {@code ServiceTracker} on the specified {@code ServiceReference}
	 * .
	 * 
	 * <p>
	 * The service referenced by the specified {@code ServiceReference} will be
	 * tracked by this {@code ServiceTracker}.
	 * 
	 * @param context The {@code BundleContext} against which the tracking is
	 *        done.
	 * @param reference The {@code ServiceReference} for the service to be
	 *        tracked.
	 * @param customizer The customizer object to call when services are added,
	 *        modified, or removed in this {@code ServiceTracker}. If customizer
	 *        is {@code null}, then this {@code ServiceTracker} will be used as
	 *        the {@code ServiceTrackerCustomizer} and this
	 *        {@code ServiceTracker} will call the
	 *        {@code ServiceTrackerCustomizer} methods on itself.
	 */
	public ServiceTracker(final BundleContext context, final ServiceReference<S> reference, final ServiceTrackerCustomizer<S, T> customizer) {
		this.context = context;
		this.trackReference = reference;
		this.trackClass = null;
		this.customizer = customizer;
		this.listenerFilter = "(" + Constants.SERVICE_ID + "=" + reference.getProperty(Constants.SERVICE_ID).toString() + ")";
		try {
			this.filter = context.createFilter(listenerFilter);
		} catch (InvalidSyntaxException e) {
			/*
			 * we could only get this exception if the ServiceReference was
			 * invalid
			 */
			IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
			iae.initCause(e);
			throw iae;
		}
	}

	/**
	 * Create a {@code ServiceTracker} on the specified class name.
	 * 
	 * <p>
	 * Services registered under the specified class name will be tracked by
	 * this {@code ServiceTracker}.
	 * 
	 * @param context The {@code BundleContext} against which the tracking is
	 *        done.
	 * @param clazz The class name of the services to be tracked.
	 * @param customizer The customizer object to call when services are added,
	 *        modified, or removed in this {@code ServiceTracker}. If customizer
	 *        is {@code null}, then this {@code ServiceTracker} will be used as
	 *        the {@code ServiceTrackerCustomizer} and this
	 *        {@code ServiceTracker} will call the
	 *        {@code ServiceTrackerCustomizer} methods on itself.
	 */
	public ServiceTracker(final BundleContext context, final String clazz, final ServiceTrackerCustomizer<S, T> customizer) {
		this.context = context;
		this.trackReference = null;
		this.trackClass = clazz;
		this.customizer = customizer;
		// we call clazz.toString to verify clazz is non-null!
		this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz + ")";
		try {
			this.filter = context.createFilter(listenerFilter);
		} catch (InvalidSyntaxException e) {
			/*
			 * we could only get this exception if the clazz argument was
			 * malformed
			 */
			IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
			iae.initCause(e);
			throw iae;
		}
	}

	/**
	 * Create a {@code ServiceTracker} on the specified {@code Filter} object.
	 * 
	 * <p>
	 * Services which match the specified {@code Filter} object will be tracked
	 * by this {@code ServiceTracker}.
	 * 
	 * @param context The {@code BundleContext} against which the tracking is
	 *        done.
	 * @param filter The {@code Filter} to select the services to be tracked.
	 * @param customizer The customizer object to call when services are added,
	 *        modified, or removed in this {@code ServiceTracker}. If customizer
	 *        is null, then this {@code ServiceTracker} will be used as the
	 *        {@code ServiceTrackerCustomizer} and this {@code ServiceTracker}
	 *        will call the {@code ServiceTrackerCustomizer} methods on itself.
	 * @param initialActive Initial active state of the tracker.
	 * @since 1.1
	 */
	public ServiceTracker(final BundleContext context, final Filter filter, final ServiceTrackerCustomizer<S, T> customizer, boolean initialActive) {
		this.context = context;
		this.trackReference = null;
		this.trackClass = null;
		this.listenerFilter = filter.toString();
		this.filter = filter;
		this.customizer = customizer;
		this.active = initialActive;
		if ((context == null)) {
			/*
			 * we throw a NPE here to be consistent with the other constructors
			 */
			throw new NullPointerException( "BundleContext");
		}
	}

	/**
	 * Create a {@code ServiceTracker} on the specified class.
	 * 
	 * <p>
	 * Services registered under the name of the specified class will be tracked
	 * by this {@code ServiceTracker}.
	 * 
	 * @param context The {@code BundleContext} against which the tracking is
	 *        done.
	 * @param clazz The class of the services to be tracked.
	 * @param customizer The customizer object to call when services are added,
	 *        modified, or removed in this {@code ServiceTracker}. If customizer
	 *        is {@code null}, then this {@code ServiceTracker} will be used as
	 *        the {@code ServiceTrackerCustomizer} and this
	 *        {@code ServiceTracker} will call the
	 *        {@code ServiceTrackerCustomizer} methods on itself.
	 * @since 1.5
	 */
	public ServiceTracker(final BundleContext context, final Class<S> clazz, final ServiceTrackerCustomizer<S, T> customizer) {
		this(context, clazz.getName(), customizer);
	}

	/**
	 * Open this {@code ServiceTracker} and begin tracking services.
	 * 
	 * <p>
	 * This implementation calls {@code open(false)}.
	 * 
	 * @throws java.lang.IllegalStateException If the {@code BundleContext} with
	 *         which this {@code ServiceTracker} was created is no longer valid.
	 * @see #open(boolean, java.util.concurrent.atomic.AtomicInteger)
     * @param trackingCount
	 */
	public void open( AtomicInteger trackingCount ) {
		open(false, trackingCount );
	}

	/**
	 * Open this {@code ServiceTracker} and begin tracking services.
	 * 
	 * <p>
	 * Services which match the search criteria specified when this
	 * {@code ServiceTracker} was created are now tracked by this
	 * {@code ServiceTracker}.
	 * 
	 *
     * @param trackAllServices If {@code true}, then this {@code ServiceTracker}
     *        will track all matching services regardless of class loader
     *        accessibility. If {@code false}, then this {@code ServiceTracker}
     *        will only track matching services which are class loader
     *        accessible to the bundle whose {@code BundleContext} is used by
     *        this {@code ServiceTracker}.
     * @param trackingCount
     * @throws java.lang.IllegalStateException If the {@code BundleContext} with
	 *         which this {@code ServiceTracker} was created is no longer valid.
	 * @since 1.3
	 */
	public void open( boolean trackAllServices, AtomicInteger trackingCount ) {
		final Tracked t;
		synchronized (this) {
			if (tracked != null) {
				return;
			}
			if (DEBUG) {
				System.out.println("ServiceTracker.open: " + filter);
			}
			t = trackAllServices ? new AllTracked( trackingCount ) : new Tracked( trackingCount );
			synchronized (t) {
				try {
					context.addServiceListener(t, listenerFilter);
					ServiceReference<S>[] references = null;
					if (trackClass != null) {
						references = getInitialReferences(trackAllServices, trackClass, null);
					} else {
						if (trackReference != null) {
							if (trackReference.getBundle() != null) {
								ServiceReference<S>[] single = new ServiceReference[] {trackReference};
								references = single;
							}
						} else { /* user supplied filter */
							references = getInitialReferences(trackAllServices, null, listenerFilter);
						}
					}
					/* set tracked with the initial references */
					t.setInitial(references);
				} catch (InvalidSyntaxException e) {
					throw new RuntimeException("unexpected InvalidSyntaxException: " + e.getMessage(), e);
				}
			}
			tracked = t;
		}
		/* Call tracked outside of synchronized region */
		t.trackInitial(); /* process the initial references */
	}

	/**
	 * Returns the list of initial {@code ServiceReference}s that will be
	 * tracked by this {@code ServiceTracker}.
	 * 
	 * @param trackAllServices If {@code true}, use
	 *        {@code getAllServiceReferences}.
	 * @param className The class name with which the service was registered, or
	 *        {@code null} for all services.
	 * @param filterString The filter criteria or {@code null} for all services.
	 * @return The list of initial {@code ServiceReference}s.
	 * @throws InvalidSyntaxException If the specified filterString has an
	 *         invalid syntax.
	 */
	private ServiceReference<S>[] getInitialReferences(boolean trackAllServices, String className, String filterString) throws InvalidSyntaxException {
		ServiceReference<S>[] result = (ServiceReference<S>[]) ((trackAllServices) ? context.getAllServiceReferences(className, filterString) : context.getServiceReferences(className, filterString));
		return result;
	}

	/**
	 * Close this {@code ServiceTracker}.
	 * 
	 * <p>
	 * This method should be called when this {@code ServiceTracker} should end
	 * the tracking of services.
	 * 
	 * <p>
	 * This implementation calls {@link #getServiceReferences()} to get the list
	 * of tracked services to remove.
     * @param trackingCount
     */
	public SortedMap<ServiceReference<S>, T> close( AtomicInteger trackingCount ) {
		final Tracked outgoing;
//		final ServiceReference<S>[] references;
        SortedMap<ServiceReference<S>, T> map = new TreeMap<ServiceReference<S>, T>(Collections.reverseOrder());
		synchronized (this) {
			outgoing = tracked;
			if (outgoing == null) {
				return map;
			}
			if (DEBUG) {
				System.out.println("ServiceTracker.close: " + filter);
			}
			outgoing.close();
            synchronized ( outgoing )
            {
                trackingCount.set( outgoing.getTrackingCount() );
                outgoing.copyEntries( map );
            }
//			references = getServiceReferences();
//			tracked = null;
			try {
				context.removeServiceListener(outgoing);
			} catch (IllegalStateException e) {
				/* In case the context was stopped. */
			}
		}
		modified(); /* clear the cache */
		synchronized (outgoing) {
			outgoing.notifyAll(); /* wake up any waiters */
		}
//		if (references != null) {
//			for (int i = 0; i < references.length; i++) {
//				outgoing.untrack(references[i], null);
//			}
//		}
		if (DEBUG) {
			if ((cachedReference == null) && (cachedService == null)) {
				System.out.println("ServiceTracker.close[cached cleared]: " + filter);
			}
		}
        return map;
	}

    public void completeClose(Map<ServiceReference<S>, T> toUntrack) {
        final Tracked outgoing;
        synchronized (this) {
            outgoing = tracked;
            if (outgoing == null) {
                return;
            }
            if (DEBUG) {
                System.out.println("ServiceTracker.close: " + filter);
            }
        }
        for (ServiceReference<S> ref: toUntrack.keySet()) {
            outgoing.untrack( ref, null );
        }
        tracked = null;
    }

	/**
	 * Default implementation of the
	 * {@code ServiceTrackerCustomizer.addingService} method.
	 * 
	 * <p>
	 * This method is only called when this {@code ServiceTracker} has been
	 * constructed with a {@code null ServiceTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation returns the result of calling {@code getService} on
	 * the {@code BundleContext} with which this {@code ServiceTracker} was
	 * created passing the specified {@code ServiceReference}.
	 * <p>
	 * This method can be overridden in a subclass to customize the service
	 * object to be tracked for the service being added. In that case, take care
	 * not to rely on the default implementation of
	 * {@link #removedService(ServiceReference, Object, int) removedService} to unget
	 * the service.
	 * 
	 * @param reference The reference to the service being added to this
	 *        {@code ServiceTracker}.
	 * @return The service object to be tracked for the service added to this
	 *         {@code ServiceTracker}.
	 * @see ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference
	 */
	public T addingService(ServiceReference<S> reference, int trackingCount) {
		T result = (T) context.getService(reference);
		return result;
	}

	/**
	 * Default implementation of the
	 * {@code ServiceTrackerCustomizer.modifiedService} method.
	 * 
	 * <p>
	 * This method is only called when this {@code ServiceTracker} has been
	 * constructed with a {@code null ServiceTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation does nothing.
	 * 
	 * @param reference The reference to modified service.
	 * @param service The service object for the modified service.
	 * @see ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, Object, int)
	 */
	public void modifiedService(ServiceReference<S> reference, T service, int trackingCount) {
		/* do nothing */
	}

	/**
	 * Default implementation of the
	 * {@code ServiceTrackerCustomizer.removedService} method.
	 * 
	 * <p>
	 * This method is only called when this {@code ServiceTracker} has been
	 * constructed with a {@code null ServiceTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation calls {@code ungetService}, on the
	 * {@code BundleContext} with which this {@code ServiceTracker} was created,
	 * passing the specified {@code ServiceReference}.
	 * <p>
	 * This method can be overridden in a subclass. If the default
	 * implementation of {@link #addingService(ServiceReference, int) addingService}
	 * method was used, this method must unget the service.
	 * 
	 * @param reference The reference to removed service.
	 * @param service The service object for the removed service.
	 * @see ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, Object, int)
	 */
	public void removedService(ServiceReference<S> reference, T service, int trackingCount) {
		context.ungetService(reference);
	}

	/**
	 * Wait for at least one service to be tracked by this
	 * {@code ServiceTracker}. This method will also return when this
	 * {@code ServiceTracker} is closed.
	 * 
	 * <p>
	 * It is strongly recommended that {@code waitForService} is not used during
	 * the calling of the {@code BundleActivator} methods.
	 * {@code BundleActivator} methods are expected to complete in a short
	 * period of time.
	 * 
	 * <p>
	 * This implementation calls {@link #getService()} to determine if a service
	 * is being tracked.
	 * 
	 * @param timeout The time interval in milliseconds to wait. If zero, the
	 *        method will wait indefinitely.
	 * @return Returns the result of {@link #getService()}.
	 * @throws InterruptedException If another thread has interrupted the
	 *         current thread.
	 * @throws IllegalArgumentException If the value of timeout is negative.
	 */
	public T waitForService(long timeout) throws InterruptedException {
		if (timeout < 0) {
			throw new IllegalArgumentException("timeout value is negative");
		}

		T object = getService();
		if (object != null) {
			return object;
		}

		final long endTime = (timeout == 0) ? 0 : (System.currentTimeMillis() + timeout);
		do {
			final Tracked t = tracked();
			if (t == null) { /* if ServiceTracker is not open */
				return null;
			}
			synchronized (t) {
				if (t.size() == 0) {
					t.wait(timeout);
				}
			}
			object = getService();
			if (endTime > 0) { // if we have a timeout
				timeout = endTime - System.currentTimeMillis();
				if (timeout <= 0) { // that has expired
					break;
				}
			}
		} while (object == null);
		return object;
	}

	/**
	 * Return an array of {@code ServiceReference}s for all services being
	 * tracked by this {@code ServiceTracker}.
	 * 
	 * @return Array of {@code ServiceReference}s or {@code null} if no services
	 *         are being tracked.
	 */
	public ServiceReference<S>[] getServiceReferences() {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return null;
		}
		synchronized (t) {
			int length = t.size();
			if (length == 0) {
				return null;
			}
			ServiceReference<S>[] result = new ServiceReference[length];
			return t.copyKeys(result);
		}
	}

	/**
	 * Returns a {@code ServiceReference} for one of the services being tracked
	 * by this {@code ServiceTracker}.
	 * 
	 * <p>
	 * If multiple services are being tracked, the service with the highest
	 * ranking (as specified in its {@code service.ranking} property) is
	 * returned. If there is a tie in ranking, the service with the lowest
	 * service ID (as specified in its {@code service.id} property); that is,
	 * the service that was registered first is returned. This is the same
	 * algorithm used by {@code BundleContext.getServiceReference}.
	 * 
	 * <p>
	 * This implementation calls {@link #getServiceReferences()} to get the list
	 * of references for the tracked services.
	 * 
	 * @return A {@code ServiceReference} or {@code null} if no services are
	 *         being tracked.
	 * @since 1.1
	 */
	public ServiceReference<S> getServiceReference() {
		ServiceReference<S> reference = cachedReference;
		if (reference != null) {
			if (DEBUG) {
				System.out.println("ServiceTracker.getServiceReference[cached]: " + filter);
			}
			return reference;
		}
		if (DEBUG) {
			System.out.println("ServiceTracker.getServiceReference: " + filter);
		}
		ServiceReference<S>[] references = getServiceReferences();
		int length = (references == null) ? 0 : references.length;
		if (length == 0) { /* if no service is being tracked */
			return null;
		}
		int index = 0;
		if (length > 1) { /* if more than one service, select highest ranking */
			int rankings[] = new int[length];
			int count = 0;
			int maxRanking = Integer.MIN_VALUE;
			for (int i = 0; i < length; i++) {
				Object property = references[i].getProperty(Constants.SERVICE_RANKING);
				int ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
				rankings[i] = ranking;
				if (ranking > maxRanking) {
					index = i;
					maxRanking = ranking;
					count = 1;
				} else {
					if (ranking == maxRanking) {
						count++;
					}
				}
			}
			if (count > 1) { /* if still more than one service, select lowest id */
				long minId = Long.MAX_VALUE;
				for (int i = 0; i < length; i++) {
					if (rankings[i] == maxRanking) {
						long id = ((Long) (references[i].getProperty(Constants.SERVICE_ID))).longValue();
						if (id < minId) {
							index = i;
							minId = id;
						}
					}
				}
			}
		}
		return cachedReference = references[index];
	}

	/**
	 * Returns the service object for the specified {@code ServiceReference} if
	 * the specified referenced service is being tracked by this
	 * {@code ServiceTracker}.
	 * 
	 * @param reference The reference to the desired service.
	 * @return A service object or {@code null} if the service referenced by the
	 *         specified {@code ServiceReference} is not being tracked.
	 */
	public T getService(ServiceReference<S> reference) {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return null;
		}
		synchronized (t) {
			return t.getCustomizedObject(reference);
		}
	}

	/**
	 * Return an array of service objects for all services being tracked by this
	 * {@code ServiceTracker}.
	 * 
	 * <p>
	 * This implementation calls {@link #getServiceReferences()} to get the list
	 * of references for the tracked services and then calls
	 * {@link #getService(ServiceReference)} for each reference to get the
	 * tracked service object.
	 * 
	 * @return An array of service objects or {@code null} if no services are
	 *         being tracked.
	 */
	public Object[] getServices() {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return null;
		}
		synchronized (t) {
			ServiceReference<S>[] references = getServiceReferences();
			int length = (references == null) ? 0 : references.length;
			if (length == 0) {
				return null;
			}
			Object[] objects = new Object[length];
			for (int i = 0; i < length; i++) {
				objects[i] = getService(references[i]);
			}
			return objects;
		}
	}

	/**
	 * Returns a service object for one of the services being tracked by this
	 * {@code ServiceTracker}.
	 * 
	 * <p>
	 * If any services are being tracked, this implementation returns the result
	 * of calling {@code getService(getServiceReference())}.
	 * 
	 * @return A service object or {@code null} if no services are being
	 *         tracked.
	 */
	public T getService() {
		T service = cachedService;
		if (service != null) {
			if (DEBUG) {
				System.out.println("ServiceTracker.getService[cached]: " + filter);
			}
			return service;
		}
		if (DEBUG) {
			System.out.println("ServiceTracker.getService: " + filter);
		}
		ServiceReference<S> reference = getServiceReference();
		if (reference == null) {
			return null;
		}
		return cachedService = getService(reference);
	}

	/**
	 * Remove a service from this {@code ServiceTracker}.
	 * 
	 * The specified service will be removed from this {@code ServiceTracker}.
	 * If the specified service was being tracked then the
	 * {@code ServiceTrackerCustomizer.removedService} method will be called for
	 * that service.
	 * 
	 * @param reference The reference to the service to be removed.
	 */
	public void remove(ServiceReference<S> reference) {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return;
		}
		t.untrack(reference, null);
	}

	/**
	 * Return the number of services being tracked by this
	 * {@code ServiceTracker}.
	 * 
	 * @return The number of services being tracked.
	 */
	public int size() {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return 0;
		}
		synchronized (t) {
			return t.size();
		}
	}

	/**
	 * Returns the tracking count for this {@code ServiceTracker}.
	 * 
	 * The tracking count is initialized to 0 when this {@code ServiceTracker}
	 * is opened. Every time a service is added, modified or removed from this
	 * {@code ServiceTracker}, the tracking count is incremented.
	 * 
	 * <p>
	 * The tracking count can be used to determine if this
	 * {@code ServiceTracker} has added, modified or removed a service by
	 * comparing a tracking count value previously collected with the current
	 * tracking count value. If the value has not changed, then no service has
	 * been added, modified or removed from this {@code ServiceTracker} since
	 * the previous tracking count was collected.
	 * 
	 * @since 1.2
	 * @return The tracking count for this {@code ServiceTracker} or -1 if this
	 *         {@code ServiceTracker} is not open.
	 */
	public int getTrackingCount() {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return -1;
		}
		synchronized (t) {
			return t.getTrackingCount();
		}
	}

	/**
	 * Called by the Tracked object whenever the set of tracked services is
	 * modified. Clears the cache.
	 */
	/*
	 * This method must not be synchronized since it is called by Tracked while
	 * Tracked is synchronized. We don't want synchronization interactions
	 * between the listener thread and the user thread.
	 */
	void modified() {
		cachedReference = null; /* clear cached value */
		cachedService = null; /* clear cached value */
		if (DEBUG) {
			System.out.println("ServiceTracker.modified: " + filter);
		}
	}

	/**
	 * Return a {@code SortedMap} of the {@code ServiceReference}s and service
	 * objects for all services being tracked by this {@code ServiceTracker}.
	 * The map is sorted in reverse natural order of {@code ServiceReference}.
	 * That is, the first entry is the service with the highest ranking and the
	 * lowest service id.
	 * 
	 * @return A {@code SortedMap} with the {@code ServiceReference}s and
	 *         service objects for all services being tracked by this
	 *         {@code ServiceTracker}. If no services are being tracked, then
	 *         the returned map is empty.
	 * @since 1.5
     * @param activate
     * @param trackingCount
     */
	public SortedMap<ServiceReference<S>, T> getTracked( Boolean activate, AtomicInteger trackingCount ) {
		SortedMap<ServiceReference<S>, T> map = new TreeMap<ServiceReference<S>, T>(Collections.reverseOrder());
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return map;
		}
		synchronized (t) {
            if ( activate != null )
            {
                active = activate;
            }
            trackingCount.set( t.getTrackingCount() );
            return t.copyEntries(map);
		}
	}

    void deactivate() {
        final Tracked t = tracked();
        if (t == null) { /* if ServiceTracker is not open */
            return;
        }
        synchronized (t) {
            active = false;
        }
    }

	/**
	 * Return if this {@code ServiceTracker} is empty.
	 * 
	 * @return {@code true} if this {@code ServiceTracker} is not tracking any
	 *         services.
	 * @since 1.5
	 */
	public boolean isEmpty() {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			return true;
		}
		synchronized (t) {
			return t.isEmpty();
		}
	}

    public boolean isActive() {
        final Tracked t = tracked();
        if (t == null) { /* if ServiceTracker is not open */
            return false;
        }
        synchronized (t) {
            return active;
        }

    }

	/**
	 * Return an array of service objects for all services being tracked by this
	 * {@code ServiceTracker}. The runtime type of the returned array is that of
	 * the specified array.
	 * 
	 * <p>
	 * This implementation calls {@link #getServiceReferences()} to get the list
	 * of references for the tracked services and then calls
	 * {@link #getService(ServiceReference)} for each reference to get the
	 * tracked service object.
	 * 
	 * @param array An array into which the tracked service objects will be
	 *        stored, if the array is large enough.
	 * @return An array of service objects being tracked. If the specified array
	 *         is large enough to hold the result, then the specified array is
	 *         returned. If the specified array is longer then necessary to hold
	 *         the result, the array element after the last service object is
	 *         set to {@code null}. If the specified array is not large enough
	 *         to hold the result, a new array is created and returned.
	 * @since 1.5
	 */
	public T[] getServices(T[] array) {
		final Tracked t = tracked();
		if (t == null) { /* if ServiceTracker is not open */
			if (array.length > 0) {
				array[0] = null;
			}
			return array;
		}
		synchronized (t) {
			ServiceReference<S>[] references = getServiceReferences();
			int length = (references == null) ? 0 : references.length;
			if (length == 0) {
				if (array.length > 0) {
					array[0] = null;
				}
				return array;
			}
			if (length > array.length) {
				array = (T[]) Array.newInstance(array.getClass().getComponentType(), length);
			}
			for (int i = 0; i < length; i++) {
				array[i] = getService(references[i]);
			}
			if (array.length > length) {
				array[length] = null;
			}
			return array;
		}
	}

    /**
     * Abstract class to track items. If a Tracker is reused (closed then reopened),
     * then a new AbstractTracked object is used. This class acts a map of tracked
     * item -> customized object. Subclasses of this class will act as the listener
     * object for the tracker. This class is used to synchronize access to the
     * tracked items. This is not a public class. It is only for use by the
     * implementation of the Tracker class.
     *
     * @param <S> The tracked item. It is the key.
     * @param <T> The value mapped to the tracked item.
     * @param <R> The reason the tracked item is being tracked or untracked.
     * @ThreadSafe
     * @version $Id: 16340086b98d308c2d12f13bcd87fc6467a5a367 $
     * @since 1.4
     */
    abstract class AbstractTracked<S, T, R> {
        /* set this to true to compile in debug messages */
        static final boolean		DEBUG	= false;

        /**
         * Map of tracked items to customized objects.
         *
         * @GuardedBy this
         */
        private final Map<S, T> tracked;

        /**
         * Modification count. This field is initialized to zero and incremented by
         * modified.
         *
         * @GuardedBy this
         */
        private final AtomicInteger					trackingCount;

        /**
         * List of items in the process of being added. This is used to deal with
         * nesting of events. Since events may be synchronously delivered, events
         * can be nested. For example, when processing the adding of a service and
         * the customizer causes the service to be unregistered, notification to the
         * nested call to untrack that the service was unregistered can be made to
         * the track method.
         *
         * Since the ArrayList implementation is not synchronized, all access to
         * this list must be protected by the same synchronized object for
         * thread-safety.
         *
         * @GuardedBy this
         */
        private final List<S> adding;

        /**
         * true if the tracked object is closed.
         *
         * This field is volatile because it is set by one thread and read by
         * another.
         */
        volatile boolean			closed;

        /**
         * Initial list of items for the tracker. This is used to correctly process
         * the initial items which could be modified before they are tracked. This
         * is necessary since the initial set of tracked items are not "announced"
         * by events and therefore the event which makes the item untracked could be
         * delivered before we track the item.
         *
         * An item must not be in both the initial and adding lists at the same
         * time. An item must be moved from the initial list to the adding list
         * "atomically" before we begin tracking it.
         *
         * Since the LinkedList implementation is not synchronized, all access to
         * this list must be protected by the same synchronized object for
         * thread-safety.
         *
         * @GuardedBy this
         */
        private final LinkedList<S> initial;

        /**
         * AbstractTracked constructor.
         * @param trackingCount
         */
        AbstractTracked( AtomicInteger trackingCount ) {
            tracked = new HashMap<S, T>();
            this.trackingCount = trackingCount;
            adding = new ArrayList<S>(6);
            initial = new LinkedList<S>();
            closed = false;
        }

        /**
         * Set initial list of items into tracker before events begin to be
         * received.
         *
         * This method must be called from Tracker's open method while synchronized
         * on this object in the same synchronized block as the add listener call.
         *
         * @param list The initial list of items to be tracked. {@code null} entries
         *        in the list are ignored.
         * @GuardedBy this
         */
        void setInitial(S[] list) {
            if (list == null) {
                return;
            }
            for (S item : list) {
                if (item == null) {
                    continue;
                }
                if (DEBUG) {
                    System.out.println("AbstractTracked.setInitial: " + item); //$NON-NLS-1$
                }
                initial.add(item);
            }
        }

        /**
         * Track the initial list of items. This is called after events can begin to
         * be received.
         *
         * This method must be called from Tracker's open method while not
         * synchronized on this object after the add listener call.
         *
         */
        void trackInitial() {
            while (true) {
                S item;
                synchronized (this) {
                    if (closed || (initial.size() == 0)) {
                        /*
                         * if there are no more initial items
                         */
                        return; /* we are done */
                    }
                    /*
                     * move the first item from the initial list to the adding list
                     * within this synchronized block.
                     */
                    item = initial.removeFirst();
                    if (tracked.get(item) != null) {
                        /* if we are already tracking this item */
                        if (DEBUG) {
                            System.out.println("AbstractTracked.trackInitial[already tracked]: " + item); //$NON-NLS-1$
                        }
                        continue; /* skip this item */
                    }
                    if (adding.contains(item)) {
                        /*
                         * if this item is already in the process of being added.
                         */
                        if (DEBUG) {
                            System.out.println("AbstractTracked.trackInitial[already adding]: " + item); //$NON-NLS-1$
                        }
                        continue; /* skip this item */
                    }
                    adding.add(item);
                }
                if (DEBUG) {
                    System.out.println("AbstractTracked.trackInitial: " + item); //$NON-NLS-1$
                }
                trackAdding(item, null); /*
                                         * Begin tracking it. We call trackAdding
                                         * since we have already put the item in the
                                         * adding list.
                                         */
            }
        }

        /**
         * Called by the owning Tracker object when it is closed.
         */
        void close() {
            closed = true;
        }

        /**
         * Begin to track an item.
         *
         * @param item Item to be tracked.
         * @param related Action related object.
         */
        void track(final S item, final R related) {
            boolean tracking;
            final T object;
            int trackingCount = -1;
            synchronized (this) {
                if (closed) {
                    return;
                }
                tracking = tracked.containsKey( item );
                object = tracked.get(item);
                if (!tracking) { /* we are not tracking the item */
                    if (adding.contains(item)) {
                        /* if this item is already in the process of being added. */
                        if (DEBUG) {
                            System.out.println("AbstractTracked.track[already adding]: " + item); //$NON-NLS-1$
                        }
                        return;
                    }
                    adding.add(item); /* mark this item is being added */
                } else { /* we are currently tracking this item */
                    if (DEBUG) {
                        System.out.println("AbstractTracked.track[modified]: " + item); //$NON-NLS-1$
                    }
                    trackingCount = modified(); /* increment modification count */
                }
            }

            if (!tracking) { /* we are not tracking the item */
                trackAdding(item, related);
            } else {
                /* Call customizer outside of synchronized region */
                customizerModified(item, related, object, trackingCount );
                /*
                 * If the customizer throws an unchecked exception, it is safe to
                 * let it propagate
                 */
            }
        }

        /**
         * Common logic to add an item to the tracker used by track and
         * trackInitial. The specified item must have been placed in the adding list
         * before calling this method.
         *
         * @param item Item to be tracked.
         * @param related Action related object.
         */
        private void trackAdding(final S item, final R related) {
            if (DEBUG) {
                System.out.println("AbstractTracked.trackAdding: " + item); //$NON-NLS-1$
            }
            T object = null;
            boolean becameUntracked = false;
            int trackingCount = -1;
            /* Call customizer outside of synchronized region */
            try {
                object = customizerAdding(item, related);
                /*
                 * If the customizer throws an unchecked exception, it will
                 * propagate after the finally
                 */
            } finally {
                synchronized (this) {
                    if (adding.remove(item) && !closed) {
                        /*
                         * if the item was not untracked during the customizer
                         * callback
                         */
                        tracked.put( item, object );
                        trackingCount = modified(); /* increment modification count */
                        notifyAll(); /* notify any waiters */
                    } else {
                        becameUntracked = true;
                    }
                }
            }
            /*
             * The item became untracked during the customizer callback.
             */
            if (becameUntracked) {
                if (DEBUG) {
                    System.out.println("AbstractTracked.trackAdding[removed]: " + item); //$NON-NLS-1$
                }
                /* Call customizer outside of synchronized region */
                customizerRemoved(item, related, object, trackingCount );
                /*
                 * If the customizer throws an unchecked exception, it is safe to
                 * let it propagate
                 */
            } else {
                customizerAdded( item, related, object, trackingCount );
            }
        }

        /**
         * Discontinue tracking the item.
         *
         * @param item Item to be untracked.
         * @param related Action related object.
         */
        void untrack(final S item, final R related) {
            final T object;
            int trackingCount;
            synchronized (this) {
                if (initial.remove(item)) { /*
                                             * if this item is already in the list
                                             * of initial references to process
                                             */
                    if (DEBUG) {
                        System.out.println("AbstractTracked.untrack[removed from initial]: " + item); //$NON-NLS-1$
                    }
                    return; /*
                             * we have removed it from the list and it will not be
                             * processed
                             */
                }

                if (adding.remove(item)) { /*
                                             * if the item is in the process of
                                             * being added
                                             */
                    if (DEBUG) {
                        System.out.println("AbstractTracked.untrack[being added]: " + item); //$NON-NLS-1$
                    }
                    return; /*
                             * in case the item is untracked while in the process of
                             * adding
                             */
                }
                object = tracked.remove(item); /*                                                 * must remove from tracker before
                                                 * calling customizer callback
                                                 */
                if (object == null) { /* are we actually tracking the item */
                    return;
                }
                trackingCount = modified(); /* increment modification count */
            }
            if (DEBUG) {
                System.out.println("AbstractTracked.untrack[removed]: " + item); //$NON-NLS-1$
            }
            /* Call customizer outside of synchronized region */
            customizerRemoved(item, related, object, trackingCount );
            /*
             * If the customizer throws an unchecked exception, it is safe to let it
             * propagate
             */
        }

        /**
         * Returns the number of tracked items.
         *
         * @return The number of tracked items.
         *
         * @GuardedBy this
         */
        int size() {
            return tracked.size();
        }

        /**
         * Returns if the tracker is empty.
         *
         * @return Whether the tracker is empty.
         *
         * @GuardedBy this
         * @since 1.5
         */
        boolean isEmpty() {
            return tracked.isEmpty();
        }

        /**
         * Return the customized object for the specified item
         *
         * @param item The item to lookup in the map
         * @return The customized object for the specified item.
         *
         * @GuardedBy this
         */
        T getCustomizedObject(final S item) {
            return tracked.get( item );
        }

        /**
         * Copy the tracked items into an array.
         *
         * @param list An array to contain the tracked items.
         * @return The specified list if it is large enough to hold the tracked
         *         items or a new array large enough to hold the tracked items.
         * @GuardedBy this
         */
        S[] copyKeys(final S[] list) {
            return tracked.keySet().toArray(list);
        }

        /**
         * Increment the modification count. If this method is overridden, the
         * overriding method MUST call this method to increment the tracking count.
         *
         * @GuardedBy this
         */
        int modified() {
            return trackingCount.incrementAndGet();
        }

        /**
         * Returns the tracking count for this {@code ServiceTracker} object.
         *
         * The tracking count is initialized to 0 when this object is opened. Every
         * time an item is added, modified or removed from this object the tracking
         * count is incremented.
         *
         * @GuardedBy this
         * @return The tracking count for this object.
         */
        int getTrackingCount() {
            return trackingCount.get();
        }

        /**
         * Copy the tracked items and associated values into the specified map.
         *
         * @param <M> Type of {@code Map} to hold the tracked items and associated
         *        values.
         * @param map The map into which to copy the tracked items and associated
         *        values. This map must not be a user provided map so that user code
         *        is not executed while synchronized on this.
         * @return The specified map.
         * @GuardedBy this
         * @since 1.5
         */
        <M extends Map<? super S, ? super T>> M copyEntries(final M map) {
            map.putAll(tracked);
            return map;
        }

        /**
         * Call the specific customizer adding method. This method must not be
         * called while synchronized on this object.
         *
         *
         *
         * @param item Item to be tracked.
         * @param related Action related object.
         * @return Customized object for the tracked item or {@code null} if the
         *         item is not to be tracked.
         */
        abstract T customizerAdding( final S item, final R related );

        abstract void customizerAdded( final S item, final R related, final T object, int trackingCount );

        /**
         * Call the specific customizer modified method. This method must not be
         * called while synchronized on this object.
         *
         * @param item Tracked item.
         * @param related Action related object.
         * @param object Customized object for the tracked item.
         * @param trackingCount
         */
        abstract void customizerModified( final S item, final R related, final T object, int trackingCount );

        /**
         * Call the specific customizer removed method. This method must not be
         * called while synchronized on this object.
         *
         * @param item Tracked item.
         * @param related Action related object.
         * @param object Customized object for the tracked item.
         * @param trackingCount
         */
        abstract void customizerRemoved( final S item, final R related, final T object, int trackingCount );
    }


	/**
	 * Inner class which subclasses AbstractTracked. This class is the
	 * {@code ServiceListener} object for the tracker.
	 * 
	 * @ThreadSafe
	 */
	private class Tracked extends AbstractTracked<ServiceReference<S>, T, ServiceEvent> implements ServiceListener {
		/**
		 * Tracked constructor.
         * @param trackingCount
         */
		Tracked( AtomicInteger trackingCount ) {
			super( trackingCount );
		}

		/**
		 * {@code ServiceListener} method for the {@code ServiceTracker} class.
		 * This method must NOT be synchronized to avoid deadlock potential.
		 * 
		 * @param event {@code ServiceEvent} object from the framework.
		 */
		final public void serviceChanged(final ServiceEvent event) {
			/*
			 * Check if we had a delayed call (which could happen when we
			 * close).
			 */
			if (closed) {
				return;
			}
			final ServiceReference<S> reference = (ServiceReference<S>) event.getServiceReference();
			if (DEBUG) {
				System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: " + reference);
			}

			switch (event.getType()) {
				case ServiceEvent.REGISTERED :
				case ServiceEvent.MODIFIED :
					track(reference, event);
					/*
					 * If the customizer throws an unchecked exception, it is
					 * safe to let it propagate
					 */
					break;
				case ServiceEvent.MODIFIED_ENDMATCH :
				case ServiceEvent.UNREGISTERING :
					untrack(reference, event);
					/*
					 * If the customizer throws an unchecked exception, it is
					 * safe to let it propagate
					 */
					break;
				default :
	                System.out.println("Unrecognized event type: ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: " + reference);
				    
			}
		}

		/**
		 * Increment the tracking count and tell the tracker there was a
		 * modification.
		 * 
		 * @GuardedBy this
		 */
		final int modified() {
			int trackingCount = super.modified(); /* increment the modification count */
			ServiceTracker.this.modified();
            return trackingCount;
		}

		/**
		 * Call the specific customizer adding method. This method must not be
		 * called while synchronized on this object.
		 * 
		 *
         *
         * @param item Item to be tracked.
         * @param related Action related object.
         * @return Customized object for the tracked item or {@code null} if the
		 *         item is not to be tracked.
		 */
		final T customizerAdding( final ServiceReference<S> item, final ServiceEvent related ) {
			return customizer.addingService( item );
		}

		final void customizerAdded( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
		    customizer.addedService( item, object, trackingCount );
		}

		/**
		 * Call the specific customizer modified method. This method must not be
		 * called while synchronized on this object.
		 *
         * @param item Tracked item.
         * @param related Action related object.
         * @param object Customized object for the tracked item.
         * @param trackingCount
         */
		final void customizerModified( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
			customizer.modifiedService( item, object, trackingCount );
		}

        /**
		 * Call the specific customizer removed method. This method must not be
		 * called while synchronized on this object.
		 *
         * @param item Tracked item.
         * @param related Action related object.
         * @param object Customized object for the tracked item.
         * @param trackingCount
         */
		final void customizerRemoved( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
			customizer.removedService(item, object, trackingCount );
		}
	}

	/**
	 * Subclass of Tracked which implements the AllServiceListener interface.
	 * This class is used by the ServiceTracker if open is called with true.
	 * 
	 * @since 1.3
	 * @ThreadSafe
	 */
	private class AllTracked extends Tracked implements AllServiceListener {
		/**
		 * AllTracked constructor.
         * @param trackingCount
         */
		AllTracked( AtomicInteger trackingCount ) {
			super( trackingCount );
		}
	}
}
