package org.apache.aries.subsystem.itests.defect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.apache.aries.subsystem.AriesSubsystem;
import org.apache.aries.subsystem.core.archive.AriesProvisionDependenciesDirective;
import org.apache.aries.subsystem.core.archive.SubsystemTypeHeader;
import org.apache.aries.subsystem.itests.SubsystemTest;
import org.apache.aries.subsystem.itests.util.BundleArchiveBuilder;
import org.apache.aries.subsystem.itests.util.SubsystemArchiveBuilder;
import org.apache.aries.subsystem.itests.util.TestCapability;
import org.apache.aries.subsystem.itests.util.TestRepository;
import org.apache.aries.subsystem.itests.util.TestRepositoryContent;
import org.apache.aries.subsystem.itests.util.TestRequirement;
import org.easymock.internal.matchers.Null;
import org.junit.Test;
import org.ops4j.pax.tinybundles.core.InnerClassStrategy;
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
import org.osgi.framework.hooks.resolver.ResolverHook;
import org.osgi.framework.hooks.resolver.ResolverHookFactory;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.service.repository.Repository;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.Subsystem.State;
import org.osgi.service.subsystem.SubsystemConstants;
import org.osgi.service.subsystem.SubsystemException;
/*
* https://issues.apache.org/jira/browse/ARIES-1383
*
* Provide option to disable the provisioning of dependencies at install time.
*
* For tests containing a numerical value in the name, see the description of
* ARIES-1383 for an explanation.
*/
public class Aries1383Test extends SubsystemTest {
private static final String SYMBOLICNAME_PREFIX = Aries1383Test.class.getSimpleName() + '.';
private static final String APPLICATION_A = SYMBOLICNAME_PREFIX + "application.a";
private static final String APPLICATION_B = SYMBOLICNAME_PREFIX + "application.b";
private static final String APPLICATION_DEPENDENCY_IN_ARCHIVE = SYMBOLICNAME_PREFIX + "application.dependency.in.archive";
private static final String APPLICATION_EMPTY = SYMBOLICNAME_PREFIX + "application.empty";
private static final String APPLICATION_INSTALL_FAILED = SYMBOLICNAME_PREFIX + "application.install.failed";
private static final String APPLICATION_INVALID_PROVISION_DEPENDENCIES = SYMBOLICNAME_PREFIX + "application.invalid.provision.dependency";
private static final String APPLICATION_MISSING_DEPENDENCY = SYMBOLICNAME_PREFIX + "application.missing.dependency";
private static final String APPLICATION_PROVISION_DEPENDENCIES_INSTALL = SYMBOLICNAME_PREFIX + "application.provision.dependencies.install";
private static final String APPLICATION_START_FAILURE = SYMBOLICNAME_PREFIX + "application.start.failure";
private static final String BUNDLE_A = SYMBOLICNAME_PREFIX + "bundle.a";
private static final String BUNDLE_B = SYMBOLICNAME_PREFIX + "bundle.b";
private static final String BUNDLE_C = SYMBOLICNAME_PREFIX + "bundle.c";
private static final String BUNDLE_D = SYMBOLICNAME_PREFIX + "bundle.d";
private static final String BUNDLE_INVALID_MANIFEST = SYMBOLICNAME_PREFIX + "bundle.invalid.manifest";
private static final String BUNDLE_START_FAILURE = SYMBOLICNAME_PREFIX + "bundle.start.failure";
private static final String ESA_EXTENSION = ".esa";
private static final String FEATURE_PROVISION_DEPENDENCIES_INSTALL = "feature.provision.dependencies.install";
private static final String FEATURE_PROVISION_DEPENDENCIES_RESOLVE = "feature.provision.dependencies.resolve";
private static final String JAR_EXTENSION = ".jar";
private static final String MANIFEST_VERSION = "1.0";
private static final String PACKAGE_A = SYMBOLICNAME_PREFIX + "a";
private static final String PACKAGE_B = SYMBOLICNAME_PREFIX + "b";
private static final String PACKAGE_C = SYMBOLICNAME_PREFIX + "c";
private static final String PACKAGE_D = SYMBOLICNAME_PREFIX + "d";
private static final String SUBSYSTEM_MANIFEST_FILE = "OSGI-INF/SUBSYSTEM.MF";
/*
* (1) A set of subsystems with interleaving content dependencies are able
* to be independently, simultaneously, and successfully installed and
* started.
*/
@Test
public void test1() throws Exception {
Subsystem root = getRootSubsystem();
final Subsystem c1 = installSubsystem(
root,
"c1",
new SubsystemArchiveBuilder()
.symbolicName("c1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.build(),
false
);
uninstallableSubsystems.add(c1);
c1.start();
stoppableSubsystems.add(c1);
@SuppressWarnings("unchecked")
Callable<Subsystem>[] installCallables = new Callable[] {
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
c1,
"a1",
new SubsystemArchiveBuilder()
.symbolicName("a1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b1")
.bundle(
"b1",
new BundleArchiveBuilder()
.symbolicName("b1")
.importPackage("b2")
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
c1,
"f1",
new SubsystemArchiveBuilder()
.symbolicName("f1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b2")
.bundle(
"b2",
new BundleArchiveBuilder()
.symbolicName("b2")
.exportPackage("b2")
.importPackage("b3")
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
c1,
"f2",
new SubsystemArchiveBuilder()
.symbolicName("f2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b4")
.bundle(
"b4",
new BundleArchiveBuilder()
.symbolicName("b4")
.exportPackage("b4")
.importPackage("b2")
.importPackage("b3")
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
c1,
"c2",
new SubsystemArchiveBuilder()
.symbolicName("c2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b3;version=\"[0,0]\"")
.exportPackage("b3")
.importPackage("b4")
.bundle(
"b3",
new BundleArchiveBuilder()
.symbolicName("b3")
.exportPackage("b3")
.importPackage("b4")
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
}
};
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<Subsystem>> installFutures = executor.invokeAll(Arrays.asList(installCallables));
final Subsystem a1 = installFutures.get(0).get();
assertConstituent(a1, "b1");
final Subsystem f1 = installFutures.get(1).get();
assertConstituent(f1, "b2");
final Subsystem f2 = installFutures.get(2).get();
assertConstituent(f2, "b4");
final Subsystem c2 = installFutures.get(3).get();
assertConstituent(c2, "b3");
@SuppressWarnings("unchecked")
Callable<Null>[] startCallables = new Callable[] {
new Callable<Null>() {
@Override
public Null call() throws Exception {
a1.start();
assertEvent(a1, State.INSTALLED, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.RESOLVING, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.RESOLVED, subsystemEvents.poll(a1.getSubsystemId(), 5000));
stoppableSubsystems.add(a1);
return null;
}
},
new Callable<Null>() {
@Override
public Null call() throws Exception {
f1.start();
assertEvent(f1, State.INSTALLED, subsystemEvents.poll(f1.getSubsystemId(), 5000));
assertEvent(f1, State.RESOLVING, subsystemEvents.poll(f1.getSubsystemId(), 5000));
assertEvent(f1, State.RESOLVED, subsystemEvents.poll(f1.getSubsystemId(), 5000));
stoppableSubsystems.add(f1);
return null;
}
},
new Callable<Null>() {
@Override
public Null call() throws Exception {
f2.start();
assertEvent(f2, State.INSTALLED, subsystemEvents.poll(f2.getSubsystemId(), 5000));
assertEvent(f2, State.RESOLVING, subsystemEvents.poll(f2.getSubsystemId(), 5000));
assertEvent(f2, State.RESOLVED, subsystemEvents.poll(f2.getSubsystemId(), 5000));
stoppableSubsystems.add(f2);
return null;
}
},
new Callable<Null>() {
@Override
public Null call() throws Exception {
c2.start();
assertEvent(c2, State.INSTALLED, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.RESOLVING, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.RESOLVED, subsystemEvents.poll(c2.getSubsystemId(), 5000));
stoppableSubsystems.add(c2);
return null;
}
}
};
List<Future<Null>> startFutures = executor.invokeAll(Arrays.asList(startCallables));
startFutures.get(0).get();
startFutures.get(1).get();
startFutures.get(2).get();
startFutures.get(3).get();
}
/*
* (2) Subsystem with apache-aries-provision-dependencies:=resolve is in the
* INSTALLING state after a successful installation.
*/
@Test
public void test2() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
try {
assertState(State.INSTALLING, subsystem);
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (3) Subsystem with apache-aries-provision-dependencies:=resolve is available
* as a service after a successful installation.
*/
@Test
public void test3() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
try {
assertReferences(
Subsystem.class,
"(&(subsystem.symbolicName="
+ APPLICATION_EMPTY
+ ")(subsystem.version=0.0.0)(subsystem.type="
+ SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ")(subsystem.state="
+ State.INSTALLING
+ "))",
1);
assertReferences(
AriesSubsystem.class,
"(&(subsystem.symbolicName="
+ APPLICATION_EMPTY
+ ")(subsystem.version=0.0.0)(subsystem.type="
+ SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ")(subsystem.state="
+ State.INSTALLING
+ "))",
1);
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (4) Subsystem with apache-aries-provision-dependencies:=resolve does not
* have its dependencies installed after a successful installation.
*/
@Test
public void test4() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_DEPENDENCY_IN_ARCHIVE, applicationDependencyInArchive(), false);
try {
assertConstituent(subsystem, BUNDLE_A);
assertNotConstituent(subsystem, BUNDLE_B);
assertNotConstituent(root, BUNDLE_B);
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (5) Subsystem with apache-aries-provision-dependencies:=resolve undergoes
* the following state transitions when starting: INSTALLING -> INSTALLED
* -> RESOLVING -> RESOLVED -> STARTING -> ACTIVE.
*/
@Test
public void test5() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem subsystem = root.install(
"application",
new SubsystemArchiveBuilder()
.header(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, "application")
.header(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.build()
);
try {
long id = subsystem.getSubsystemId();
assertEvent(subsystem, State.INSTALLING, subsystemEvents.poll(id, 5000));
assertNull(subsystemEvents.poll(id, 1));
subsystem.start();
try {
assertEvent(subsystem, State.INSTALLED, subsystemEvents.poll(id, 5000));
assertEvent(subsystem, State.RESOLVING, subsystemEvents.poll(id, 5000));
assertEvent(subsystem, State.RESOLVED, subsystemEvents.poll(id, 5000));
assertEvent(subsystem, State.STARTING, subsystemEvents.poll(id, 5000));
assertEvent(subsystem, State.ACTIVE, subsystemEvents.poll(id, 5000));
assertNull(subsystemEvents.poll(id, 1));
}
finally {
stopSubsystemSilently(subsystem);
}
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (6) Subsystem with apache-aries-provision-dependencies:=resolve has its
* dependencies installed after a successful start.
*/
@Test
public void test6() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = root.install(
"application",
new SubsystemArchiveBuilder()
.symbolicName("application")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("bundle1")
.bundle(
"bundle1",
new BundleArchiveBuilder()
.symbolicName("bundle1")
.exportPackage("a")
.importPackage("b")
.build())
.bundle(
"bundle2",
new BundleArchiveBuilder()
.symbolicName("bundle2")
.exportPackage("b")
.build())
.build()
);
try {
assertNotConstituent(root, "bundle2");
startSubsystem(subsystem, false);
try {
assertConstituent(root, "bundle2");
}
finally {
stopSubsystemSilently(subsystem);
}
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (7) Subsystem with apache-aries-provision-dependencies:=resolve is in the
* INSTALL_FAILED state after an unsuccessful installation.
*/
@Test
public void test7() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
try {
Subsystem subsystem = root.install(APPLICATION_INSTALL_FAILED, applicationInstallFailed());
uninstallSubsystemSilently(subsystem);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
long id = lastSubsystemId();
assertEvent(id, APPLICATION_INSTALL_FAILED, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertEvent(id, APPLICATION_INSTALL_FAILED, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALL_FAILED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_INSTALL_FAILED, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.UNINSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_INSTALL_FAILED, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.UNINSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
}
}
/*
* (8) Subsystem with apache-aries-provision-dependencies:=resolve is not
* available as a service after an unsuccessful installation.
*/
@Test
public void test8() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(root, APPLICATION_INSTALL_FAILED, applicationInstallFailed(), false);
uninstallSubsystemSilently(subsystem);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
assertEquals("Subsystem service should not exist", 0,
bundleContext.getServiceReferences(
Subsystem.class,
"(" + SubsystemConstants.SUBSYSTEM_ID_PROPERTY + "=" + lastSubsystemId() + ")"
).size());
}
}
/*
* (9) Subsystem with apache-aries-provision-dependencies:=resolve is in the
* INSTALLING state when dependencies cannot be provisioned after invoking
* the start method.
*/
@Test
public void test9() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_MISSING_DEPENDENCY, applicationMissingDependency(), false);
try {
startSubsystem(subsystem, false);
stopSubsystemSilently(subsystem);
fail("Subsystem should not have started");
}
catch (SubsystemException e) {
e.printStackTrace();
assertState(State.INSTALLING, subsystem);
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (10) Subsystem fails installation if the apache-aries-provision-dependencies
* directive has a value other than "install" or "resolve".
*/
@Test
public void test10() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(
root,
APPLICATION_INVALID_PROVISION_DEPENDENCIES,
applicationInvalidProvisionDependencies(),
false);
uninstallSubsystemSilently(subsystem);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
}
/*
* (11) Subsystem with apache-aries-provision-dependencies:=resolve undergoes
* the following state transitions when starting fails due to a runtime
* resolution failure: INSTALLING -> INSTALLED -> RESOLVING -> INSTALLED.
*/
@Test
public void test11() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem subsystem = root.install(APPLICATION_DEPENDENCY_IN_ARCHIVE, applicationDependencyInArchive());
ServiceRegistration<ResolverHookFactory> registration = bundleContext.registerService(
ResolverHookFactory.class,
new ResolverHookFactory() {
@Override
public ResolverHook begin(Collection<BundleRevision> triggers) {
return new ResolverHook() {
@Override
public void filterResolvable(Collection<BundleRevision> candidates) {
for (Iterator<BundleRevision> i = candidates.iterator(); i.hasNext();) {
BundleRevision revision = i.next();
if (revision.getSymbolicName().equals(BUNDLE_B)) {
i.remove();
}
}
}
@Override
public void filterSingletonCollisions(
BundleCapability singleton,
Collection<BundleCapability> collisionCandidates) {
// Nothing.
}
@Override
public void filterMatches(
BundleRequirement requirement,
Collection<BundleCapability> candidates) {
// Nothing.
}
@Override
public void end() {
// Nothing.
}
};
}
},
null
);
try {
subsystem.start();
stopSubsystemSilently(subsystem);
fail("Subsystem should not have started");
}
catch (SubsystemException e) {
e.printStackTrace();
long id = lastSubsystemId();
assertEvent(id, APPLICATION_DEPENDENCY_IN_ARCHIVE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertEvent(id, APPLICATION_DEPENDENCY_IN_ARCHIVE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_DEPENDENCY_IN_ARCHIVE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_DEPENDENCY_IN_ARCHIVE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
}
finally {
registration.unregister();
uninstallSubsystemSilently(subsystem);
}
}
/*
* (12) Subsystem with apache-aries-provision-dependencies:=resolve undergoes
* the following state transitions when starting fails due to a start
* failure: INSTALLING -> INSTALLED -> RESOLVING -> RESOLVED -> STARTING ->
* RESOLVED.
*/
@Test
public void test12() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem subsystem = root.install(APPLICATION_START_FAILURE, applicationStartFailure());
try {
subsystem.start();
stopSubsystemSilently(subsystem);
fail("Subsystem should not have started");
}
catch (SubsystemException e) {
e.printStackTrace();
long id = lastSubsystemId();
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.STARTING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_START_FAILURE, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
/*
* (13) The root subsystem has apache-aries-provision-dependencies:=install.
*/
@Test
public void test13() throws Exception {
Subsystem root = getRootSubsystem();
Map<String, String> headers = root.getSubsystemHeaders(null);
String headerStr = headers.get(SubsystemConstants.SUBSYSTEM_TYPE);
SubsystemTypeHeader header = new SubsystemTypeHeader(headerStr);
AriesProvisionDependenciesDirective directive = header.getAriesProvisionDependenciesDirective();
assertEquals(
"Wrong directive",
AriesProvisionDependenciesDirective.INSTALL,
directive);
}
/*
* (14) Subsystem with explicit apache-aries-provision-dependencies:=install
* works as before.
*/
@Test
public void test14() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_PROVISION_DEPENDENCIES_INSTALL,
applicationProvisionDependenciesInstall(), true);
try {
assertConstituent(subsystem, BUNDLE_A);
assertConstituent(root, BUNDLE_B);
startSubsystem(subsystem, true);
stopSubsystem(subsystem);
}
finally {
uninstallSubsystem(subsystem);
}
}
/*
* (15) Unscoped subsystem with a value of apache-aries-provision-dependencies
* that is different than the scoped parent fails installation.
*/
@Test
public void test15a() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(root, FEATURE_PROVISION_DEPENDENCIES_RESOLVE,
featureProvisionDependenciesResolve(), false);
uninstallSubsystemSilently(subsystem);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
}
/*
* (15) Unscoped subsystem with a value of apache-aries-provision-dependencies
* that is different than the scoped parent fails installation.
*/
@Test
public void test15b() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem application = installSubsystem(root, APPLICATION_PROVISION_DEPENDENCIES_INSTALL,
applicationProvisionDependenciesInstall(), true);
try {
Subsystem feature = installSubsystem(application, FEATURE_PROVISION_DEPENDENCIES_RESOLVE,
featureProvisionDependenciesResolve(), false);
uninstallSubsystemSilently(feature);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
finally {
uninstallSubsystemSilently(application);
}
}
/*
* (16) Unscoped subsystem with a value of apache-aries-provision-dependencies
* that is the same as the scoped parent installs successfully.
*/
@Test
public void test16a() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(
root,
FEATURE_PROVISION_DEPENDENCIES_INSTALL,
new SubsystemArchiveBuilder()
.symbolicName("application")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString())
.build(),
true);
uninstallSubsystemSilently(subsystem);
}
catch (SubsystemException e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
}
/*
* (16) Unscoped subsystem with a value of apache-aries-provision-dependencies
* that is the same as the scoped parent installs successfully.
*/
@Test
public void test16b() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem application = installSubsystem(
root,
"application",
new SubsystemArchiveBuilder()
.symbolicName("application")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString())
.build(),
true);
try {
Subsystem feature = installSubsystem(
application,
"feature",
new SubsystemArchiveBuilder()
.symbolicName("feature")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE + ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString())
.build(),
true);
uninstallSubsystemSilently(feature);
}
catch (SubsystemException e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
finally {
uninstallSubsystemSilently(application);
}
}
/*
* (16) Unscoped subsystem with a value of apache-aries-provision-dependencies
* that is the same as the scoped parent installs successfully.
*/
@Test
public void test16c() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(
root,
"application",
new SubsystemArchiveBuilder()
.symbolicName("application")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.subsystem(
"feature",
new SubsystemArchiveBuilder()
.symbolicName("feature")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.build())
.build(),
false);
uninstallSubsystemSilently(subsystem);
}
catch (SubsystemException e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
}
/*
* (17) Scoped subsystem with a value of apache-aries-provision-dependencies
* that is the same as the scoped parent behaves accordingly.
*/
@Test
public void test17() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem parent = root.install(APPLICATION_B, applicationB());
try {
long id = parent.getSubsystemId();
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertNotConstituent(root, BUNDLE_B);
assertConstituent(parent, BUNDLE_A);
Subsystem child = getChild(parent, APPLICATION_A);
assertNotNull("Missing child", child);
id = child.getSubsystemId();
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertNotConstituent(root, BUNDLE_D);
assertConstituent(child, BUNDLE_A);
assertConstituent(child, BUNDLE_C);
parent.start();
try {
id = parent.getSubsystemId();
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.STARTING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_B, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.ACTIVE, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(root, BUNDLE_B);
id = child.getSubsystemId();
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.STARTING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, APPLICATION_A, Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.ACTIVE, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(root, BUNDLE_D);
}
finally {
stopSubsystemSilently(parent);
}
}
finally {
uninstallSubsystemSilently(parent);
}
}
/*
* (18) Scoped subsystem with a value of apache-aries-provision-dependencies
* that overrides the scoped parent behaves accordingly.
*/
@Test
public void test18() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem parent = root.install(
"parent",
new SubsystemArchiveBuilder()
.symbolicName("parent")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.content("bundle1")
.bundle(
"bundle1",
new BundleArchiveBuilder()
.symbolicName("bundle1")
.importPackage("a")
.build())
.bundle(
"bundle2",
new BundleArchiveBuilder()
.symbolicName("bundle2")
.exportPackage("a")
.build())
.build()
);
try {
long id = parent.getSubsystemId();
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(parent, "bundle2");
assertConstituent(parent, "bundle1");
parent.start();
Subsystem child = parent.install(
"child",
new SubsystemArchiveBuilder()
.symbolicName("child")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("bundle3")
.bundle(
"bundle3",
new BundleArchiveBuilder()
.symbolicName("bundle3")
.importPackage("b")
.build())
.bundle(
"bundle4",
new BundleArchiveBuilder()
.symbolicName("bundle4")
.exportPackage("b")
.build())
.build()
);
id = child.getSubsystemId();
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLING, subsystemEvents.poll(id, 5000),
ServiceEvent.REGISTERED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertNotConstituent(parent, "bundle4");
assertConstituent(child, "bundle3");
child.start();
try {
id = parent.getSubsystemId();
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.STARTING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "parent", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.ACTIVE, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
id = child.getSubsystemId();
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.INSTALLED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.RESOLVED, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.STARTING, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertEvent(id, "child", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION,
State.ACTIVE, subsystemEvents.poll(id, 5000),
ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(parent, "bundle4");
}
finally {
stopSubsystemSilently(parent);
}
}
finally {
uninstallSubsystemSilently(parent);
}
}
/*
* (19) Scoped subsystem with only features as parents is able to override
* the value of apache-aries-provision-dependencies.
*/
@Test
public void test19() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
Subsystem feature1 = installSubsystem(
root,
"feature1",
new SubsystemArchiveBuilder()
.symbolicName("feature1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.build()
);
try {
Subsystem feature2 = installSubsystem(
root,
"feature2",
new SubsystemArchiveBuilder()
.symbolicName("feature2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE
+ ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString())
.build()
);
try {
SubsystemArchiveBuilder applicationArchive = new SubsystemArchiveBuilder()
.symbolicName("application")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.content("bundle1")
.bundle(
"bundle1",
new BundleArchiveBuilder()
.symbolicName("bundle1")
.importPackage("a")
.build())
.bundle(
"bundle2",
new BundleArchiveBuilder()
.symbolicName("bundle2")
.exportPackage("a")
.build());
Subsystem application1 = feature1.install("application", applicationArchive.build());
Subsystem application2 = feature2.install("application", applicationArchive.build());
assertSame("Wrong subsystem", application1, application2);
assertEquals("Wrong subsystem", application1, application2);
assertChild(feature1, "application");
assertChild(feature2, "application");
long id = application1.getSubsystemId();
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.INSTALLING,
subsystemEvents.poll(id, 5000), ServiceEvent.REGISTERED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(application1, "bundle1");
assertNotConstituent(application1, "bundle2");
application1.start();
try {
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.INSTALLED,
subsystemEvents.poll(id, 5000), ServiceEvent.MODIFIED);
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.RESOLVING,
subsystemEvents.poll(id, 5000), ServiceEvent.MODIFIED);
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.RESOLVED,
subsystemEvents.poll(id, 5000), ServiceEvent.MODIFIED);
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.STARTING,
subsystemEvents.poll(id, 5000), ServiceEvent.MODIFIED);
assertEvent(id, "application", Version.emptyVersion,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, State.ACTIVE,
subsystemEvents.poll(id, 5000), ServiceEvent.MODIFIED);
assertNull("Unexpected event", subsystemEvents.poll(id, 1));
assertConstituent(application1, "bundle2");
}
finally {
stopSubsystemSilently(application1);
}
}
finally {
uninstallSubsystemSilently(feature2);
}
}
finally {
uninstallSubsystemSilently(feature1);
}
}
/*
* (20) Install a scoped subsystem, S1, with
* apache-aries-provision-dependencies:=resolve. Install two features, F1 and
* F2, independently as children of S1. F1 has bundle B1 as content. F2 has
* bundle B2 as content. B2 has B1 as a dependency. B1 should be a
* constituent of F1 but not of the root subsystem.
*/
@Test
public void test20() throws Exception {
serviceRegistrations.add(bundleContext.registerService(
Repository.class,
new TestRepository.Builder()
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b1")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.content(new BundleArchiveBuilder()
.symbolicName("b1")
.exportPackage("a")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b2")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.content(new BundleArchiveBuilder()
.symbolicName("b2")
.importPackage("a")
.buildAsBytes())
.build())
.build(),
null));
Subsystem root = getRootSubsystem();
Subsystem s1 = installSubsystem(
root,
"s1",
new SubsystemArchiveBuilder()
.symbolicName("s1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.build(),
false
);
uninstallableSubsystems.add(s1);
startSubsystem(s1, false);
stoppableSubsystems.add(s1);
Subsystem f2 = installSubsystem(
s1,
"f2",
new SubsystemArchiveBuilder()
.symbolicName("f2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.content("b2")
.build(),
false
);
uninstallableSubsystems.add(f2);
assertChild(s1, "f2", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(f2, "b2");
Subsystem f1 = installSubsystem(
s1,
"f1",
new SubsystemArchiveBuilder()
.symbolicName("f1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.content("b1")
.build(),
false
);
uninstallableSubsystems.add(f1);
assertChild(s1, "f1", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(f1, "b1");
assertNotConstituent(root, "b1");
}
/*
* (21) Install a scoped subsystem, S1, with
* apache-aries-provision-dependencies:=resolve. Install two features, F1 and
* F2, independently as children of S1. F1 has bundle B1 and B2 as content.
* F2 has bundle B2 and B3 as content. B2 is shared content. B1 has a
* dependency on bundle B4, B2 has a dependency on bundle B5. B3 has a
* dependency on bundle B6. Start F1. Dependency bundles B4 and B5 should be
* provisioned but not B6.
*/
@Test
public void test21() throws Exception {
serviceRegistrations.add(bundleContext.registerService(
Repository.class,
new TestRepository.Builder()
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b1")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.requirement(new TestRequirement.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.directive(
PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE,
"(osgi.wiring.package=b4)"))
.content(new BundleArchiveBuilder()
.symbolicName("b1")
.importPackage("b4")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b2")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.requirement(new TestRequirement.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.directive(
PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE,
"(osgi.wiring.package=b5)"))
.content(new BundleArchiveBuilder()
.symbolicName("b2")
.importPackage("b5")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b3")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.requirement(new TestRequirement.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.directive(
PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE,
"(osgi.wiring.package=b6)"))
.content(new BundleArchiveBuilder()
.symbolicName("b3")
.importPackage("b6")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b4")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.capability(new TestCapability.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.attribute(
PackageNamespace.PACKAGE_NAMESPACE,
"b4"))
.content(new BundleArchiveBuilder()
.symbolicName("b4")
.exportPackage("b4")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b5")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.capability(new TestCapability.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.attribute(
PackageNamespace.PACKAGE_NAMESPACE,
"b5"))
.content(new BundleArchiveBuilder()
.symbolicName("b5")
.exportPackage("b5")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b6")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.capability(new TestCapability.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.attribute(
PackageNamespace.PACKAGE_NAMESPACE,
"b6"))
.content(new BundleArchiveBuilder()
.symbolicName("b6")
.exportPackage("b6")
.buildAsBytes())
.build())
.build(),
null));
Subsystem root = getRootSubsystem();
Subsystem s1 = installSubsystem(
root,
"s1",
new SubsystemArchiveBuilder()
.symbolicName("s1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.build(),
false
);
uninstallableSubsystems.add(s1);
startSubsystem(s1, false);
stoppableSubsystems.add(s1);
Subsystem f2 = installSubsystem(
s1,
"f2",
new SubsystemArchiveBuilder()
.symbolicName("f2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.content("b2,b3")
.build(),
false
);
uninstallableSubsystems.add(f2);
assertChild(s1, "f2", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(s1, "f2", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(f2, "b2");
assertConstituent(f2, "b3");
Subsystem f1 = installSubsystem(
s1,
"f1",
new SubsystemArchiveBuilder()
.symbolicName("f1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.content("b1,b2")
.build(),
false
);
uninstallableSubsystems.add(f1);
assertChild(s1, "f1", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(s1, "f1", null, SubsystemConstants.SUBSYSTEM_TYPE_FEATURE);
assertConstituent(f1, "b1");
assertConstituent(f1, "b2");
startSubsystem(f1, false);
stoppableSubsystems.add(f1);
assertState(EnumSet.of(State.RESOLVED, State.ACTIVE), f2);
assertConstituent(s1, "b4");
assertConstituent(s1, "b5");
assertConstituent(s1, "b6");
}
@Test
public void testFullLifeCycle() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
startSubsystem(subsystem, false);
stopSubsystem(subsystem);
uninstallSubsystem(subsystem);
}
@Test
public void testImplicitlyInstalledChildOverridesProvisionDependencies() throws Exception {
Subsystem root = getRootSubsystem();
subsystemEvents.clear();
try {
Subsystem subsystem = root.install(
"parent",
new SubsystemArchiveBuilder()
.symbolicName("parent")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.INSTALL.toString())
.subsystem(
"child",
new SubsystemArchiveBuilder()
.symbolicName("child")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString())
.build())
.build());
uninstallSubsystemSilently(subsystem);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
}
@Test
public void testInstall() throws Exception {
Subsystem root = getRootSubsystem();
try {
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
uninstallSubsystemSilently(subsystem);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
}
@Test
public void testInstallChildIntoInstallingParent() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_DEPENDENCY_IN_ARCHIVE, applicationDependencyInArchive(), false);
try {
assertState(State.INSTALLING, subsystem);
installSubsystem(subsystem, APPLICATION_A, applicationA(), false);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
@Test
public void testStart() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
try {
startSubsystem(subsystem, false);
stopSubsystemSilently(subsystem);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have started");
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
@Test
public void testStop() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
try {
startSubsystem(subsystem, false);
try {
stopSubsystem(subsystem);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have stopped");
}
}
finally {
uninstallSubsystemSilently(subsystem);
}
}
@Test
public void testUninstall() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem subsystem = installSubsystem(root, APPLICATION_EMPTY, applicationEmpty(), false);
try {
uninstallSubsystem(subsystem);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have uninstalled");
}
}
private InputStream applicationA() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_A);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A + ',' + BUNDLE_C);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_A + JAR_EXTENSION, bundleA())
.add(BUNDLE_B + JAR_EXTENSION, bundleB())
.add(BUNDLE_C + JAR_EXTENSION, bundleC())
.add(BUNDLE_D + JAR_EXTENSION, bundleD())
.build();
}
private InputStream applicationB() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_B);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A + ',' + APPLICATION_A + ";type=osgi.subsystem.application");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_A + JAR_EXTENSION, bundleA())
.add(BUNDLE_B + JAR_EXTENSION, bundleB())
.add(APPLICATION_A + ESA_EXTENSION, applicationA())
.build();
}
private InputStream applicationDependencyInArchive() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_DEPENDENCY_IN_ARCHIVE);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_A + JAR_EXTENSION, bundleA())
.add(BUNDLE_B + JAR_EXTENSION, bundleB())
.build();
}
private InputStream applicationEmpty() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), MANIFEST_VERSION);
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_EMPTY);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.build();
}
private InputStream applicationInstallFailed() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), MANIFEST_VERSION);
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_INSTALL_FAILED);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_INVALID_MANIFEST + JAR_EXTENSION, bundleInvalidManifest())
.build();
}
private InputStream applicationInvalidProvisionDependencies() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_INVALID_PROVISION_DEPENDENCIES);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.NAME + ":=foo");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.build();
}
private InputStream applicationMissingDependency() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_MISSING_DEPENDENCY);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_A + JAR_EXTENSION, bundleA())
.build();
}
private InputStream applicationProvisionDependenciesInstall() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_PROVISION_DEPENDENCIES_INSTALL);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.INSTALL.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_A + JAR_EXTENSION, bundleA())
.add(BUNDLE_B + JAR_EXTENSION, bundleB())
.build();
}
private InputStream applicationStartFailure() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_START_FAILURE);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
attributes.putValue(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_START_FAILURE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.add(BUNDLE_START_FAILURE + JAR_EXTENSION, bundleStartFailure())
.build();
}
private void assertReferences(Class<?> clazz, String filter, int expected) throws Exception {
ServiceReference<?>[] references = bundleContext.getAllServiceReferences(clazz.getName(), filter);
if (expected < 1) {
assertNull("References exist", references);
}
else {
assertNotNull("No references", references);
assertEquals("No references or more than one", expected, references.length);
}
}
private InputStream bundleA() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_A)
.set(Constants.EXPORT_PACKAGE, PACKAGE_A)
.set(Constants.IMPORT_PACKAGE, PACKAGE_B)
.build();
}
private InputStream bundleB() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_B)
.set(Constants.EXPORT_PACKAGE, PACKAGE_B)
.build();
}
private InputStream bundleC() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_C)
.set(Constants.EXPORT_PACKAGE, PACKAGE_C)
.set(Constants.IMPORT_PACKAGE, PACKAGE_B)
.set(Constants.IMPORT_PACKAGE, PACKAGE_D)
.build();
}
private InputStream bundleD() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_D)
.set(Constants.EXPORT_PACKAGE, PACKAGE_D)
.build();
}
private InputStream bundleInvalidManifest() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_INVALID_MANIFEST)
.set(Constants.PROVIDE_CAPABILITY, "osgi.ee;osgi.ee=J2SE-1.4")
.build();
}
private InputStream bundleStartFailure() {
return TinyBundles
.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_START_FAILURE)
.set(Constants.BUNDLE_ACTIVATOR, BundleStartFailureActivator.class.getName())
.add(BundleStartFailureActivator.class, InnerClassStrategy.NONE)
.build();
}
private InputStream featureProvisionDependenciesResolve() throws Exception {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
attributes.putValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, FEATURE_PROVISION_DEPENDENCIES_RESOLVE);
attributes.putValue(SubsystemConstants.SUBSYSTEM_TYPE,
SubsystemConstants.SUBSYSTEM_TYPE_FEATURE + ';' +
AriesProvisionDependenciesDirective.RESOLVE.toString());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.close();
return TinyBundles
.bundle()
.add(SUBSYSTEM_MANIFEST_FILE, new ByteArrayInputStream(baos.toByteArray()))
.build();
}
public static interface TestService {}
public static class TestServiceImpl implements TestService {}
public static class TestServiceClientActivator implements BundleActivator {
@Override
public void start(BundleContext context) throws Exception {
ServiceReference<TestService> ref = null;
for (int i = 0; i < 80; i++) { // 20 seconds with 250ms sleep.
ref = context.getServiceReference(TestService.class);
if (ref == null) {
Thread.sleep(250);
continue;
}
break;
}
try {
TestService service = context.getService(ref);
service.getClass();
}
finally {
context.ungetService(ref);
}
}
@Override
public void stop(BundleContext context) throws Exception {
}
}
public static class TestServiceImplActivator implements BundleActivator {
private ServiceRegistration<TestService> reg;
@Override
public void start(BundleContext context) throws Exception {
reg = context.registerService(
TestService.class,
new TestServiceImpl(),
null);
}
@Override
public void stop(BundleContext context) throws Exception {
reg.unregister();
}
}
private static class BundleStartFailureActivator implements BundleActivator {
@Override
public void start(BundleContext context) throws Exception {
throw new IllegalStateException();
}
@Override
public void stop(BundleContext context) throws Exception {
// Nothing.
}
}
@Test
public void testInterleavingContentDependencies() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem c1 = installSubsystem(
root,
"c1",
new SubsystemArchiveBuilder()
.symbolicName("c1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("c1b1;version=\"[0,0]\"")
.exportPackage("c1b1")
.importPackage("c2b1")
.bundle(
"c1b1",
new BundleArchiveBuilder()
.symbolicName("c1b1")
.exportPackage("c1b1")
.importPackage("c2b1")
.build())
.build(),
false
);
uninstallableSubsystems.add(c1);
Subsystem c2 = installSubsystem(
root,
"c2",
new SubsystemArchiveBuilder()
.symbolicName("c2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("c2b1;version=\"[0,0]\"")
.exportPackage("c2b1")
.importPackage("c1b1")
.bundle(
"c2b1",
new BundleArchiveBuilder()
.symbolicName("c2b1")
.exportPackage("c2b1")
.importPackage("c1b1")
.build())
.build(),
false
);
uninstallableSubsystems.add(c2);
startSubsystem(c1, false);
stoppableSubsystems.add(c1);
assertState(EnumSet.of(State.RESOLVED, State.ACTIVE), c2);
stoppableSubsystems.add(c2);
}
@Test
public void testRestart2() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem c1 = installSubsystem(
root,
"c1",
new SubsystemArchiveBuilder()
.symbolicName("c1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("c1b1;version=\"[0,0]\"")
.exportPackage("c1b1")
.importPackage("c2b1")
.bundle(
"c1b1",
new BundleArchiveBuilder()
.symbolicName("c1b1")
.exportPackage("c1b1")
.importPackage("c2b1")
.build())
.build(),
false
);
uninstallableSubsystems.add(c1);
Subsystem c2 = installSubsystem(
root,
"c2",
new SubsystemArchiveBuilder()
.symbolicName("c2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("c2b1;version=\"[0,0]\"")
.exportPackage("c2b1")
.importPackage("c1b1")
.bundle(
"c2b1",
new BundleArchiveBuilder()
.symbolicName("c2b1")
.exportPackage("c2b1")
.importPackage("c1b1")
.build())
.build(),
false
);
uninstallableSubsystems.add(c2);
assertChild(root, "c1", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
assertChild(root, "c2", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
restartSubsystemsImplBundle();
root = getRootSubsystem();
c1 = getChild(root, "c1", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
assertNotNull("Missing child", c1);
uninstallableSubsystems.add(c1);
c2 = getChild(root, "c2", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
assertNotNull("Missing child", c2);
uninstallableSubsystems.add(c2);
startSubsystem(c1, false);
stoppableSubsystems.add(c1);
try {
assertState(EnumSet.of(State.RESOLVED, State.ACTIVE), c2);
}
catch (AssertionError e) {
System.out.println(c2.getState());
}
}
@Test
public void testRestart() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem a1 = installSubsystem(
root,
"a1",
new SubsystemArchiveBuilder()
.symbolicName("a1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION + ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b1,c1;type=osgi.subsystem.composite")
.bundle(
"b1",
new BundleArchiveBuilder()
.symbolicName("b1")
.importPackage("b2")
.build())
.bundle(
"b2",
new BundleArchiveBuilder()
.symbolicName("b2")
.exportPackage("b2")
.build())
.subsystem(
"c1",
new SubsystemArchiveBuilder()
.symbolicName("c1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("b1;version=\"[0,0]\"")
.importPackage("b2")
.bundle(
"b1",
new BundleArchiveBuilder()
.symbolicName("b1")
.importPackage("b2")
.build())
.build())
.build(),
false);
uninstallableSubsystems.add(a1);
assertChild(root, "a1");
assertState(State.INSTALLING, a1);
Subsystem c1 = getChild(a1, "c1", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
assertNotNull("Missing child", c1);
assertState(State.INSTALLING, c1);
restartSubsystemsImplBundle();
root = getRootSubsystem();
a1 = getChild(root, "a1");
assertNotNull("Missing child", a1);
uninstallableSubsystems.add(a1);
assertState(State.INSTALLING, a1);
assertConstituent(a1, "b1");
assertNotConstituent(root, "b2");
c1 = getChild(a1, "c1", null, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
assertNotNull("Missing child", c1);
uninstallableSubsystems.add(c1);
assertConstituent(c1, "b1");
startSubsystem(c1, false);
stoppableSubsystems.add(c1);
assertState(State.INSTALLED, a1);
stoppableSubsystems.add(a1);
assertConstituent(root, "b2");
}
@Test
public void test4e3bCompliance() throws Exception {
serviceRegistrations.add(bundleContext.registerService(
Repository.class,
new TestRepository.Builder()
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"a")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.capability(new TestCapability.Builder()
.namespace(PackageNamespace.PACKAGE_NAMESPACE)
.attribute(
PackageNamespace.PACKAGE_NAMESPACE,
"x")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion))
.capability(new TestCapability.Builder()
.namespace(BundleNamespace.BUNDLE_NAMESPACE)
.attribute(
BundleNamespace.BUNDLE_NAMESPACE,
"a")
.attribute(
BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
Version.emptyVersion))
.content(new BundleArchiveBuilder()
.symbolicName("a")
.exportPackage("x")
.buildAsBytes())
.build())
.resource(new TestRepositoryContent.Builder()
.capability(new TestCapability.Builder()
.namespace(IdentityNamespace.IDENTITY_NAMESPACE)
.attribute(
IdentityNamespace.IDENTITY_NAMESPACE,
"b")
.attribute(
IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
Version.emptyVersion)
.attribute(
IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
IdentityNamespace.TYPE_BUNDLE))
.capability(new TestCapability.Builder()
.namespace("y"))
.content(new BundleArchiveBuilder()
.symbolicName("b")
.header("Provide-Capability", "y")
.buildAsBytes())
.build())
.build(),
null));
Subsystem root = getRootSubsystem();
try {
Subsystem s1 = installSubsystem(
root,
"s1",
new SubsystemArchiveBuilder()
.symbolicName("s1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.subsystem(
"s3",
new SubsystemArchiveBuilder()
.symbolicName("s3")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.subsystem(
"s2",
new SubsystemArchiveBuilder()
.symbolicName("s2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION)
.bundle(
"c",
new BundleArchiveBuilder()
.symbolicName("c")
.importPackage("x")
.build())
.bundle(
"d",
new BundleArchiveBuilder()
.symbolicName("d")
.header("Require-Bundle", "a")
.build())
.bundle(
"e",
new BundleArchiveBuilder()
.symbolicName("e")
.header("Require-Capability", "y")
.build())
.build())
.build())
.build(),
true);
uninstallableSubsystems.add(s1);
fail("Subsystem should not have installed");
}
catch (SubsystemException e) {
e.printStackTrace();
}
}
@Test
public void testMatchingCapabilityInDisconnectedRegion() throws Exception {
Subsystem root = getRootSubsystem();
BundleArchiveBuilder b1Builder = new BundleArchiveBuilder()
.symbolicName("b1")
.exportPackage("b1");
Bundle b1 = root.getBundleContext().installBundle("b1", b1Builder.build());
try {
Subsystem a1 = installSubsystem(
root,
"a1",
new SubsystemArchiveBuilder()
.symbolicName("a1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.build(),
false
);
uninstallableSubsystems.add(a1);
startSubsystem(a1, false);
stoppableSubsystems.add(a1);
removeConnectionWithParent(a1);
Subsystem a2 = installSubsystem(
a1,
"a2",
new SubsystemArchiveBuilder()
.symbolicName("a2")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION)
.content("b2")
.bundle(
"b2",
new BundleArchiveBuilder()
.symbolicName("b2")
.importPackage("b1")
.build())
.bundle(
"b1",
b1Builder.build())
.build(),
false
);
uninstallableSubsystems.add(a2);
assertState(State.INSTALLING, a2);
assertNotConstituent(a1, "b1");
try {
startSubsystem(a2, false);
stoppableSubsystems.add(a2);
assertConstituent(a1, "b1");
}
catch (SubsystemException e) {
e.printStackTrace();
fail("Subsystem should have started");
}
}
finally {
uninstallSilently(b1);
}
}
@Test
public void testProvideCapabilityNamespaceOnly() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem c1 = installSubsystem(
root,
"c1",
new SubsystemArchiveBuilder()
.symbolicName("c1")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.provideCapability("y")
.build());
uninstallableSubsystems.add(c1);
try {
startSubsystem(c1);
stoppableSubsystems.add(c1);
}
catch (SubsystemException e) {
e.printStackTrace();
fail("Subsystem should have started");
}
}
@Test
public void testComApiComImplAppClient() throws Exception {
Subsystem root = getRootSubsystem();
final Subsystem shared = installSubsystem(
root,
"shared",
new SubsystemArchiveBuilder()
.symbolicName("shared")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.importPackage("org.osgi.framework")
.build(),
false
);
uninstallableSubsystems.add(shared);
shared.start();
stoppableSubsystems.add(shared);
@SuppressWarnings("unchecked")
Callable<Subsystem>[] installCallables = new Callable[] {
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"client",
new SubsystemArchiveBuilder()
.symbolicName("client")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION)
.bundle(
"client",
new BundleArchiveBuilder()
.symbolicName("client")
.importPackage("org.apache.aries.subsystem.itests.defect")
.requireCapability("osgi.service;filter:=\"(objectClass="
+ TestService.class.getName()
+ ")\";effective:=active")
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"impl",
new SubsystemArchiveBuilder()
.symbolicName("impl")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.content("impl;version=\"[0,0]\"")
.provideCapability("osgi.service;objectClass:List<String>=\""
+ TestService.class.getName()
+ "\"")
.importPackage("org.osgi.framework")
.requireBundle("api")
.bundle(
"impl",
new BundleArchiveBuilder()
.symbolicName("impl")
.provideCapability("osgi.service;objectClass:List<String>=\""
+ TestService.class.getName()
+ "\"")
.importPackage("org.osgi.framework")
.requireBundle("api")
.clazz(TestServiceImpl.class)
.activator(TestServiceImplActivator.class)
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"api",
new SubsystemArchiveBuilder()
.symbolicName("api")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.content("api;version=\"[0,0]\"")
.exportPackage("org.apache.aries.subsystem.itests.defect")
.provideCapability("osgi.wiring.bundle;osgi.wiring.bundle=api;bundle-version=0")
.bundle(
"api",
new BundleArchiveBuilder()
.symbolicName("api")
.exportPackage("org.apache.aries.subsystem.itests.defect")
.clazz(TestService.class)
.build())
.build(),
false);
uninstallableSubsystems.add(result);
return result;
}
}
};
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<Subsystem>> installFutures = executor.invokeAll(Arrays.asList(installCallables));
final Subsystem a1 = installFutures.get(0).get();
final Subsystem c1 = installFutures.get(1).get();
final Subsystem c2 = installFutures.get(2).get();
@SuppressWarnings("unchecked")
Callable<Void>[] startCallables = new Callable[] {
new Callable<Void>() {
@Override
public Void call() throws Exception {
a1.start();
stoppableSubsystems.add(a1);
assertEvent(a1, State.INSTALLED, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.RESOLVING, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.RESOLVED, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.STARTING, subsystemEvents.poll(a1.getSubsystemId(), 5000));
assertEvent(a1, State.ACTIVE, subsystemEvents.poll(a1.getSubsystemId(), 5000));
return null;
}
},
new Callable<Void>() {
@Override
public Void call() throws Exception {
c1.start();
stoppableSubsystems.add(c1);
assertEvent(c1, State.INSTALLED, subsystemEvents.poll(c1.getSubsystemId(), 5000));
assertEvent(c1, State.RESOLVING, subsystemEvents.poll(c1.getSubsystemId(), 5000));
assertEvent(c1, State.RESOLVED, subsystemEvents.poll(c1.getSubsystemId(), 5000));
assertEvent(c1, State.STARTING, subsystemEvents.poll(c1.getSubsystemId(), 5000));
assertEvent(c1, State.ACTIVE, subsystemEvents.poll(c1.getSubsystemId(), 5000));
return null;
}
},
new Callable<Void>() {
@Override
public Void call() throws Exception {
c2.start();
stoppableSubsystems.add(c2);
assertEvent(c2, State.INSTALLED, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.RESOLVING, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.RESOLVED, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.STARTING, subsystemEvents.poll(c2.getSubsystemId(), 5000));
assertEvent(c2, State.ACTIVE, subsystemEvents.poll(c2.getSubsystemId(), 5000));
return null;
}
}
};
List<Future<Void>> startFutures = executor.invokeAll(Arrays.asList(startCallables));
startFutures.get(0).get();
startFutures.get(1).get();
startFutures.get(2).get();
}
@Test
public void testComApiComImplComClient() throws Exception {
Subsystem root = getRootSubsystem();
final Subsystem shared = installSubsystem(
root,
"shared",
new SubsystemArchiveBuilder()
.symbolicName("shared")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.importPackage("org.osgi.framework")
.build(),
false
);
uninstallableSubsystems.add(shared);
shared.start();
stoppableSubsystems.add(shared);
@SuppressWarnings("unchecked")
Callable<Subsystem>[] installCallables = new Callable[] {
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"client",
new SubsystemArchiveBuilder()
.symbolicName("client")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.content("client;version=\"[0,0]\"")
.importPackage("org.osgi.framework")
.requireCapability("osgi.service;filter:=\"(objectClass="
+ TestService.class.getName()
+ ")\";effective:=active")
.importService(TestService.class.getName())
.requireBundle("api,impl")
.bundle(
"client",
new BundleArchiveBuilder()
.symbolicName("client")
.importPackage("org.osgi.framework")
.requireCapability("osgi.service;filter:=\"(objectClass="
+ TestService.class.getName()
+ ")\";effective:=active")
.requireBundle("api,impl")
.activator(TestServiceClientActivator.class)
.build())
.build(),
false);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"impl",
new SubsystemArchiveBuilder()
.symbolicName("impl")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.content("impl;version=\"[0,0]\"")
.provideCapability("osgi.service;objectClass:List<String>=\""
+ TestService.class.getName()
+ "\"")
.exportService(TestService.class.getName())
.importPackage("org.osgi.framework")
.requireBundle("api")
.provideCapability("osgi.wiring.bundle;osgi.wiring.bundle=impl;bundle-version=0")
.bundle(
"impl",
new BundleArchiveBuilder()
.symbolicName("impl")
.provideCapability("osgi.service;objectClass:List<String>=\""
+ TestService.class.getName()
+ "\"")
.importPackage("org.osgi.framework")
.requireBundle("api")
.clazz(TestServiceImpl.class)
.activator(TestServiceImplActivator.class)
.build())
.build(),
false);
return result;
}
},
new Callable<Subsystem>() {
@Override
public Subsystem call() throws Exception {
Subsystem result = installSubsystem(
shared,
"api",
new SubsystemArchiveBuilder()
.symbolicName("api")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
.content("api;version=\"[0,0]\"")
.exportPackage("org.apache.aries.subsystem.itests.defect")
.provideCapability("osgi.wiring.bundle;osgi.wiring.bundle=api;bundle-version=0")
.bundle(
"api",
new BundleArchiveBuilder()
.symbolicName("api")
.exportPackage("org.apache.aries.subsystem.itests.defect")
.clazz(TestService.class)
.build())
.build(),
false);
return result;
}
}
};
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<Subsystem>> installFutures = executor.invokeAll(Arrays.asList(installCallables));
final Subsystem client = installFutures.get(0).get();
final Subsystem impl = installFutures.get(1).get();
final Subsystem api = installFutures.get(2).get();
@SuppressWarnings("unchecked")
Callable<Void>[] startCallables = new Callable[] {
new Callable<Void>() {
@Override
public Void call() throws Exception {
client.start();
assertEvent(client, State.INSTALLED, subsystemEvents.poll(client.getSubsystemId(), 5000));
assertEvent(client, State.RESOLVING, subsystemEvents.poll(client.getSubsystemId(), 5000));
assertEvent(client, State.RESOLVED, subsystemEvents.poll(client.getSubsystemId(), 5000));
assertEvent(client, State.STARTING, subsystemEvents.poll(client.getSubsystemId(), 5000));
assertEvent(client, State.ACTIVE, subsystemEvents.poll(client.getSubsystemId(), 5000));
return null;
}
},
new Callable<Void>() {
@Override
public Void call() throws Exception {
impl.start();
assertEvent(impl, State.INSTALLED, subsystemEvents.poll(impl.getSubsystemId(), 5000));
assertEvent(impl, State.RESOLVING, subsystemEvents.poll(impl.getSubsystemId(), 5000));
assertEvent(impl, State.RESOLVED, subsystemEvents.poll(impl.getSubsystemId(), 5000));
assertEvent(impl, State.STARTING, subsystemEvents.poll(impl.getSubsystemId(), 5000));
assertEvent(impl, State.ACTIVE, subsystemEvents.poll(impl.getSubsystemId(), 5000));
return null;
}
},
new Callable<Void>() {
@Override
public Void call() throws Exception {
api.start();
assertEvent(api, State.INSTALLED, subsystemEvents.poll(api.getSubsystemId(), 5000));
assertEvent(api, State.RESOLVING, subsystemEvents.poll(api.getSubsystemId(), 5000));
assertEvent(api, State.RESOLVED, subsystemEvents.poll(api.getSubsystemId(), 5000));
assertEvent(api, State.STARTING, subsystemEvents.poll(api.getSubsystemId(), 5000));
assertEvent(api, State.ACTIVE, subsystemEvents.poll(api.getSubsystemId(), 5000));
return null;
}
}
};
List<Future<Void>> startFutures = executor.invokeAll(Arrays.asList(startCallables));
startFutures.get(0).get();
startFutures.get(1).get();
startFutures.get(2).get();
}
@Test
public void testAutoInstallDependenciesComposite() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem b = installSubsystem(
root,
"b",
new SubsystemArchiveBuilder()
.symbolicName("b")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString())
.content("a;version=\"[0,0]\"")
.exportPackage("a")
.importPackage("b")
.bundle(
"a",
new BundleArchiveBuilder()
.symbolicName("a")
.importPackage("b")
.exportPackage("a")
.build())
.bundle(
"b",
new BundleArchiveBuilder()
.symbolicName("b")
.exportPackage("b")
.build())
.build(),
false
);
uninstallableSubsystems.add(b);
try {
Subsystem a = installSubsystem(
root,
"a",
new SubsystemArchiveBuilder()
.symbolicName("a")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION)
.bundle(
"a",
new BundleArchiveBuilder()
.symbolicName("a")
.importPackage("a")
.build())
.build(),
true
);
uninstallableSubsystems.add(a);
assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), b);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
}
@Test
public void testAutoInstallDependenciesFeature() throws Exception {
Subsystem root = getRootSubsystem();
Subsystem shared = installSubsystem(
root,
"shared",
new SubsystemArchiveBuilder()
.symbolicName("shared")
.type(SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE
+ ';'
+ AriesProvisionDependenciesDirective.RESOLVE.toString()
+ ';'
+ SubsystemConstants.PROVISION_POLICY_DIRECTIVE
+ ":="
+ SubsystemConstants.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
.build(),
false
);
uninstallableSubsystems.add(shared);
startSubsystem(shared, false);
Subsystem b = installSubsystem(
shared,
"b",
new SubsystemArchiveBuilder()
.symbolicName("b")
.type(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE)
.content("a")
.bundle(
"a",
new BundleArchiveBuilder()
.symbolicName("a")
.importPackage("b")
.exportPackage("a")
.build())
.bundle(
"b",
new BundleArchiveBuilder()
.symbolicName("b")
.exportPackage("b")
.build())
.build(),
false
);
try {
installSubsystem(
shared,
"a",
new SubsystemArchiveBuilder()
.symbolicName("a")
.type(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION
+ ';'
+ AriesProvisionDependenciesDirective.INSTALL.toString())
.bundle(
"a",
new BundleArchiveBuilder()
.symbolicName("a")
.importPackage("a")
.build())
.build(),
true
);
assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), b);
}
catch (Exception e) {
e.printStackTrace();
fail("Subsystem should have installed");
}
}
}