| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.ipojo.junit4osgi; |
| |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import junit.framework.TestCase; |
| |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.packageadmin.PackageAdmin; |
| |
| /** |
| * OSGi Test Case. |
| * Allows the injection of the bundle context. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class OSGiTestCase extends TestCase { |
| |
| /** |
| * The bundle context. |
| */ |
| protected BundleContext context; |
| |
| /** |
| * List of get references. |
| */ |
| private List m_references = new ArrayList(); |
| |
| /** |
| * List of helpers. |
| */ |
| private List m_helpers = new ArrayList(); |
| |
| /** |
| * Gets the Bundle Context. |
| * @return the bundle context. |
| */ |
| public BundleContext getContext() { |
| return context; |
| } |
| |
| /** |
| * Add an helper. |
| * This method is called by the {@link Helper#Helper(OSGiTestCase)} |
| * method. |
| * @param helper the helper object. |
| */ |
| public void addHelper(Helper helper) { |
| m_helpers.add(helper); |
| } |
| |
| /** |
| * Extends runBare to release (unget) services after the teardown. |
| * @throws Throwable when an error occurs. |
| * @see junit.framework.TestCase#runBare() |
| */ |
| public void runBare() throws Throwable { |
| setUp(); |
| try { |
| runTest(); |
| } finally { |
| tearDown(); |
| // Stop Helpers |
| for (int i = 0; i < m_helpers.size(); i++) { |
| ((Helper) m_helpers.get(i)).dispose(); |
| } |
| // Unget services |
| for (int i = 0; i < m_references.size(); i++) { |
| context.ungetService((ServiceReference) m_references.get(i)); |
| } |
| m_references.clear(); |
| } |
| |
| } |
| |
| public void setBundleContext(BundleContext bc) { |
| context = bc; |
| } |
| |
| public BundleContext getBundleContext() { |
| return context; |
| } |
| |
| /** |
| * Checks that the given string is contained in the given array. |
| * @param message the assert point message |
| * @param array the String array |
| * @param txt the String to search |
| */ |
| public static void assertContains(String message, String[] array, String txt) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i].equals(txt)) { |
| return; |
| } |
| } |
| fail(formatContainsMessage(message, array, txt)); |
| } |
| |
| /** |
| * Checks that the given integer is contained in the given array. |
| * @param message the assert point message |
| * @param array the byte array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, byte[] array, int num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Byte[] bytes = new Byte[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Byte(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Integer(num))); |
| } |
| |
| /** |
| * Checks that the given integer is contained in the given array. |
| * @param message the assert point message |
| * @param array the short array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, short[] array, int num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Short[] bytes = new Short[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Short(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Integer(num))); |
| } |
| |
| /** |
| * Checks that the given integer is contained in the given array. |
| * @param message the assert point message |
| * @param array the integer array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, int[] array, int num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Integer[] bytes = new Integer[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Integer(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Integer(num))); |
| } |
| |
| /** |
| * Checks that the given long is contained in the given array. |
| * @param message the assert point message |
| * @param array the long array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, long[] array, long num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Long[] bytes = new Long[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Long(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Long(num))); |
| } |
| |
| /** |
| * Checks that the given float is contained in the given array. |
| * @param message the assert point message |
| * @param array the float array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, float[] array, float num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Float[] bytes = new Float[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Float(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Float(num))); |
| } |
| |
| /** |
| * Checks that the given double is contained in the given array. |
| * @param message the assert point message |
| * @param array the double array |
| * @param num the number to search |
| */ |
| public static void assertContains(String message, double[] array, double num) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == num) { |
| return; |
| } |
| } |
| Double[] bytes = new Double[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Double(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Double(num))); |
| } |
| |
| /** |
| * Checks that the given character is contained in the given array. |
| * @param message the assert point message |
| * @param array the character array |
| * @param character the character to search |
| */ |
| public static void assertContains(String message, char[] array, char character) { |
| for (int i = 0; i < array.length; i++) { |
| if (array[i] == character) { |
| return; |
| } |
| } |
| Character[] bytes = new Character[array.length]; |
| for (int i = 0; i < array.length; i++) { |
| bytes[i] = new Character(array[i]); |
| } |
| fail(formatContainsMessage(message, bytes, new Character(character))); |
| } |
| |
| /** |
| * Asserts that two doubles are equal. If they are not an |
| * AssertionFailedError is thrown with the given message. |
| * @param message the assert point message |
| * @param expected the expected double |
| * @param actual the received double |
| */ |
| public static void assertEquals(String message, double expected, |
| double actual) { |
| if (expected != actual) { |
| fail(formatEqualsMessage(message, new Double(expected), new Double( |
| actual))); |
| } |
| } |
| |
| /** |
| * Asserts that two objects are not equal. If they are an |
| * AssertionFailedError is thrown with the given message. |
| * @param message the assert point message |
| * @param o1 the unexpected object |
| * @param o2 the received object |
| */ |
| public static void assertNotEquals(String message, Object o1, Object o2) { |
| if (o1.equals(o2)) { |
| fail(formatNotEqualsMessage(message, o1, o2)); |
| } |
| } |
| |
| /** |
| * Checks that the given string is contained in the given array. |
| * @param string the String to search |
| * @param array the String array |
| * @return <code>true</code> if the array contains the string |
| */ |
| public static boolean contains(String string, String[] array) { |
| for (int i = 0; array != null && i < array.length; i++) { |
| if (array[i] != null && array[i].equals(string)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Checks that the given integer is contained in the given array. |
| * @param value the number to search |
| * @param array the integer array |
| * @return <code>true</code> if the array contains the value |
| */ |
| public static boolean contains(int value, int[] array) { |
| for (int i = 0; array != null && i < array.length; i++) { |
| if (array[i] == value) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Formats a failure message for 'equality' tests. |
| * @param message the assertion point message |
| * @param expected the expected value |
| * @param actual the received value |
| * @return the computed message |
| */ |
| private static String formatEqualsMessage(String message, Object expected, |
| Object actual) { |
| String formatted = ""; |
| if (message != null) { |
| formatted = message + " "; |
| } |
| return formatted + "expected:<" + expected + "> but was:<" + actual |
| + ">"; |
| } |
| |
| /** |
| * Formats a failure message for 'un-equality' tests. |
| * @param message the assertion point message |
| * @param o1 the unexpected value |
| * @param o2 the received value |
| * @return the computed message |
| */ |
| private static String formatNotEqualsMessage(String message, Object o1, |
| Object o2) { |
| String formatted = ""; |
| if (message != null) { |
| formatted = message + " "; |
| } |
| return formatted + "o1:<" + o1 + "> is equals to o2:<" + o2 + ">"; |
| } |
| |
| /** |
| * Formats a failure message for 'contains' tests. |
| * @param message the assertion point message |
| * @param array the array |
| * @param txt the looked value |
| * @return the computed message |
| */ |
| private static String formatContainsMessage(String message, Object[] array, |
| Object txt) { |
| String formatted = ""; |
| if (message != null) { |
| formatted = message + " "; |
| } |
| |
| String arr = null; |
| for (int i = 0; i < array.length; i++) { |
| if (arr == null) { |
| arr = "[" + array[i]; |
| } else { |
| arr += "," + array[i]; |
| } |
| } |
| arr += "]"; |
| |
| return formatted + "array:" + arr + " does not contains:<" + txt + ">"; |
| } |
| |
| /** |
| * Returns the service object of a service provided by the specified bundle, |
| * offering the specified interface and matching the given filter. |
| * |
| * @param bundle the bundle from which the service is searched. |
| * @param itf the interface provided by the searched service. |
| * @param filter an additional filter (can be {@code null}). |
| * @return the service object provided by the specified bundle, offering the |
| * specified interface and matching the given filter. |
| */ |
| public static Object getServiceObject(Bundle bundle, String itf, |
| String filter) { |
| ServiceReference ref = getServiceReference(bundle, itf, filter); |
| if (ref != null) { |
| return bundle.getBundleContext().getService(ref); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Returns the service objects of the services provided by the specified |
| * bundle, offering the specified interface and matching the given filter. |
| * |
| * @param bundle the bundle from which services are searched. |
| * @param itf the interface provided by the searched services. |
| * @param filter an additional filter (can be {@code null}). |
| * @return the service objects provided by the specified bundle, offering |
| * the specified interface and matching the given filter. |
| */ |
| public static Object[] getServiceObjects(Bundle bundle, String itf, |
| String filter) { |
| ServiceReference[] refs = getServiceReferences(bundle, itf, filter); |
| if (refs != null) { |
| Object[] list = new Object[refs.length]; |
| for (int i = 0; i < refs.length; i++) { |
| list[i] = bundle.getBundleContext().getService(refs[i]); |
| } |
| return list; |
| } else { |
| return new Object[0]; |
| } |
| } |
| |
| /** |
| * Returns the service reference of a service provided by the specified |
| * bundle, offering the specified interface and matching the given filter. |
| * |
| * @param bundle the bundle from which the service is searched. |
| * @param itf the interface provided by the searched service. |
| * @param filter an additional filter (can be {@code null}). |
| * @return a service reference provided by the specified bundle, offering |
| * the specified interface and matching the given filter. If no |
| * service is found, {@code null} is returned. |
| */ |
| public static ServiceReference getServiceReference(Bundle bundle, |
| String itf, String filter) { |
| ServiceReference[] refs = getServiceReferences(bundle, itf, filter); |
| if (refs.length != 0) { |
| return refs[0]; |
| } else { |
| // No service found |
| return null; |
| } |
| } |
| |
| /** |
| * Checks if the service is available. |
| * @param itf the service interface |
| * @return <code>true</code> if the service is available, <code>false</code> |
| * otherwise. |
| */ |
| public boolean isServiceAvailable(String itf) { |
| ServiceReference ref = getServiceReference(itf, null); |
| return ref != null; |
| } |
| |
| /** |
| * Checks if the service is available. |
| * @param itf the service interface |
| * @param pid the service pid |
| * @return <code>true</code> if the service is available, <code>false</code> |
| * otherwise. |
| */ |
| public boolean isServiceAvailableByPID(String itf, String pid) { |
| ServiceReference ref = getServiceReferenceByPID(itf, pid); |
| return ref != null; |
| } |
| |
| /** |
| * Returns the service reference of the service provided by the specified |
| * bundle, offering the specified interface and having the given persistent |
| * ID. |
| * |
| * @param bundle the bundle from which the service is searched. |
| * @param itf the interface provided by the searched service. |
| * @param pid the persistent ID of the searched service. |
| * @return a service provided by the specified bundle, offering the |
| * specified interface and having the given persistent ID. |
| */ |
| public static ServiceReference getServiceReferenceByPID(Bundle bundle, |
| String itf, String pid) { |
| String filter = "(" + "service.pid" + "=" + pid + ")"; |
| ServiceReference[] refs = getServiceReferences(bundle, itf, filter); |
| if (refs == null) { |
| return null; |
| } else if (refs.length == 1) { |
| return refs[0]; |
| } else { |
| throw new IllegalStateException( |
| "A service lookup by PID returned several providers (" |
| + refs.length + ")" + " for " + itf + " with pid=" |
| + pid); |
| } |
| } |
| |
| /** |
| * Returns the service reference of all the services provided in the |
| * specified bundle, offering the specified interface and matching the given |
| * filter. |
| * |
| * @param bundle the bundle from which services are searched. |
| * @param itf the interface provided by the searched services. |
| * @param filter an additional filter (can be {@code null}). |
| * @return all the service references provided in the specified bundle, |
| * offering the specified interface and matching the given filter. |
| * If no service matches, an empty array is returned. |
| */ |
| public static ServiceReference[] getServiceReferences(Bundle bundle, |
| String itf, String filter) { |
| ServiceReference[] refs = null; |
| try { |
| // Get all the service references |
| refs = bundle.getBundleContext().getServiceReferences(itf, filter); |
| } catch (InvalidSyntaxException e) { |
| throw new IllegalArgumentException( |
| "Cannot get service references: " + e.getMessage()); |
| } |
| if (refs == null) { |
| return new ServiceReference[0]; |
| } else { |
| return refs; |
| } |
| } |
| |
| /** |
| * Returns the service object of a service provided by the local bundle, |
| * offering the specified interface and matching the given filter. |
| * |
| * @param itf the interface provided by the searched service. |
| * @param filter an additional filter (can be {@code null}). |
| * @return the service object provided by the local bundle, offering the |
| * specified interface and matching the given filter. |
| */ |
| public Object getServiceObject(String itf, String filter) { |
| ServiceReference ref = getServiceReference(itf, filter); |
| if (ref != null) { |
| m_references.add(ref); |
| return context.getService(ref); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Returns the service object associated with this service reference. |
| * |
| * @param ref service reference |
| * @return the service object. |
| */ |
| public Object getServiceObject(ServiceReference ref) { |
| if (ref != null) { |
| m_references.add(ref); |
| return context.getService(ref); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Returns the service objects of the services provided by the local bundle, |
| * offering the specified interface and matching the given filter. |
| * |
| * @param itf the interface provided by the searched services. |
| * @param filter an additional filter (can be {@code null}). |
| * @return the service objects provided by the local bundle, offering the |
| * specified interface and matching the given filter. |
| */ |
| public Object[] getServiceObjects(String itf, String filter) { |
| ServiceReference[] refs = getServiceReferences(itf, filter); |
| if (refs != null) { |
| Object[] list = new Object[refs.length]; |
| for (int i = 0; i < refs.length; i++) { |
| m_references.add(refs[i]); |
| list[i] = context.getService(refs[i]); |
| } |
| return list; |
| } else { |
| return new Object[0]; |
| } |
| } |
| |
| /** |
| * Returns the service reference of a service provided by the local bundle, |
| * offering the specified interface and matching the given filter. |
| * |
| * @param itf the interface provided by the searched service. |
| * @param filter an additional filter (can be {@code null}). |
| * @return a service reference provided by the local bundle, offering the |
| * specified interface and matching the given filter. If no service |
| * is found, {@code null} is returned. |
| */ |
| public ServiceReference getServiceReference(String itf, String filter) { |
| return getServiceReference(context.getBundle(), itf, filter); |
| } |
| |
| /** |
| * Returns the service reference of a service provided offering the |
| * specified interface. |
| * |
| * @param itf the interface provided by the searched service. |
| * @return a service reference provided by the local bundle, offering the |
| * specified interface and matching the given filter. If no service |
| * is found, {@code null} is returned. |
| */ |
| public ServiceReference getServiceReference(String itf) { |
| return getServiceReference(context.getBundle(), itf, null); |
| } |
| |
| /** |
| * Returns the service reference of the service provided by the local |
| * bundle, offering the specified interface and having the given persistent |
| * ID. |
| * |
| * @param itf the interface provided by the searched service. |
| * @param pid the persistent ID of the searched service. |
| * @return a service provided by the local bundle, offering the specified |
| * interface and having the given persistent ID. |
| */ |
| public ServiceReference getServiceReferenceByPID(String itf, String pid) { |
| return getServiceReferenceByPID(context.getBundle(), itf, pid); |
| } |
| |
| /** |
| * Returns the service reference of all the services provided in the local |
| * bundle, offering the specified interface and matching the given filter. |
| * |
| * @param itf the interface provided by the searched services. |
| * @param filter an additional filter (can be {@code null}). |
| * @return all the service references provided in the local bundle, offering |
| * the specified interface and matching the given filter. If no |
| * service matches, an empty array is returned. |
| */ |
| public ServiceReference[] getServiceReferences(String itf, String filter) { |
| return getServiceReferences(context.getBundle(), itf, filter); |
| } |
| |
| /** |
| * Gets the package admin exposed by the framework. |
| * Fails if the package admin is not available. |
| * @return the package admin service. |
| */ |
| public PackageAdmin getPackageAdmin() { |
| PackageAdmin pa = (PackageAdmin) getServiceObject(PackageAdmin.class.getName(), null); |
| if (pa == null) { |
| fail("No package admin available"); |
| } |
| return pa; |
| } |
| |
| /** |
| * Refresh the packages. |
| * Fails if the package admin service is not available. |
| */ |
| public void refresh() { |
| getPackageAdmin().refreshPackages(null); |
| } |
| |
| /** |
| * Waits for a service. Fails on timeout. |
| * If timeout is set to 0, it sets the timeout to 10s. |
| * @param itf the service interface |
| * @param filter the filter |
| * @param timeout the timeout |
| */ |
| public void waitForService(String itf, String filter, long timeout) { |
| if (timeout == 0) { |
| timeout = 10000; // Default 10 secondes. |
| } |
| ServiceReference[] refs = getServiceReferences(itf, filter); |
| long begin = System.currentTimeMillis(); |
| if (refs.length != 0) { |
| return; |
| } else { |
| while(refs.length == 0) { |
| try { |
| Thread.sleep(5); |
| } catch (InterruptedException e) { |
| // Interrupted |
| } |
| long now = System.currentTimeMillis(); |
| |
| if ((now - begin) > timeout) { |
| fail("Timeout ... no services matching with the request after " + timeout + "ms"); |
| } |
| refs = getServiceReferences(itf, filter); |
| } |
| } |
| } |
| |
| |
| /** |
| * Installs a bundle. |
| * Fails if the bundle cannot be installed. |
| * Be aware that you have to uninstall the bundle yourself. |
| * @param url bundle url |
| * @return the installed bundle |
| */ |
| public Bundle installBundle(String url) { |
| try { |
| return context.installBundle(url); |
| } catch (BundleException e) { |
| fail("Cannot install the bundle " + url + " : " + e.getMessage()); |
| } |
| return null; // Can not happen |
| } |
| |
| /** |
| * Installs a bundle. |
| * Fails if the bundle cannot be installed. |
| * Be aware that you have to uninstall the bundle yourself. |
| * @param url bundle url |
| * @param stream input stream containing the bundle |
| * @return the installed bundle |
| */ |
| public Bundle installBundle(String url, InputStream stream) { |
| try { |
| return context.installBundle(url, stream); |
| } catch (BundleException e) { |
| fail("Cannot install the bundle " + url + " : " + e.getMessage()); |
| } |
| return null; // Can not happen |
| } |
| |
| /** |
| * Installs and starts a bundle. |
| * Fails if the bundle cannot be installed or an error occurs |
| * during startup. Be aware that you have to uninstall the bundle |
| * yourself. |
| * @param url the bundle url |
| * @return the Bundle object. |
| */ |
| public Bundle installAndStart(String url) { |
| Bundle bundle = installBundle(url); |
| try { |
| bundle.start(); |
| } catch (BundleException e) { |
| fail("Cannot start the bundle " + url + " : " + e.getMessage()); |
| } |
| return bundle; |
| } |
| |
| /** |
| * Installs and starts a bundle. |
| * Fails if the bundle cannot be installed or an error occurs |
| * during startup. Be aware that you have to uninstall the bundle |
| * yourself. |
| * @param url the bundle url |
| * @param stream input stream containing the bundle |
| * @return the Bundle object. |
| */ |
| public Bundle installAndStart(String url, InputStream stream) { |
| Bundle bundle = installBundle(url, stream); |
| try { |
| bundle.start(); |
| } catch (BundleException e) { |
| fail("Cannot start the bundle " + url + " : " + e.getMessage()); |
| } |
| return bundle; |
| } |
| |
| /** |
| * Get the bundle by its id. |
| * @param bundleId the bundle id. |
| * @return the bundle with the given id. |
| */ |
| public Bundle getBundle(long bundleId) { |
| return context.getBundle(bundleId); |
| } |
| |
| /** |
| * Gets a bundle by its symbolic name. |
| * Fails if no bundle matches. |
| * @param name the symbolic name of the bundle |
| * @return the bundle object. |
| */ |
| public Bundle getBundle(String name) { |
| Bundle[] bundles = context.getBundles(); |
| for (int i = 0; i < bundles.length; i++) { |
| if (name.equals(bundles[i].getSymbolicName())) { |
| return bundles[i]; |
| } |
| } |
| fail("No bundles with the given symbolic name " + name); |
| return null; // should not happen |
| } |
| |
| |
| |
| } |