/*
 * Copyright (c) OSGi Alliance (2007, 2010). 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.osgi.util.tracker;

import java.util.HashMap;
import java.util.Map;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.SynchronousBundleListener;

/**
 * The {@code BundleTracker} class simplifies tracking bundles much like
 * the {@code ServiceTracker} simplifies tracking services.
 * <p>
 * A {@code BundleTracker} is constructed with state criteria and a
 * {@code BundleTrackerCustomizer} object. A {@code BundleTracker} can
 * use the {@code BundleTrackerCustomizer} to select which bundles are
 * tracked and to create a customized object to be tracked with the bundle. The
 * {@code BundleTracker} can then be opened to begin tracking all bundles
 * whose state matches the specified state criteria.
 * <p>
 * The {@code getBundles} method can be called to get the
 * {@code Bundle} objects of the bundles being tracked. The
 * {@code getObject} method can be called to get the customized object for
 * a tracked bundle.
 * <p>
 * The {@code BundleTracker} class is thread-safe. It does not call a
 * {@code BundleTrackerCustomizer} while holding any locks.
 * {@code BundleTrackerCustomizer} implementations must also be
 * thread-safe.
 * 
 * @param <T> The type of the tracked object.
 * @ThreadSafe
 * @version $Id: 4f1410cfefaf6b9fb6060090d605324e5d9254ac $
 * @since 1.4
 */
public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
	/* set this to true to compile in debug messages */
	static final boolean				DEBUG	= false;

	/**
	 * The Bundle Context used by this {@code BundleTracker}.
	 */
	protected final BundleContext		context;

	/**
	 * The {@code BundleTrackerCustomizer} object for this tracker.
	 */
	final BundleTrackerCustomizer<T>	customizer;

	/**
	 * Tracked bundles: {@code Bundle} object -> customized Object and
	 * {@code BundleListener} object
	 */
	private volatile Tracked			tracked;

	/**
	 * 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.
	 */
	private Tracked tracked() {
		return tracked;
	}

	/**
	 * State mask for bundles being tracked. This field contains the ORed values
	 * of the bundle states being tracked.
	 */
	final int	mask;

	/**
	 * Create a {@code BundleTracker} for bundles whose state is present in
	 * the specified state mask.
	 * 
	 * <p>
	 * Bundles whose state is present on the specified state mask will be
	 * tracked by this {@code BundleTracker}.
	 * 
	 * @param context The {@code BundleContext} against which the tracking
	 *        is done.
	 * @param stateMask The bit mask of the {@code OR}ing of the bundle
	 *        states to be tracked.
	 * @param customizer The customizer object to call when bundles are added,
	 *        modified, or removed in this {@code BundleTracker}. If
	 *        customizer is {@code null}, then this
	 *        {@code BundleTracker} will be used as the
	 *        {@code BundleTrackerCustomizer} and this
	 *        {@code BundleTracker} will call the
	 *        {@code BundleTrackerCustomizer} methods on itself.
	 * @see Bundle#getState()
	 */
	public BundleTracker(BundleContext context, int stateMask,
			BundleTrackerCustomizer<T> customizer) {
		this.context = context;
		this.mask = stateMask;
		this.customizer = (customizer == null) ? this : customizer;
	}

	/**
	 * Open this {@code BundleTracker} and begin tracking bundles.
	 * 
	 * <p>
	 * Bundle which match the state criteria specified when this
	 * {@code BundleTracker} was created are now tracked by this
	 * {@code BundleTracker}.
	 * 
	 * @throws java.lang.IllegalStateException If the {@code BundleContext}
	 *         with which this {@code BundleTracker} was created is no
	 *         longer valid.
	 * @throws java.lang.SecurityException If the caller and this class do not
	 *         have the appropriate
	 *         {@code AdminPermission[context bundle,LISTENER]}, and the
	 *         Java Runtime Environment supports permissions.
	 */
	public void open() {
		final Tracked t;
		synchronized (this) {
			if (tracked != null) {
				return;
			}
			if (DEBUG) {
				System.out.println("BundleTracker.open"); //$NON-NLS-1$
			}
			t = new Tracked();
			synchronized (t) {
				context.addBundleListener(t);
				Bundle[] bundles = context.getBundles();
				if (bundles != null) {
					int length = bundles.length;
					for (int i = 0; i < length; i++) {
						int state = bundles[i].getState();
						if ((state & mask) == 0) {
							/* null out bundles whose states are not interesting */
							bundles[i] = null;
						}
					}
					/* set tracked with the initial bundles */
					t.setInitial(bundles);
				}
			}
			tracked = t;
		}
		/* Call tracked outside of synchronized region */
		t.trackInitial(); /* process the initial references */
	}

	/**
	 * Close this {@code BundleTracker}.
	 * 
	 * <p>
	 * This method should be called when this {@code BundleTracker} should
	 * end the tracking of bundles.
	 * 
	 * <p>
	 * This implementation calls {@link #getBundles()} to get the list of
	 * tracked bundles to remove.
	 */
	public void close() {
		final Bundle[] bundles;
		final Tracked outgoing;
		synchronized (this) {
			outgoing = tracked;
			if (outgoing == null) {
				return;
			}
			if (DEBUG) {
				System.out.println("BundleTracker.close"); //$NON-NLS-1$
			}
			outgoing.close();
			bundles = getBundles();
			tracked = null;
			try {
				context.removeBundleListener(outgoing);
			}
			catch (IllegalStateException e) {
				/* In case the context was stopped. */
			}
		}
		if (bundles != null) {
			for (int i = 0; i < bundles.length; i++) {
				outgoing.untrack(bundles[i], null);
			}
		}
	}

	/**
	 * Default implementation of the
	 * {@code BundleTrackerCustomizer.addingBundle} method.
	 * 
	 * <p>
	 * This method is only called when this {@code BundleTracker} has been
	 * constructed with a {@code null BundleTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation simply returns the specified {@code Bundle}.
	 * 
	 * <p>
	 * This method can be overridden in a subclass to customize the object to be
	 * tracked for the bundle being added.
	 * 
	 * @param bundle The {@code Bundle} being added to this
	 *        {@code BundleTracker} object.
	 * @param event The bundle event which caused this customizer method to be
	 *        called or {@code null} if there is no bundle event associated
	 *        with the call to this method.
	 * @return The specified bundle.
	 * @see BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)
	 */
	public T addingBundle(Bundle bundle, BundleEvent event) {
		T result = (T) bundle;
		return result;
	}

	/**
	 * Default implementation of the
	 * {@code BundleTrackerCustomizer.modifiedBundle} method.
	 * 
	 * <p>
	 * This method is only called when this {@code BundleTracker} has been
	 * constructed with a {@code null BundleTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation does nothing.
	 * 
	 * @param bundle The {@code Bundle} whose state has been modified.
	 * @param event The bundle event which caused this customizer method to be
	 *        called or {@code null} if there is no bundle event associated
	 *        with the call to this method.
	 * @param object The customized object for the specified Bundle.
	 * @see BundleTrackerCustomizer#modifiedBundle(Bundle, BundleEvent, Object)
	 */
	public void modifiedBundle(Bundle bundle, BundleEvent event, T object) {
		/* do nothing */
	}

	/**
	 * Default implementation of the
	 * {@code BundleTrackerCustomizer.removedBundle} method.
	 * 
	 * <p>
	 * This method is only called when this {@code BundleTracker} has been
	 * constructed with a {@code null BundleTrackerCustomizer} argument.
	 * 
	 * <p>
	 * This implementation does nothing.
	 * 
	 * @param bundle The {@code Bundle} being removed.
	 * @param event The bundle event which caused this customizer method to be
	 *        called or {@code null} if there is no bundle event associated
	 *        with the call to this method.
	 * @param object The customized object for the specified bundle.
	 * @see BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)
	 */
	public void removedBundle(Bundle bundle, BundleEvent event, T object) {
		/* do nothing */
	}

	/**
	 * Return an array of {@code Bundle}s for all bundles being tracked by
	 * this {@code BundleTracker}.
	 * 
	 * @return An array of {@code Bundle}s or {@code null} if no
	 *         bundles are being tracked.
	 */
	public Bundle[] getBundles() {
		final Tracked t = tracked();
		if (t == null) { /* if BundleTracker is not open */
			return null;
		}
		synchronized (t) {
			int length = t.size();
			if (length == 0) {
				return null;
			}
			return t.copyKeys(new Bundle[length]);
		}
	}

	/**
	 * Returns the customized object for the specified {@code Bundle} if
	 * the specified bundle is being tracked by this {@code BundleTracker}.
	 * 
	 * @param bundle The {@code Bundle} being tracked.
	 * @return The customized object for the specified {@code Bundle} or
	 *         {@code null} if the specified {@code Bundle} is not
	 *         being tracked.
	 */
	public T getObject(Bundle bundle) {
		final Tracked t = tracked();
		if (t == null) { /* if BundleTracker is not open */
			return null;
		}
		synchronized (t) {
			return t.getCustomizedObject(bundle);
		}
	}

	/**
	 * Remove a bundle from this {@code BundleTracker}.
	 * 
	 * The specified bundle will be removed from this {@code BundleTracker}
	 * . If the specified bundle was being tracked then the
	 * {@code BundleTrackerCustomizer.removedBundle} method will be called
	 * for that bundle.
	 * 
	 * @param bundle The {@code Bundle} to be removed.
	 */
	public void remove(Bundle bundle) {
		final Tracked t = tracked();
		if (t == null) { /* if BundleTracker is not open */
			return;
		}
		t.untrack(bundle, null);
	}

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

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

	/**
	 * Return a {@code Map} with the {@code Bundle}s and customized
	 * objects for all bundles being tracked by this {@code BundleTracker}.
	 * 
	 * @return A {@code Map} with the {@code Bundle}s and customized
	 *         objects for all services being tracked by this
	 *         {@code BundleTracker}. If no bundles are being tracked, then
	 *         the returned map is empty.
	 * @since 1.5
	 */
	public Map<Bundle, T> getTracked() {
		Map<Bundle, T> map = new HashMap<Bundle, T>();
		final Tracked t = tracked();
		if (t == null) { /* if BundleTracker is not open */
			return map;
		}
		synchronized (t) {
			return t.copyEntries(map);
		}
	}

	/**
	 * Inner class which subclasses AbstractTracked. This class is the
	 * {@code SynchronousBundleListener} object for the tracker.
	 * 
	 * @ThreadSafe
	 * @since 1.4
	 */
	class Tracked extends AbstractTracked<Bundle, T, BundleEvent> implements
			SynchronousBundleListener {
		/**
		 * Tracked constructor.
		 */
		Tracked() {
			super();
		}

		/**
		 * {@code BundleListener} method for the {@code BundleTracker}
		 * class. This method must NOT be synchronized to avoid deadlock
		 * potential.
		 * 
		 * @param event {@code BundleEvent} object from the framework.
		 */
		public void bundleChanged(final BundleEvent event) {
			/*
			 * Check if we had a delayed call (which could happen when we
			 * close).
			 */
			if (closed) {
				return;
			}
			final Bundle bundle = event.getBundle();
			final int state = bundle.getState();
			if (DEBUG) {
				System.out
						.println("BundleTracker.Tracked.bundleChanged[" + state + "]: " + bundle); //$NON-NLS-1$ //$NON-NLS-2$
			}

			if ((state & mask) != 0) {
				track(bundle, event);
				/*
				 * If the customizer throws an unchecked exception, it is safe
				 * to let it propagate
				 */
			}
			else {
				untrack(bundle, event);
				/*
				 * If the customizer throws an unchecked exception, it is safe
				 * to let it propagate
				 */
			}
		}

		/**
		 * 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.
		 */
		T customizerAdding(final Bundle item, final BundleEvent related) {
			return customizer.addingBundle(item, related);
		}

		/**
		 * 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.
		 */
		void customizerModified(final Bundle item, final BundleEvent related,
				final T object) {
			customizer.modifiedBundle(item, related, object);
		}

		/**
		 * 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.
		 */
		void customizerRemoved(final Bundle item, final BundleEvent related,
				final T object) {
			customizer.removedBundle(item, related, object);
		}
	}
}
