| /* |
| * 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.apache.aries.subsystem.itests; |
| |
| 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.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.ops4j.pax.exam.CoreOptions.composite; |
| import static org.ops4j.pax.exam.CoreOptions.junitBundles; |
| import static org.ops4j.pax.exam.CoreOptions.mavenBundle; |
| import static org.ops4j.pax.exam.CoreOptions.streamBundle; |
| import static org.ops4j.pax.exam.CoreOptions.systemProperty; |
| import static org.ops4j.pax.exam.CoreOptions.vmOption; |
| import static org.ops4j.pax.exam.CoreOptions.when; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.Field; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.EnumSet; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.apache.aries.itest.AbstractIntegrationTest; |
| import org.apache.aries.itest.RichBundleContext; |
| import org.apache.aries.subsystem.AriesSubsystem; |
| import org.apache.aries.subsystem.core.archive.ProvisionPolicyDirective; |
| import org.apache.aries.subsystem.core.archive.SubsystemTypeHeader; |
| import org.apache.aries.subsystem.core.archive.TypeAttribute; |
| import org.apache.aries.subsystem.core.internal.BundleResource; |
| import org.apache.aries.subsystem.core.internal.SubsystemIdentifier; |
| import org.apache.aries.subsystem.itests.util.TestRepository; |
| import org.apache.aries.subsystem.itests.util.Utils; |
| import org.apache.aries.unittest.fixture.ArchiveFixture; |
| import org.apache.aries.unittest.fixture.ArchiveFixture.JarFixture; |
| import org.apache.aries.unittest.fixture.ArchiveFixture.ManifestFixture; |
| import org.apache.aries.unittest.fixture.ArchiveFixture.ZipFixture; |
| import org.apache.aries.util.filesystem.FileSystem; |
| import org.eclipse.equinox.region.Region; |
| import org.eclipse.equinox.region.RegionDigraph; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.runner.RunWith; |
| import org.ops4j.io.StreamUtils; |
| import org.ops4j.pax.exam.Configuration; |
| import org.ops4j.pax.exam.CoreOptions; |
| import org.ops4j.pax.exam.Option; |
| import org.ops4j.pax.exam.junit.PaxExam; |
| import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; |
| import org.ops4j.pax.exam.spi.reactors.PerClass; |
| import org.ops4j.pax.tinybundles.core.TinyBundles; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.FrameworkEvent; |
| import org.osgi.framework.FrameworkListener; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceEvent; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.framework.Version; |
| import org.osgi.framework.namespace.IdentityNamespace; |
| import org.osgi.framework.startlevel.BundleStartLevel; |
| import org.osgi.framework.startlevel.FrameworkStartLevel; |
| import org.osgi.framework.wiring.BundleRevision; |
| import org.osgi.framework.wiring.FrameworkWiring; |
| import org.osgi.resource.Capability; |
| import org.osgi.resource.Resource; |
| import org.osgi.service.repository.Repository; |
| import org.osgi.service.repository.RepositoryContent; |
| import org.osgi.service.subsystem.Subsystem; |
| import org.osgi.service.subsystem.Subsystem.State; |
| import org.osgi.service.subsystem.SubsystemConstants; |
| |
| @RunWith(PaxExam.class) |
| @ExamReactorStrategy(PerClass.class) |
| public abstract class SubsystemTest extends AbstractIntegrationTest { |
| private static final String SUBSYSTEM_CORE_NAME = "org.apache.aries.subsystem.core"; |
| protected static boolean createdApplications = false; |
| boolean installModeler = true; |
| boolean installConfigAdmin = false; |
| |
| public SubsystemTest() { |
| } |
| |
| public SubsystemTest(boolean installModeller) { |
| this.installModeler = installModeller; |
| } |
| |
| public Option baseOptions() { |
| String localRepo = getLocalRepo(); |
| return composite( |
| junitBundles(), |
| // this is how you set the default log level when using pax |
| // logging (logProfile) |
| systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"), |
| when(localRepo != null).useOptions(vmOption("-Dorg.ops4j.pax.url.mvn.localRepository=" + localRepo)) |
| ); |
| } |
| |
| @Configuration |
| public Option[] configuration() throws Exception { |
| new File("target").mkdirs(); |
| init(); |
| return new Option[] { |
| baseOptions(), |
| systemProperty("org.osgi.framework.bsnversion").value("multiple"), |
| // Bundles |
| mavenBundle("org.apache.aries", "org.apache.aries.util").versionAsInProject(), |
| mavenBundle("org.apache.aries.application", "org.apache.aries.application.utils").versionAsInProject(), |
| mavenBundle("org.apache.aries.application", "org.apache.aries.application.api").versionAsInProject(), |
| when(installModeler).useOptions(modelerBundles()), |
| when(installConfigAdmin).useOptions( |
| mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject()), |
| mavenBundle("org.apache.aries.subsystem", "org.apache.aries.subsystem.api").versionAsInProject(), |
| mavenBundle("org.apache.aries.subsystem", SUBSYSTEM_CORE_NAME).versionAsInProject(), |
| streamBundle(createCoreFragment()).noStart(), |
| mavenBundle("org.apache.aries.subsystem", "org.apache.aries.subsystem.itest.interfaces").versionAsInProject(), |
| mavenBundle("org.apache.aries.testsupport", "org.apache.aries.testsupport.unit").versionAsInProject(), |
| mavenBundle("org.apache.felix", "org.apache.felix.resolver").versionAsInProject(), |
| mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.coordinator").version("1.1.0.v20120522-1841"), |
| mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.event").versionAsInProject(), |
| mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.region").version("1.1.0.v20120522-1841"), |
| mavenBundle("org.osgi", "org.osgi.enterprise").versionAsInProject(), |
| mavenBundle("org.easymock", "easymock").versionAsInProject(), |
| mavenBundle("org.ops4j.pax.logging", "pax-logging-api").versionAsInProject(), |
| mavenBundle("org.ops4j.pax.logging", "pax-logging-service").versionAsInProject(), |
| // org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=7777"), |
| }; |
| } |
| |
| protected void init() throws Exception { |
| |
| } |
| |
| private Option modelerBundles() { |
| return CoreOptions.composite( |
| mavenBundle("org.apache.aries.application", "org.apache.aries.application.modeller").versionAsInProject(), |
| mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint").versionAsInProject(), |
| mavenBundle("org.apache.aries.proxy", "org.apache.aries.proxy").versionAsInProject()); |
| } |
| |
| /** |
| * The itests need private packages from the core subsystems bundle. |
| * So this fragment exports them. |
| * @return stream containing the fragment |
| */ |
| private InputStream createCoreFragment() { |
| return TinyBundles.bundle() |
| .set("Bundle-SymbolicName", SUBSYSTEM_CORE_NAME + ".fragment") |
| .set("Export-Package", "org.apache.aries.subsystem.core.internal,org.apache.aries.subsystem.core.archive") |
| .set("Fragment-Host", SUBSYSTEM_CORE_NAME) |
| .build(); |
| } |
| |
| protected final SubsystemEventHandler subsystemEvents = new SubsystemEventHandler(); |
| |
| @SuppressWarnings("rawtypes") |
| protected Collection<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>(); |
| |
| @Before |
| public void setUp() throws Exception { |
| if (!createdApplications) { |
| createApplications(); |
| createdApplications = true; |
| } |
| bundleContext.getBundle(0).getBundleContext().addServiceListener(subsystemEvents, '(' + Constants.OBJECTCLASS + '=' + Subsystem.class.getName() + ')'); |
| } |
| |
| protected void createApplications() throws Exception { |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @After |
| public void tearDown() throws Exception |
| { |
| bundleContext.removeServiceListener(subsystemEvents); |
| for (ServiceRegistration registration : serviceRegistrations) |
| Utils.unregisterQuietly(registration); |
| serviceRegistrations.clear(); |
| } |
| |
| protected RichBundleContext context(Subsystem subsystem) { |
| return new RichBundleContext(subsystem.getBundleContext()); |
| } |
| |
| protected void assertEmptySubsystem(Subsystem subsystem) { |
| assertSymbolicName("org.apache.aries.subsystem.itests.subsystem.empty", subsystem); |
| assertVersion("0", subsystem); |
| assertType(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, subsystem); |
| } |
| |
| protected void assertBundleState(int state, String symbolicName, Subsystem subsystem) { |
| Bundle bundle = context(subsystem).getBundleByName(symbolicName); |
| assertNotNull("Bundle not found: " + symbolicName, bundle); |
| assertBundleState(bundle, state); |
| } |
| |
| protected void assertBundleState(Bundle bundle, int state) { |
| assertTrue("Wrong state: " + bundle + " [expected " + state + " but was " + bundle.getState() + "]", (bundle.getState() & state) != 0); |
| } |
| |
| protected Subsystem assertChild(Subsystem parent, String symbolicName) { |
| return assertChild(parent, symbolicName, null, null); |
| } |
| |
| protected Subsystem assertChild(Subsystem parent, String symbolicName, Version version) { |
| return assertChild(parent, symbolicName, version, null); |
| } |
| |
| protected Subsystem assertChild(Subsystem parent, String symbolicName, Version version, String type) { |
| Subsystem result = getChild(parent, symbolicName, version, type); |
| assertNotNull("Child does not exist: " + symbolicName, result); |
| return result; |
| } |
| |
| protected void assertChild(Subsystem parent, Subsystem child) { |
| Collection<Subsystem> children = new ArrayList<Subsystem>(1); |
| children.add(child); |
| assertChildren(parent, children); |
| } |
| |
| protected void assertChildren(int size, Subsystem subsystem) { |
| assertEquals("Wrong number of children", size, subsystem.getChildren().size()); |
| } |
| |
| protected void assertChildren(Subsystem parent, Collection<Subsystem> children) { |
| assertTrue("Parent did not contain all children", parent.getChildren().containsAll(children)); |
| } |
| |
| protected void assertClassLoadable(String clazz, Bundle bundle) { |
| try { |
| bundle.loadClass(clazz); |
| } |
| catch (Exception e) { |
| e.printStackTrace(); |
| fail("Class " + clazz + " from bundle " + bundle + " should be loadable"); |
| } |
| } |
| |
| protected void assertConstituent(Subsystem subsystem, String symbolicName) { |
| assertConstituent(subsystem, symbolicName, Version.emptyVersion); |
| } |
| |
| protected void assertConstituent(Subsystem subsystem, String symbolicName, Version version) { |
| assertConstituent(subsystem, symbolicName, version, IdentityNamespace.TYPE_BUNDLE); |
| } |
| |
| protected void assertContituent(Subsystem subsystem, String symbolicName, String type) { |
| assertConstituent(subsystem, symbolicName, Version.emptyVersion, type); |
| } |
| |
| protected Resource assertConstituent(Subsystem subsystem, String symbolicName, Version version, String type) { |
| Resource constituent = getConstituent(subsystem, symbolicName, version, type); |
| assertNotNull("Constituent not found: " + symbolicName + ';' + version + ';' + type, constituent); |
| return constituent; |
| } |
| |
| protected void assertConstituents(int size, Subsystem subsystem) { |
| assertEquals("Wrong number of constituents", size, subsystem.getConstituents().size()); |
| } |
| |
| protected void assertEvent(Subsystem subsystem, Subsystem.State state) throws InterruptedException { |
| assertEvent(subsystem, state, 0); |
| } |
| |
| protected void assertEvent(Subsystem subsystem, Subsystem.State state, long timeout) throws InterruptedException { |
| assertEvent(subsystem, state, subsystemEvents.poll(subsystem.getSubsystemId(), timeout)); |
| } |
| protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemEventHandler.ServiceEventInfo event) { |
| if (State.INSTALLING.equals(state)) |
| assertEvent(subsystem, state, event, ServiceEvent.REGISTERED); |
| else |
| assertEvent(subsystem, state, event, ServiceEvent.MODIFIED); |
| } |
| |
| protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemEventHandler.ServiceEventInfo event, int type) { |
| // TODO Could accept a ServiceRegistration as an argument and verify it against the one in the event. |
| assertNotNull("No event", event); |
| assertEquals("Wrong ID", subsystem.getSubsystemId(), event.getId()); |
| assertEquals("Wrong symbolic name", subsystem.getSymbolicName(), event.getSymbolicName()); |
| assertEquals("Wrong version", subsystem.getVersion(), event.getVersion()); |
| assertEquals("Wrong type", subsystem.getType(), event.getType()); |
| assertEquals("Wrong state", state, event.getState()); |
| assertEquals("Wrong event type", type, event.getEventType()); |
| } |
| |
| protected String assertHeaderExists(Subsystem subsystem, String name) { |
| String header = subsystem.getSubsystemHeaders(null).get(name); |
| assertNotNull("Missing header: " + name, header); |
| return header; |
| } |
| |
| protected void assertId(Subsystem subsystem) { |
| assertId(subsystem.getSubsystemId()); |
| } |
| |
| protected void assertId(Long id) { |
| assertTrue("Subsystem ID was not a positive integer: " + id, id > 0); |
| } |
| |
| protected void assertLastId(long id) throws Exception { |
| Subsystem root = getRootSubsystem(); |
| Field lastId = SubsystemIdentifier.class.getDeclaredField("lastId"); |
| lastId.setAccessible(true); |
| assertEquals("Wrong lastId", id, lastId.getLong(root)); |
| } |
| |
| protected void resetLastId() throws Exception { |
| Field lastId = SubsystemIdentifier.class.getDeclaredField("lastId"); |
| lastId.setAccessible(true); |
| lastId.setInt(SubsystemIdentifier.class, 0); |
| } |
| |
| protected void assertLocation(String expected, String actual) { |
| assertTrue("Wrong location: " + actual, actual.indexOf(expected) != -1); |
| } |
| |
| protected void assertLocation(String expected, Subsystem subsystem) { |
| assertLocation(expected, subsystem.getLocation()); |
| } |
| |
| protected void assertNotChild(Subsystem parent, Subsystem child) { |
| assertFalse("Parent contained child", parent.getChildren().contains(child)); |
| } |
| |
| protected void assertNotConstituent(Subsystem subsystem, String symbolicName) { |
| assertNotConstituent(subsystem, symbolicName, Version.emptyVersion, IdentityNamespace.TYPE_BUNDLE); |
| } |
| |
| protected void assertNotConstituent(Subsystem subsystem, String symbolicName, Version version, String type) { |
| Resource constituent = getConstituent(subsystem, symbolicName, version, type); |
| assertNull("Constituent found: " + symbolicName + ';' + version + ';' + type, constituent); |
| } |
| |
| protected void assertParent(Subsystem expected, Subsystem subsystem) { |
| for (Subsystem parent : subsystem.getParents()) { |
| if (parent.equals(expected)) |
| return; |
| |
| } |
| fail("Parent did not exist: " + expected.getSymbolicName()); |
| } |
| |
| protected void assertProvisionPolicy(Subsystem subsystem, boolean acceptsDependencies) { |
| String headerStr = subsystem.getSubsystemHeaders(null).get(SubsystemConstants.SUBSYSTEM_TYPE); |
| assertNotNull("Missing subsystem type header", headerStr); |
| SubsystemTypeHeader header = new SubsystemTypeHeader(headerStr); |
| ProvisionPolicyDirective directive = header.getProvisionPolicyDirective(); |
| if (acceptsDependencies) |
| assertTrue("Subsystem does not accept dependencies", directive.isAcceptDependencies()); |
| else |
| assertTrue("Subsystem accepts dependencies", directive.isRejectDependencies()); |
| } |
| |
| protected void assertRefresh(Collection<Bundle> bundles) throws InterruptedException { |
| FrameworkWiring wiring = getSystemBundleAsFrameworkWiring(); |
| final AtomicBoolean refreshed = new AtomicBoolean(false); |
| wiring.refreshBundles(bundles, new FrameworkListener[]{ new FrameworkListener() { |
| @Override |
| public void frameworkEvent(FrameworkEvent event) { |
| if (FrameworkEvent.PACKAGES_REFRESHED == event.getType()) { |
| synchronized (refreshed) { |
| refreshed.set(true); |
| refreshed.notify(); |
| } |
| } |
| } |
| }}); |
| synchronized (refreshed) { |
| refreshed.wait(5000); |
| } |
| assertTrue("Bundles not refreshed", refreshed.get()); |
| } |
| |
| protected void assertRefreshAndResolve(Collection<Bundle> bundles) throws InterruptedException { |
| assertRefresh(bundles); |
| assertResolve(bundles); |
| } |
| |
| protected void assertRegionContextBundle(Subsystem s) { |
| Bundle b = getRegionContextBundle(s); |
| assertEquals("Not active", Bundle.ACTIVE, b.getState()); |
| assertEquals("Wrong location", s.getLocation() + '/' + s.getSubsystemId(), b.getLocation()); |
| assertEquals("Wrong symbolic name", "org.osgi.service.subsystem.region.context." + s.getSubsystemId(), b.getSymbolicName()); |
| assertEquals("Wrong version", Version.parseVersion("1.0.0"), b.getVersion()); |
| assertConstituent(s, "org.osgi.service.subsystem.region.context." + s.getSubsystemId(), Version.parseVersion("1.0.0"), IdentityNamespace.TYPE_BUNDLE); |
| } |
| |
| protected void assertResolve(Collection<Bundle> bundles) { |
| FrameworkWiring wiring = getSystemBundleAsFrameworkWiring(); |
| assertTrue("Bundles not resolved", wiring.resolveBundles(bundles)); |
| } |
| |
| protected void assertServiceEventsInstall(Subsystem subsystem) throws InterruptedException { |
| assertEvent(subsystem, Subsystem.State.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.INSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| } |
| |
| protected void assertServiceEventsResolve(Subsystem subsystem) throws InterruptedException { |
| assertEvent(subsystem, Subsystem.State.RESOLVING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertServiceEventResolved(subsystem, ServiceEvent.MODIFIED); |
| } |
| |
| protected void assertServiceEventsStart(Subsystem subsystem) throws InterruptedException { |
| assertEvent(subsystem, Subsystem.State.STARTING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.ACTIVE, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| } |
| |
| protected void assertServiceEventsStop(Subsystem subsystem) throws InterruptedException { |
| assertEvent(subsystem, Subsystem.State.STOPPING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertServiceEventResolved(subsystem, ServiceEvent.MODIFIED); |
| // Don't forget about the unregistering event, which will have the same state as before. |
| assertServiceEventResolved(subsystem, ServiceEvent.UNREGISTERING); |
| } |
| |
| protected void assertServiceEventResolved(Subsystem subsystem, int type) throws InterruptedException { |
| assertEvent(subsystem, Subsystem.State.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000), type); |
| } |
| |
| protected void assertStartLevel(Bundle bundle, int expected) { |
| assertNotNull("Bundle is null", bundle); |
| assertEquals("Wrong start level", expected, bundle.adapt(BundleStartLevel.class).getStartLevel()); |
| } |
| |
| protected void assertState(State expected, State actual) { |
| assertState(EnumSet.of(expected), actual); |
| } |
| |
| protected void assertState(EnumSet<State> expected, State actual) { |
| assertTrue("Wrong state: expected=" + expected + ", actual=" + actual, expected.contains(actual)); |
| } |
| |
| protected void assertState(State expected, Subsystem subsystem) { |
| assertState(expected, subsystem.getState()); |
| } |
| |
| protected void assertState(EnumSet<State> expected, Subsystem subsystem) { |
| assertState(expected, subsystem.getState()); |
| } |
| |
| protected Subsystem assertSubsystemLifeCycle(File file) throws Exception { |
| Subsystem rootSubsystem = context().getService(Subsystem.class); |
| assertNotNull("Root subsystem was null", rootSubsystem); |
| Subsystem subsystem = rootSubsystem.install(file.toURI().toURL().toExternalForm()); |
| assertNotNull("The subsystem was null", subsystem); |
| assertState(EnumSet.of(State.INSTALLING, State.INSTALLED), subsystem.getState()); |
| assertEvent(subsystem, Subsystem.State.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.INSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertChild(rootSubsystem, subsystem); |
| subsystem.start(); |
| assertState(EnumSet.of(State.RESOLVING, State.RESOLVED, State.STARTING, State.ACTIVE), subsystem.getState()); |
| assertEvent(subsystem, Subsystem.State.RESOLVING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.STARTING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.ACTIVE, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| subsystem.stop(); |
| assertState(EnumSet.of(State.STOPPING, State.RESOLVED), subsystem.getState()); |
| assertEvent(subsystem, Subsystem.State.STOPPING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| subsystem.uninstall(); |
| assertState(EnumSet.of(State.UNINSTALLING, State.UNINSTALLED), subsystem.getState()); |
| assertEvent(subsystem, Subsystem.State.UNINSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertEvent(subsystem, Subsystem.State.UNINSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); |
| assertNotChild(rootSubsystem, subsystem); |
| return subsystem; |
| } |
| |
| protected void assertSubsystemNotNull(Subsystem subsystem) { |
| assertNotNull("Subsystem was null", subsystem); |
| } |
| |
| protected void assertSymbolicName(String expected, Subsystem subsystem) { |
| assertSymbolicName(expected, subsystem.getSymbolicName()); |
| } |
| |
| protected void assertSymbolicName(String expected, String actual) { |
| assertEquals("Wrong symbolic name", expected, actual); |
| } |
| |
| protected void assertType(String expected, Subsystem subsystem) { |
| assertEquals("Wrong type", expected, subsystem.getType()); |
| } |
| |
| protected void assertVersion(String expected, Subsystem subsystem) { |
| assertVersion(Version.parseVersion(expected), subsystem); |
| } |
| |
| protected void assertVersion(Version expected, Subsystem subsystem) { |
| assertVersion(expected, subsystem.getVersion()); |
| } |
| |
| protected void assertVersion(Version expected, Version actual) { |
| assertEquals("Wrong version", expected, actual); |
| } |
| |
| protected Header version(String version) { |
| return new Header(Constants.BUNDLE_VERSION, version); |
| } |
| |
| protected Header name(String name) { |
| return new Header(Constants.BUNDLE_SYMBOLICNAME, name); |
| } |
| |
| protected Header exportPackage(String exportPackage) { |
| return new Header(Constants.EXPORT_PACKAGE, exportPackage); |
| } |
| |
| protected Header importPackage(String importPackage) { |
| return new Header(Constants.IMPORT_PACKAGE, importPackage); |
| } |
| |
| protected Header requireBundle(String bundleName) { |
| return new Header(Constants.REQUIRE_BUNDLE, bundleName); |
| } |
| |
| protected Header requireCapability(String capability) { |
| return new Header(Constants.REQUIRE_CAPABILITY, capability); |
| } |
| |
| protected Header provideCapability(String capability) { |
| return new Header(Constants.PROVIDE_CAPABILITY, capability); |
| } |
| protected static void createBundle(Header... headers) throws IOException { |
| createBundle(Collections.<String> emptyList(), headers); |
| } |
| |
| protected static void createBundle(List<String> emptyFiles, Header... headers) throws IOException { |
| HashMap<String, String> headerMap = new HashMap<String, String>(); |
| for (Header header : headers) { |
| headerMap.put(header.key, header.value); |
| } |
| createBundle(emptyFiles, headerMap); |
| } |
| |
| private static void createBundle(List<String> emptyFiles, Map<String, String> headers) throws IOException |
| { |
| String symbolicName = headers.get(Constants.BUNDLE_SYMBOLICNAME); |
| JarFixture bundle = ArchiveFixture.newJar(); |
| ManifestFixture manifest = bundle.manifest(); |
| for (Entry<String, String> header : headers.entrySet()) { |
| manifest.attribute(header.getKey(), header.getValue()); |
| } |
| for (String path : emptyFiles) { |
| bundle.file(path).end(); |
| } |
| write(symbolicName, bundle); |
| } |
| |
| protected static void createBlueprintBundle(String symbolicName, String blueprintXml) |
| throws IOException { |
| write(symbolicName, |
| ArchiveFixture.newJar().manifest().symbolicName(symbolicName) |
| .end().file("OSGI-INF/blueprint/blueprint.xml", blueprintXml)); |
| } |
| |
| private RepositoryContent createBundleRepositoryContent(String file) throws Exception { |
| return createBundleRepositoryContent(new File(file)); |
| } |
| |
| private RepositoryContent createBundleRepositoryContent(File file) throws Exception { |
| return new BundleResource(FileSystem.getFSRoot(file)); |
| } |
| |
| protected static void createManifest(String name, Map<String, String> headers) throws IOException { |
| ManifestFixture manifest = ArchiveFixture.newJar().manifest(); |
| for (Entry<String, String> header : headers.entrySet()) { |
| manifest.attribute(header.getKey(), header.getValue()); |
| } |
| write(name, manifest); |
| } |
| |
| protected static void createSubsystem(String name, String...contents) throws IOException { |
| File manifest = new File(name + ".mf"); |
| ZipFixture fixture = ArchiveFixture.newZip(); |
| if (manifest.exists()) |
| // The following input stream is closed by ArchiveFixture.copy. |
| fixture.binary("OSGI-INF/SUBSYSTEM.MF", new FileInputStream(name + ".mf")); |
| if (contents != null) { |
| for (String content : contents) { |
| // The following input stream is closed by ArchiveFixture.copy. |
| fixture.binary(content, new FileInputStream(content)); |
| } |
| } |
| write(name, fixture); |
| } |
| |
| protected Subsystem findSubsystemService(long id) throws InvalidSyntaxException { |
| String filter = "(" + SubsystemConstants.SUBSYSTEM_ID_PROPERTY + "=" + id + ")"; |
| return context().getService(Subsystem.class, filter, 5000); |
| } |
| |
| protected Subsystem getChild(Subsystem parent, String symbolicName) { |
| return getChild(parent, symbolicName, null, null); |
| } |
| |
| protected Subsystem getChild(Subsystem parent, String symbolicName, Version version) { |
| return getChild(parent, symbolicName, version, null); |
| } |
| |
| protected Subsystem getChild(Subsystem parent, String symbolicName, Version version, String type) { |
| for (Subsystem child : parent.getChildren()) { |
| if (symbolicName.equals(child.getSymbolicName())) { |
| if (version == null) |
| version = Version.emptyVersion; |
| if (version.equals(child.getVersion())) { |
| if (type == null) |
| type = SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION; |
| if (type.equals(child.getType())) { |
| return child; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static Object getIdentityAttribute(Resource resource, String name) { |
| List<Capability> capabilities = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE); |
| Capability capability = capabilities.get(0); |
| return capability.getAttributes().get(name); |
| } |
| |
| public static String getSymbolicNameAttribute(Resource resource) { |
| return (String)getIdentityAttribute(resource, IdentityNamespace.IDENTITY_NAMESPACE); |
| } |
| |
| public static Version getVersionAttribute(Resource resource) { |
| Version result = (Version)getIdentityAttribute(resource, IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE); |
| if (result == null) |
| result = Version.emptyVersion; |
| return result; |
| } |
| |
| public static String getTypeAttribute(Resource resource) { |
| String result = (String)getIdentityAttribute(resource, IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE); |
| if (result == null) |
| result = TypeAttribute.DEFAULT_VALUE; |
| return result; |
| } |
| |
| protected Resource getConstituent(Subsystem subsystem, String symbolicName, Version version, String type) { |
| for (Resource resource : subsystem.getConstituents()) { |
| if (symbolicName.equals(getSymbolicNameAttribute(resource))) { |
| if (version == null) |
| version = Version.emptyVersion; |
| if (version.equals(getVersionAttribute(resource))) { |
| if (type == null) |
| type = IdentityNamespace.TYPE_BUNDLE; |
| if (type.equals(getTypeAttribute(resource))) { |
| return resource; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| protected AriesSubsystem getConstituentAsAriesSubsystem(Subsystem subsystem, String symbolicName, Version version, String type) { |
| Resource resource = getConstituent(subsystem, symbolicName, version, type); |
| return (AriesSubsystem)resource; |
| } |
| |
| protected Bundle getConstituentAsBundle(Subsystem subsystem, String symbolicName, Version version, String type) { |
| return getConstituentAsBundleRevision(subsystem, symbolicName, version, type).getBundle(); |
| } |
| |
| protected BundleRevision getConstituentAsBundleRevision(Subsystem subsystem, String symbolicName, Version version, String type) { |
| Resource resource = getConstituent(subsystem, symbolicName, version, type); |
| return (BundleRevision)resource; |
| } |
| |
| protected Subsystem getConstituentAsSubsystem(Subsystem subsystem, String symbolicName, Version version, String type) { |
| Resource resource = getConstituent(subsystem, symbolicName, version, type); |
| return (Subsystem)resource; |
| } |
| |
| protected Region getRegion(Subsystem subsystem) { |
| RegionDigraph digraph = context().getService(RegionDigraph.class); |
| String name = getRegionName(subsystem); |
| Region region = digraph.getRegion(name); |
| assertNotNull("Region not found: " + name, region); |
| return region; |
| } |
| |
| protected Bundle getRegionContextBundle(Subsystem subsystem) { |
| BundleContext bc = subsystem.getBundleContext(); |
| assertNotNull("No region context bundle", bc); |
| return bc.getBundle(); |
| } |
| |
| protected String getRegionName(Subsystem subsystem) { |
| if (subsystem.getSubsystemId() == 0) |
| return "org.eclipse.equinox.region.kernel"; |
| return subsystem.getSymbolicName() + ';' + subsystem.getVersion() + ';' + subsystem.getType() + ';' + subsystem.getSubsystemId(); |
| } |
| |
| protected AriesSubsystem getRootAriesSubsystem() { |
| return context().getService(AriesSubsystem.class); |
| } |
| |
| protected Subsystem getRootSubsystem() { |
| return context().getService(Subsystem.class, "(subsystem.id=0)"); |
| } |
| |
| protected Subsystem getRootSubsystemInState(Subsystem.State state, long timeout) throws InterruptedException { |
| Subsystem root = getRootSubsystem(); |
| long now = System.currentTimeMillis(); |
| long then = now + timeout; |
| while (!root.getState().equals(state) && System.currentTimeMillis() < then) |
| Thread.sleep(100); |
| if (!root.getState().equals(state)) |
| fail("Root subsystem never achieved state: " + state); |
| return root; |
| } |
| |
| protected Bundle getSystemBundle() { |
| return bundleContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION); |
| } |
| |
| protected FrameworkStartLevel getSystemBundleAsFrameworkStartLevel() { |
| return getSystemBundle().adapt(FrameworkStartLevel.class); |
| } |
| |
| protected FrameworkWiring getSystemBundleAsFrameworkWiring() { |
| return getSystemBundle().adapt(FrameworkWiring.class); |
| } |
| |
| protected Bundle getSubsystemCoreBundle() { |
| return context().getBundleByName(SUBSYSTEM_CORE_NAME); |
| } |
| |
| protected Bundle installBundleFromFile(String fileName) throws FileNotFoundException, BundleException { |
| return installBundleFromFile(new File(fileName), getRootSubsystem()); |
| } |
| |
| protected Bundle installBundleFromFile(String fileName, Subsystem subsystem) throws FileNotFoundException, BundleException { |
| return installBundleFromFile(new File(fileName), subsystem); |
| } |
| |
| private Bundle installBundleFromFile(File file, Subsystem subsystem) throws FileNotFoundException, BundleException { |
| Bundle bundle = installBundleFromFile(file, subsystem.getBundleContext()); |
| assertBundleState(Bundle.INSTALLED|Bundle.RESOLVED, bundle.getSymbolicName(), subsystem); |
| return bundle; |
| } |
| |
| private Bundle installBundleFromFile(File file, BundleContext bundleContext) throws FileNotFoundException, BundleException { |
| // The following input stream is closed by the bundle context. |
| return bundleContext.installBundle(file.toURI().toString(), new FileInputStream(file)); |
| } |
| |
| protected Subsystem installSubsystemFromFile(Subsystem parent, String fileName) throws Exception { |
| return installSubsystemFromFile(parent, new File(fileName)); |
| } |
| |
| protected Subsystem installSubsystemFromFile(String fileName) throws Exception { |
| return installSubsystemFromFile(new File(fileName)); |
| } |
| |
| protected Subsystem installSubsystemFromFile(Subsystem parent, File file) throws Exception { |
| return installSubsystem(parent, file.toURI().toURL().toExternalForm()); |
| } |
| |
| private Subsystem installSubsystemFromFile(File file) throws Exception { |
| return installSubsystem(getRootSubsystem(), file.toURI().toURL().toExternalForm()); |
| } |
| |
| protected Subsystem installSubsystem(String location) throws Exception { |
| return installSubsystem(getRootSubsystem(), location); |
| } |
| |
| protected Subsystem installSubsystem(String location, InputStream content) throws Exception { |
| return installSubsystem(getRootSubsystem(), location, content); |
| } |
| |
| protected Subsystem installSubsystem(Subsystem parent, String location) throws Exception { |
| // The following input stream is closed by Subsystem.install. |
| return installSubsystem(parent, location, new URL(location).openStream()); |
| } |
| |
| protected Subsystem installSubsystem(Subsystem parent, String location, InputStream content) throws Exception { |
| subsystemEvents.clear(); |
| Subsystem subsystem = parent.install(location, content); |
| assertSubsystemNotNull(subsystem); |
| assertEvent(subsystem, State.INSTALLING, 5000); |
| assertEvent(subsystem, State.INSTALLED, 5000); |
| assertChild(parent, subsystem); |
| assertLocation(location, subsystem); |
| assertParent(parent, subsystem); |
| assertState(State.INSTALLED, subsystem); |
| assertLocation(location, subsystem); |
| assertId(subsystem); |
| // TODO This does not take into account nested directories. |
| // assertDirectory(subsystem); |
| return subsystem; |
| } |
| |
| protected void registerRepositoryService(Repository repository) { |
| serviceRegistrations.add(bundleContext.registerService( |
| Repository.class, repository, null)); |
| } |
| |
| protected void registerRepositoryService(Resource...resources) { |
| TestRepository.Builder builder = new TestRepository.Builder(); |
| for (Resource resource : resources) { |
| builder.resource(resource); |
| } |
| registerRepositoryService(builder.build()); |
| } |
| |
| protected void registerRepositoryService(String...files) throws Exception { |
| Resource[] resources = new Resource[files.length]; |
| int i = 0; |
| for (String file : files) { |
| resources[i++] = (Resource)createBundleRepositoryContent(file); |
| } |
| registerRepositoryService(resources); |
| } |
| |
| protected void restartSubsystemsImplBundle() throws BundleException { |
| Bundle b = getSubsystemCoreBundle(); |
| b.stop(); |
| b.start(); |
| } |
| |
| protected void startBundle(Bundle bundle) throws BundleException { |
| startBundle(bundle, getRootSubsystem()); |
| } |
| |
| protected void startBundle(Bundle bundle, Subsystem subsystem) throws BundleException { |
| bundle.start(); |
| assertBundleState(Bundle.ACTIVE, bundle.getSymbolicName(), subsystem); |
| } |
| |
| protected void startSubsystem(Subsystem subsystem) throws Exception { |
| startSubsystemFromInstalled(subsystem); |
| } |
| |
| protected void startSubsystemFromInstalled(Subsystem subsystem) throws InterruptedException { |
| assertState(State.INSTALLED, subsystem); |
| subsystemEvents.clear(); |
| subsystem.start(); |
| assertEvent(subsystem, State.RESOLVING, 5000); |
| assertEvent(subsystem, State.RESOLVED, 5000); |
| assertEvent(subsystem, State.STARTING, 5000); |
| assertEvent(subsystem, State.ACTIVE, 5000); |
| assertState(State.ACTIVE, subsystem); |
| } |
| |
| protected void startSubsystemFromResolved(Subsystem subsystem) throws InterruptedException { |
| assertState(State.RESOLVED, subsystem); |
| subsystemEvents.clear(); |
| subsystem.start(); |
| assertEvent(subsystem, State.STARTING, 5000); |
| assertEvent(subsystem, State.ACTIVE, 5000); |
| assertState(State.ACTIVE, subsystem); |
| } |
| |
| protected void stopAndUninstallSubsystemSilently(Subsystem subsystem) { |
| stopSubsystemSilently(subsystem); |
| uninstallSubsystemSilently(subsystem); |
| } |
| |
| protected void stopSubsystem(Subsystem subsystem) throws Exception { |
| assertState(State.ACTIVE, subsystem); |
| subsystemEvents.clear(); |
| subsystem.stop(); |
| assertEvent(subsystem, State.STOPPING, 5000); |
| assertEvent(subsystem, State.RESOLVED, 5000); |
| assertState(State.RESOLVED, subsystem); |
| } |
| |
| protected void stopSubsystemSilently(Subsystem subsystem) { |
| try { |
| stopSubsystem(subsystem); |
| } |
| catch (Throwable t) { |
| t.printStackTrace(); |
| } |
| } |
| |
| protected void uninstallSilently(Bundle bundle) { |
| if (bundle == null) |
| return; |
| try { |
| bundle.uninstall(); |
| } |
| catch (Exception e) {} |
| } |
| |
| protected void uninstallSubsystem(Subsystem subsystem) throws Exception { |
| assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), subsystem); |
| subsystemEvents.clear(); |
| Collection<Subsystem> parents = subsystem.getParents(); |
| Bundle b = null; |
| Region region = null; |
| RegionDigraph digraph = context().getService(RegionDigraph.class); |
| if (subsystem.getType().equals(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION) |
| || subsystem.getType().equals(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)) { |
| b = getRegionContextBundle(subsystem); |
| region = digraph.getRegion(b); |
| } |
| State state = subsystem.getState(); |
| subsystem.uninstall(); |
| if (!EnumSet.of(State.INSTALL_FAILED, State.INSTALLED, State.INSTALLING).contains(state)) |
| assertEvent(subsystem, State.INSTALLED, 5000); |
| assertEvent(subsystem, State.UNINSTALLING, 5000); |
| assertEvent(subsystem, State.UNINSTALLED, 5000); |
| assertState(State.UNINSTALLED, subsystem); |
| for (Subsystem parent : parents) |
| assertNotChild(parent, subsystem); |
| // assertNotDirectory(subsystem); |
| if (subsystem.getType().equals(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION) |
| || subsystem.getType().equals(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)) { |
| assertEquals("Region context bundle not uninstalled", Bundle.UNINSTALLED, b.getState()); |
| assertNull("Region not removed", digraph.getRegion(region.getName())); |
| } |
| } |
| |
| protected void uninstallSubsystemSilently(Subsystem subsystem) { |
| if (subsystem == null) |
| return; |
| try { |
| uninstallSubsystem(subsystem); |
| } |
| catch (Throwable t) { |
| t.printStackTrace(); |
| } |
| } |
| |
| protected void writeToFile(InputStream is, String name) { |
| try { |
| FileOutputStream dest = new FileOutputStream(name); |
| StreamUtils.copyStream(is, dest, true); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| protected static void write(String file, ArchiveFixture.AbstractFixture fixture) throws IOException |
| { |
| write(new File(file), fixture); |
| } |
| |
| private static void write(File file, ArchiveFixture.AbstractFixture fixture) throws IOException { |
| FileOutputStream fos = new FileOutputStream(file); |
| try { |
| fixture.writeOut(fos); |
| } |
| finally { |
| fos.close(); |
| } |
| } |
| |
| static void createApplication(String name, String ... contents) throws Exception |
| { |
| ClassLoader cl = SubsystemTest.class.getClassLoader(); |
| ZipFixture feature = ArchiveFixture |
| .newZip() |
| .binary("OSGI-INF/SUBSYSTEM.MF", |
| // The following input stream is closed by ArchiveFixture.copy. |
| cl.getResourceAsStream(name + "/OSGI-INF/SUBSYSTEM.MF")); |
| for (String content : contents) { |
| try { |
| feature.binary(content, |
| // The following input stream is closed by ArchiveFixture.copy. |
| cl.getResourceAsStream(name + '/' + content)); |
| } |
| catch (Exception e) { |
| // The following input stream is closed by ArchiveFixture.copy. |
| feature.binary(content, new FileInputStream(new File(content))); |
| } |
| } |
| feature.end(); |
| FileOutputStream fos = new FileOutputStream(name + ".esa"); |
| try { |
| feature.writeOut(fos); |
| } finally { |
| Utils.closeQuietly(fos); |
| } |
| } |
| |
| protected static String normalizeBundleLocation(String location) { |
| if (location.startsWith("initial@")) |
| return location.substring(8); |
| return location; |
| } |
| |
| protected InputStream getResource(String path) { |
| InputStream is = this.getClass().getClassLoader().getResourceAsStream(path); |
| if (is == null) { |
| throw new IllegalArgumentException("No resource found at path " + path); |
| } |
| return is; |
| } |
| |
| } |