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

aQute.junit.runtime.OSGiTestCase Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package aQute.junit.runtime;

import java.text.MessageFormat;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

public abstract class OSGiTestCase extends TestCase {
	/**
	 * Returns the {@link BundleContext} for the current class. This method
	 * should be called by subclasses as their point of entry into the OSGi
	 * Framework, but it may return {@code null} if the class is not associated
	 * by a bundle -- for example, if the Test is executed outside of an OSGi
	 * Framework.
	 *
	 * @return The {@link BundleContext} of the receiver, or {@code
		 * null} if the
	 */
	protected BundleContext getBundleContext() {
		Bundle bundle = FrameworkUtil.getBundle(this.getClass());
		return bundle != null ? bundle.getBundleContext() : null;
	}

	/**
	 * Asserts that at least one service of the specified type is currently
	 * available. If not, an {@link AssertionFailedError} is thrown.
	 *
	 * @param service The service interface type.
	 * @param filter An additional service filter, which may be {@code null}.
	 */
	protected void assertSvcAvail(Class service, String filter) {
		assertSvcAvail(null, service, filter);
	}

	/**
	 * Asserts that at least one service of the specified type is currently
	 * available. If not, an {@link AssertionFailedError} is thrown with the
	 * given message.
	 *
	 * @param message
	 * @param service The service interface type.
	 * @param filter An additional service filter, which may be {@code
		 * null}.
	 */
	protected void assertSvcAvail(String message, Class service, String filter) {
		BundleContext context = getBundleContext();
		ServiceReference[] refs = null;
		try {
			refs = context.getServiceReferences(service.getName(), filter);
		} catch (InvalidSyntaxException e) {
			fail("Invalid filter syntax");
		}

		if (refs == null || refs.length == 0) {
			fail(message);
			return;
		}

		Object svcObj = context.getService(refs[0]);
		if (svcObj == null)
			fail(message);

		try {
			if (!service.isInstance(svcObj))
				fail(message);
		} finally {
			context.ungetService(refs[0]);
		}
	}

	/**
	 * 

* Perform the specified operation against a service, or fail immediately if * a matching service is not available. *

*

* Example: *

*

* Example: *

* *
	 * String reply = withService(HelloService.class, null, new Operation<HelloService, String>() {
	 * 	public String call(HelloService service) {
	 * 		return service.sayHello();
	 * 	}
	 * });
	 * 
* * @param The service type. * @param The result type. * @param service The service class. * @param filter An additional filter expression, or {@code * null}. * @param operation The operation to perform against the service. * @throws Exception */ protected R withService(Class service, String filter, Operation operation) throws Exception { return withService(service, filter, 0, operation); } /** *

* Perform the specified operation against a service, if available. *

*

* Example: *

* *
	 * String reply = withService(HelloService.class, null, 0, new Operation<HelloService, String>() {
	 * 	public String call(HelloService service) {
	 * 		return service.sayHello();
	 * 	}
	 * });
	 * 
* * @param The service type. * @param The result type. * @param service The service class. * @param filter An additional filter expression, or {@code * null}. * @param timeout The maximum time to wait (in ms) for a service to become * available; a zero or negative timeout implies we should fail * if the service is not immediatelt available. * @param operation The operation to perform against the service. * @throws Exception */ protected R withService(Class service, String filter, long timeout, Operation operation) throws Exception { BundleContext context = getBundleContext(); ServiceTracker tracker = null; if (filter != null) { try { Filter combined = FrameworkUtil .createFilter("(" + Constants.OBJECTCLASS + "=" + service.getName() + ")"); tracker = new ServiceTracker<>(context, combined, null); } catch (InvalidSyntaxException e) { fail("Invalid filter syntax."); return null; } } else { tracker = new ServiceTracker<>(context, service.getName(), null); } try { tracker.open(); Object instance; if (timeout <= 0) { instance = tracker.getService(); } else { instance = tracker.waitForService(timeout); } if (instance == null || !service.isInstance(instance)) fail(MessageFormat.format("Service \"{0}\" not available.", service.getName())); @SuppressWarnings("unchecked") S casted = (S) instance; return operation.perform(casted); } catch (InterruptedException e) { fail("Interrupted."); } finally { tracker.close(); } // unreachable return null; } /** * Default wait timeout is 10 seconds */ public static long DEFAULT_TIMEOUT = 10000; }