All Downloads are FREE. Search and download functionalities are using the official Maven repository.

domino.java.ServiceWatcherCapsule Maven / Gradle / Ivy

There is a newer version: 0.3.1
Show newest version
package domino.java;

import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

import de.tototec.utils.functional.Optional;
import de.tototec.utils.functional.Procedure1;
import domino.java.capsule.Capsule;
import domino.java.internal.Logger;
import domino.java.internal.LoggerFactory;

/**
 * A capsule which executes the given event handlers on service state
 * transitions while the current scope is active. Tracks all state transitions
 * and services visible to the class loader. The custom object facility of the
 * service tracker is not used.
 *
 * @param filter
 *            Filter expression restricting the set of services to be tracked
 * @param f
 *            Event handlers
 * @param bundleContext
 *            Bundle context
 * @tparam S Service type to be tracked
 */
public class ServiceWatcherCapsule implements Capsule {

	private final Logger log = LoggerFactory.getLogger(ServiceWatcherCapsule.class);
	
	private final Filter filter;
	private final Procedure1> f;
	private final BundleContext bundleContext;

	private Optional> tracker = Optional.none();

	public ServiceWatcherCapsule(
			final Filter filter,
			final Procedure1> f,
			final BundleContext bundleContext) {
		this.filter = filter;
		this.f = f;
		this.bundleContext = bundleContext;
	}

	public Optional> tracker() {
		return tracker;
	}
	
	@Override
	public void start() {
		log.debug("About to create service tracker with filter: {}", filter);
		// Create tracker matching this filter
		final ServiceTracker t = new ServiceTracker(bundleContext, filter, null) {
			@Override
			public S addingService(final ServiceReference reference) {
				final S service = context.getService(reference);
				final ServiceWatcherEvent event = new ServiceWatcherEvent(
						service,
						new ServiceWatcherContext<>(tracker().orNull(), reference),
						ServiceWatcherEvent.EventType.ADDING);
				f.apply(event);
				return service;
			}

			@Override
			public void modifiedService(final ServiceReference reference, final S service) {
				final ServiceWatcherEvent event = new ServiceWatcherEvent(
						service,
						new ServiceWatcherContext<>(tracker().orNull(), reference),
						ServiceWatcherEvent.EventType.MODIFIED);
				f.apply(event);
			}

			@Override
			public void removedService(final ServiceReference reference, final S service) {
				final ServiceWatcherEvent event = new ServiceWatcherEvent(
						service,
						new ServiceWatcherContext<>(tracker().orNull(), reference),
						ServiceWatcherEvent.EventType.REMOVED);
				try {
					f.apply(event);
				} finally {
					context.ungetService(reference);
				}
			}
		};
		tracker = Optional.some(t);
		t.open();
	}

	@Override
	public void stop() {
		tracker.foreach(t -> {
			t.close();
			tracker = Optional.none();
		});
	}

}