/* * 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.geronimo.osgi.registry.itest; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.geronimo.osgi.locator.Activator; import org.apache.geronimo.osgi.locator.ProviderLocator; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.CoreOptions; import static org.ops4j.pax.exam.CoreOptions.bundle; import static org.ops4j.pax.exam.CoreOptions.equinox; import static org.ops4j.pax.exam.CoreOptions.felix; import static org.ops4j.pax.exam.CoreOptions.options; import static org.ops4j.pax.exam.CoreOptions.provision; import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; import org.ops4j.pax.exam.Customizer; import org.ops4j.pax.exam.Inject; import org.ops4j.pax.exam.Option; import static org.ops4j.pax.exam.OptionUtils.combine; import org.ops4j.pax.exam.junit.JUnit4TestRunner; import org.ops4j.pax.exam.options.MavenArtifactProvisionOption; import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.*; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @RunWith(JUnit4TestRunner.class) public class OSGiServiceLocatorTest { @Inject protected BundleContext bundleContext; @org.ops4j.pax.exam.junit.Configuration public static Option[] configuration() throws Exception { Option[] options = options( // the target code we're testing... mavenBundle("org.apache.geronimo.specs", "geronimo-osgi-registry"), // bundle containing test resources mavenBundle("org.apache.geronimo.specs", "geronimo-osgi-itesta"), // this bundle opts out of the SPI-Provider status mavenBundle("org.apache.geronimo.specs", "geronimo-osgi-itestb"), mavenBundle("org.ops4j.pax.logging", "pax-logging-api"), felix(), equinox().version("3.5.0"), // we want to specify an activator for the test probe bundle that // is the standard one for adding the locator service to a spec // bundle. We'll use our activator instance to perform class lookups new Customizer() { @Override public InputStream customizeTestProbe( InputStream testProbe ) throws IOException { return modifyBundle(testProbe) // these two classes need to be in every participating bundle .add(org.apache.geronimo.osgi.locator.Activator.class) .add(org.apache.geronimo.osgi.locator.ProviderLocator.class) // we don't have any direct references to this class, so force it to be // included. .add(org.apache.geronimo.osgi.registry.itest.TestTargetLocal.class) // set the required activator also .set(Constants.BUNDLE_ACTIVATOR, org.apache.geronimo.osgi.locator.Activator.class.getName()) // we need an import for activator to function properly. .set(Constants.IMPORT_PACKAGE, "org.apache.geronimo.osgi.registry.api") .build(); } } ); options = updateOptions(options); return options; } @Test public void testServiceLocator() throws Exception { Bundle bundle1 = getInstalledBundle("org.apache.geronimo.specs.geronimo-osgi-itesta"); // now testing the services lookup and instantiation mechanism. These should all be satisfied by // the extender rather than loaded from the classpath. Object service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(service); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", service.getClass().getName()); // we expect a new instance on each call. Verify that the instances are different Object service2 = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(service2); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", service2.getClass().getName()); assertNotSame(service, service2); // now testing a multiple instances get. This should only pick up the definition from the // bundle that includes the SPI-Provider header (testa) List services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertEquals(1, services.size()); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", services.get(0).getClass().getName()); // these should be different instances assertNotSame(service, services.get(0)); // this is multiple instances defined in a single services file. services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itesta.MultiTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertEquals(2, services.size()); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget", services.get(0).getClass().getName()); assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", services.get(1).getClass().getName()); // this should not be found service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.NotFound", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNull(service); // again, not found. Should return an empty list services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.NotFound", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertEquals(0, services.size()); // this should result in an exception try { service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.NoClass", this.getClass(), Thread.currentThread().getContextClassLoader()); fail("Expected ClassNotFoundException not thrown"); } catch (ClassNotFoundException e) { } // this should return an empty list services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.NoClass", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertTrue(services.isEmpty()); // this should result in an exception try { service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.BadClass", this.getClass(), Thread.currentThread().getContextClassLoader()); fail("Expected Exception not thrown"); } catch (NullPointerException e) { } // but this should just give an empty list again services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.BadClass", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertTrue(services.isEmpty()); // this should result in an exception try { service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.NoConstructor", this.getClass(), Thread.currentThread().getContextClassLoader()); fail("Expected Exception not thrown"); } catch (InstantiationException e) { } // and again, an empty list services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.NoConstructor", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertTrue(services.isEmpty()); // this should result in an exception try { service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.NoAccess", this.getClass(), Thread.currentThread().getContextClassLoader()); fail("Expected Exception not thrown"); } catch (IllegalAccessException e) { } // empty list services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.NoAccess", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertTrue(services.isEmpty()); // same set of tests, but this time we're looking for classes, not instances Class<?> target = ProviderLocator.getServiceClass("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(target); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", target.getName()); // now testing a multiple instances get. This should pick up a definition from both // jars on the class path List<Class<?>> classes = ProviderLocator.getServiceClasses("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(classes); assertEquals(1, classes.size()); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", classes.get(0).getName()); // this is multiple instances defined in a single services file. classes = ProviderLocator.getServiceClasses("org.apache.geronimo.osgi.registry.itesta.MultiTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(classes); assertEquals(2, classes.size()); // this should return an instance created from the services definition assertEquals("org.apache.geronimo.osgi.itesta.TestTarget", classes.get(0).getName()); assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", classes.get(1).getName()); // this should not be found target = ProviderLocator.getServiceClass("org.apache.geronimo.osgi.registry.itest.NotFound", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNull(target); // again, not found. Should return an empty list classes = ProviderLocator.getServiceClasses("org.apache.geronimo.osgi.registry.itest.NotFound", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(classes); assertEquals(0, classes.size()); // this should result in an exception try { target = ProviderLocator.getServiceClass("org.apache.geronimo.osgi.registry.itest.NoClass", this.getClass(), Thread.currentThread().getContextClassLoader()); fail("Expected ClassNotFoundException not thrown"); } catch (ClassNotFoundException e) { } // an empty list again classes = ProviderLocator.getServiceClasses("org.apache.geronimo.osgi.registry.itest.NoClass", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(classes); assertTrue(classes.isEmpty()); // now stop the first bundle, which should remove the service defintions. bundle1.stop(); // repeat the first queries, which should fail now service = ProviderLocator.getService("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNull(service); // this should revert to an empty list now. services = ProviderLocator.getServices("org.apache.geronimo.osgi.registry.itest.TestTarget", this.getClass(), Thread.currentThread().getContextClassLoader()); assertNotNull(services); assertEquals(0, services.size()); } protected Bundle getInstalledBundle(String symbolicName) { for (Bundle b : bundleContext.getBundles()) { if (b.getSymbolicName().equals(symbolicName)) { return b; } } return null; } public static MavenArtifactProvisionOption mavenBundle(String groupId, String artifactId) { return CoreOptions.mavenBundle().groupId(groupId).artifactId(artifactId).versionAsInProject(); } protected static Option[] updateOptions(Option[] options) { // We need to add pax-exam-junit here when running with the ibm // jdk to avoid the following exception during the test run: // ClassNotFoundException: org.ops4j.pax.exam.junit.Configuration if ("IBM Corporation".equals(System.getProperty("java.vendor"))) { Option[] ibmOptions = options( wrappedBundle(mavenBundle("org.ops4j.pax.exam", "pax-exam-junit")) ); options = combine(ibmOptions, options); } return options; } }