/*
 * Copyright (c) OSGi Alliance (2007, 2017). 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.annotation.versioning.ConsumerType;
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
 * @author $Id: ac16c218a0df059303f253a33523f753000623c4 $
 * @since 1.4
 */
@ConsumerType
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)
	 */
	@Override
	public T addingBundle(Bundle bundle, BundleEvent event) {
		@SuppressWarnings("unchecked")
		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)
	 */
	@Override
	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)
	 */
	@Override
	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) {
			if (t.isEmpty()) {
				return null;
			}
			return t.copyKeys(new Bundle[0]);
		}
	}

	/**
	 * 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);
		}
	}

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

	/**
	 * Inner class which subclasses AbstractTracked. This class is the
	 * {@code SynchronousBundleListener} object for the tracker.
	 * 
	 * @ThreadSafe
	 * @since 1.4
	 */
	private final 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.
		 */
		@Override
		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.
		 */
		@Override
		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.
		 */
		@Override
		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.
		 */
		@Override
		void customizerRemoved(final Bundle item, final BundleEvent related, final T object) {
			customizer.removedBundle(item, related, object);
		}
	}
}
