Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java Sun Aug 28 20:39:09 2011 @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.aries.subsystem.core.archive.Archive; import org.apache.aries.subsystem.core.internal.Activator; import org.apache.aries.subsystem.core.internal.AriesSubsystem; import org.apache.aries.subsystem.core.internal.OsgiIdentityRequirement; @@ -42,14 +43,12 @@ import org.osgi.service.subsystem.Subsys * So does the locating of providers for feature content with respect to children of the first parent that is not a feature. */ public class SubsystemEnvironment implements Environment { - private final Repository repository; private final Set<Resource> resources = new HashSet<Resource>(); private final Map<Resource, Repository> resourceToRepository = new HashMap<Resource, Repository>(); private final AriesSubsystem subsystem; public SubsystemEnvironment(AriesSubsystem subsystem) throws IOException, URISyntaxException { this.subsystem = subsystem; - repository = new ArchiveRepository(subsystem.getArchive()); } @Override @@ -61,17 +60,14 @@ public class SubsystemEnvironment implem OsgiIdentityRequirement identity = (OsgiIdentityRequirement)requirement; if (subsystem.isFeature()) { // Features share content resources as well as transitive dependencies. - findFeatureContentProviders(capabilities, identity); - findContentProviders(capabilities, identity); - } - else { - // Applications and composites do not share content resources, only transitive dependencies. - findContentProviders(capabilities, identity); + findConstituentProviders(requirement, capabilities); } + findArchiveProviders(capabilities, identity, !identity.isTransitiveDependency()); + findRepositoryServiceProviders(capabilities, identity, !identity.isTransitiveDependency()); return capabilities; } // This means we're looking for capabilities satisfying a requirement within a content resource or transitive dependency. - findTransitiveDependencyProviders(requirement, capabilities); + findArchiveProviders(capabilities, requirement, false); findRepositoryServiceProviders(capabilities, requirement, false); return capabilities; } @@ -101,79 +97,99 @@ public class SubsystemEnvironment implem return true; } - private void findArchiveProviders(Collection<Capability> capabilities, Requirement requirement) { - for (Capability capability : repository.findProviders(requirement)) { - capabilities.add(capability); - resourceToRepository.put(capability.getResource(), repository); - resources.add(capability.getResource()); - } - } - - private void findContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement) { - findArchiveProviders(capabilities, requirement); - findRepositoryServiceProviders(capabilities, requirement, !requirement.isTransitiveDependency()); - } - - private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement) { + private void findConstituentProviders(Requirement requirement, Collection<Capability> capabilities) { Subsystem subsystem = this.subsystem; - while (subsystem.getParent() != null && "osgi.feature".equals(subsystem.getParent().getHeaders().get("Subsystem-Type"))) // TODO Add to constants. + while (subsystem.getParent() != null) { subsystem = subsystem.getParent(); - findFeatureContentProviders(capabilities, requirement, subsystem); + } + findConstituentProviders(subsystem, requirement, capabilities); } - private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement, Subsystem subsystem) { + private void findConstituentProviders(Subsystem subsystem, Requirement requirement, Collection<Capability> capabilities) { for (Resource resource : subsystem.getConstituents()) { for (Capability capability : resource.getCapabilities(requirement.getNamespace())) { if (requirement.matches(capability)) { capabilities.add(capability); - resourceToRepository.put(capability.getResource(), repository); - resources.add(capability.getResource()); } } } - findFeatureContentProviders(capabilities, requirement, subsystem.getChildren()); - } - - private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement, Collection<Subsystem> subsystems) { - for (Subsystem subsystem : subsystems) - if ("osgi.feature".equals(subsystem.getParent().getHeaders().get("Subsystem-Type"))) // TODO Add to constants. - findFeatureContentProviders(capabilities, requirement, subsystem); + findConstituentProviders(subsystem.getChildren(), requirement, capabilities); } - private void findRepositoryServiceProviders(Collection<Capability> capabilities, Requirement requirement, boolean content) { - Collection<Repository> repositories = Activator.getRepositories(); - for (Repository repository : repositories) { - for (Capability capability : repository.findProviders(requirement)) { - capabilities.add(capability); - resourceToRepository.put(capability.getResource(), repository); - if (content) - resources.add(capability.getResource()); - } + private void findConstituentProviders(Collection<Subsystem> children, Requirement requirement, Collection<Capability> capabilities) { + for (Subsystem child : children) { + findConstituentProviders(child, requirement, capabilities); } } - private void findTransitiveDependencyProviders(Requirement requirement, Collection<Capability> capabilities) { - Subsystem subsystem = this.subsystem; + private void findArchiveProviders(Collection<Capability> capabilities, Requirement requirement, boolean content) { + AriesSubsystem subsystem = this.subsystem; while (subsystem.getParent() != null) { subsystem = subsystem.getParent(); } - findTransitiveDependencyProviders(subsystem.getChildren(), requirement, capabilities); + findArchiveProviders(capabilities, requirement, subsystem, content); } - private void findTransitiveDependencyProviders(Subsystem subsystem, Requirement requirement, Collection<Capability> capabilities) { - for (Resource resource : subsystem.getConstituents()) { - for (Capability capability : resource.getCapabilities(requirement.getNamespace())) { - if (requirement.matches(capability)) { - capabilities.add(capability); - } + private void findArchiveProviders(Collection<Capability> capabilities, Requirement requirement, AriesSubsystem subsystem, boolean content) { + Archive archive = subsystem.getArchive(); + // Archive will be null for the root subsystem and for any subsystem that had no content resources included in the archive. + if (archive != null) { + for (Capability capability : archive.findProviders(requirement)) { + capabilities.add(capability); + resourceToRepository.put(capability.getResource(), archive); + if (content) + resources.add(capability.getResource()); } } - findTransitiveDependencyProviders(subsystem.getChildren(), requirement, capabilities); + findArchiveProviders(capabilities, requirement, subsystem.getChildren(), content); } - private void findTransitiveDependencyProviders(Collection<Subsystem> children, Requirement requirement, Collection<Capability> capabilities) { + private void findArchiveProviders(Collection<Capability> capabilities, Requirement requirement, Collection<Subsystem> children, boolean content) { for (Subsystem child : children) { - findTransitiveDependencyProviders(child, requirement, capabilities); + findArchiveProviders(capabilities, requirement, (AriesSubsystem)child, content); + } + } + +// private void findContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement) { +// findArchiveProviders(capabilities, requirement); +// findRepositoryServiceProviders(capabilities, requirement, !requirement.isTransitiveDependency()); +// } + +// private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement) { +// Subsystem subsystem = this.subsystem; +// while (subsystem.getParent() != null && "osgi.feature".equals(subsystem.getParent().getHeaders().get("Subsystem-Type"))) // TODO Add to constants. +// subsystem = subsystem.getParent(); +// findFeatureContentProviders(capabilities, requirement, subsystem); +// } +// +// private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement, Subsystem subsystem) { +// for (Resource resource : subsystem.getConstituents()) { +// for (Capability capability : resource.getCapabilities(requirement.getNamespace())) { +// if (requirement.matches(capability)) { +// capabilities.add(capability); +// resourceToRepository.put(capability.getResource(), repository); +// resources.add(capability.getResource()); +// } +// } +// } +// findFeatureContentProviders(capabilities, requirement, subsystem.getChildren()); +// } +// +// private void findFeatureContentProviders(Collection<Capability> capabilities, OsgiIdentityRequirement requirement, Collection<Subsystem> subsystems) { +// for (Subsystem subsystem : subsystems) +// if ("osgi.feature".equals(subsystem.getParent().getHeaders().get("Subsystem-Type"))) // TODO Add to constants. +// findFeatureContentProviders(capabilities, requirement, subsystem); +// } + + private void findRepositoryServiceProviders(Collection<Capability> capabilities, Requirement requirement, boolean content) { + Collection<Repository> repositories = Activator.getRepositories(); + for (Repository repository : repositories) { + for (Capability capability : repository.findProviders(requirement)) { + capabilities.add(capability); + resourceToRepository.put(capability.getResource(), repository); + if (content) + resources.add(capability.getResource()); + } } } }
Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java?rev=1162585&view=auto ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java (added) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java Sun Aug 28 20:39:09 2011 @@ -0,0 +1,105 @@ +/* + * 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.core.obr; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.aries.subsystem.core.internal.Activator; +import org.apache.aries.subsystem.core.internal.OsgiIdentityRequirement; +import org.apache.aries.subsystem.core.obr.felix.FelixResourceAdapter; +import org.apache.aries.subsystem.core.obr.felix.OsgiResourceAdapter; +import org.apache.felix.bundlerepository.Reason; +import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.Requirement; +import org.osgi.framework.wiring.Resource; +import org.osgi.framework.wiring.Wire; +import org.osgi.service.resolver.Environment; +import org.osgi.service.resolver.ResolutionException; +import org.osgi.service.resolver.Resolver; +import org.osgi.service.subsystem.SubsystemException; + +public class SubsystemResolver implements Resolver { + private static void addCapabilities(Collection<Capability> capabilities, Environment environment, Requirement requirement) { + Collection<Capability> caps = environment.findProviders(requirement); + if (caps.isEmpty()) + return; + Capability capability = caps.iterator().next(); + capabilities.add(capability); + addCapabilities(capabilities, environment, capability.getResource().getRequirements(null)); + } + + private static void addCapabilities(Collection<Capability> capabilities, Environment environment, List<Requirement> requirements) { + for (Requirement requirement : requirements) { + addCapabilities(capabilities, environment, requirement); + } + } + @Override + public Map<Resource, List<Wire>> resolve(Environment environment, Requirement... requirements) throws ResolutionException { + Collection<Capability> capabilities = new ArrayList<Capability>(); + /* + * TODO Until an implementation of Resolver comes along, need to find as many resources with capabilities satisfying as + * many requirements as possible. This is because the Felix OBR resolver does not make use of this environment. In particular, + * we need to add resources that come from subsystem archives or constituents as these will not be available otherwise. + */ + for (Requirement requirement : requirements) +// capabilities.addAll(environment.findProviders(requirement)); + addCapabilities(capabilities, environment, requirement); + List<Resource> resources = new ArrayList<Resource>(capabilities.size()); + for (Capability capability : capabilities) + resources.add(capability.getResource()); + org.apache.felix.bundlerepository.Resolver resolver = Activator.getRepositoryAdmin().resolver(); + for (Resource resource : resources) + resolver.add(new OsgiResourceAdapter(resource)); + if (resolver.resolve()) { + /* + * TODO For now, these need to go back through the environment in order to be sure the URL is available. + * This is because RepositoryAdmin is not going through the environment as part of pulling in transitive + * dependencies. Once a "real" Resolver is available, this will no longer be necessary. + */ + for (org.apache.felix.bundlerepository.Resource resource : resolver.getRequiredResources()) { + Resource r = new FelixResourceAdapter(resource); + // Make the environment aware of the resource and its URL. + environment.findProviders(new OsgiIdentityRequirement(r, true)); + resources.add(r); + } + for (org.apache.felix.bundlerepository.Resource resource : resolver.getOptionalResources()) { + Resource r = new FelixResourceAdapter(resource); + // Make the environment aware of the resource and its URL. + environment.findProviders(new OsgiIdentityRequirement(r, true)); + resources.add(r); + } + } + else { + Reason[] reasons = resolver.getUnsatisfiedRequirements(); + StringBuilder builder = new StringBuilder("Failed to resolve subsystem").append(System.getProperty("line.separator")); + for (Reason reason : reasons) + builder + .append("resource = ") + .append(reason.getResource().getSymbolicName()) + .append(", requirement = ") + .append(reason.getRequirement().getName()) + .append(System.getProperty("line.separator")); + throw new SubsystemException(builder.toString()); + } + Map<Resource, List<Wire>> result = new HashMap<Resource, List<Wire>>(resources.size()); + for (Resource resource : resources) + result.put(resource, Collections.EMPTY_LIST); + return result; + } +} Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java Sun Aug 28 20:39:09 2011 @@ -17,15 +17,14 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.jar.JarInputStream; import java.util.jar.Manifest; +import org.apache.aries.subsystem.core.archive.BundleManifest; +import org.apache.aries.subsystem.core.archive.ExportPackageHeader; import org.apache.aries.subsystem.core.archive.ImportPackageHeader; -import org.apache.aries.subsystem.core.internal.OsgiContentCapability; import org.apache.aries.subsystem.core.internal.OsgiIdentityCapability; -import org.osgi.framework.Constants; import org.osgi.framework.wiring.Capability; import org.osgi.framework.wiring.Requirement; import org.osgi.framework.wiring.Resource; @@ -34,12 +33,12 @@ public class BundleResource implements R public static BundleResource newInstance(URL content) throws IOException { BundleResource result = new BundleResource(content); result.capabilities.add(new OsgiIdentityCapability(result, result.manifest)); - result.capabilities.add(new OsgiContentCapability(result, content)); return result; } private final List<Capability> capabilities = new ArrayList<Capability>(); - private final Manifest manifest; + private final BundleManifest manifest; + private final List<Requirement> requirements = new ArrayList<Requirement>(); private BundleResource(InputStream content) throws IOException { JarInputStream jis = new JarInputStream(content); @@ -47,7 +46,7 @@ public class BundleResource implements R Manifest manifest = jis.getManifest(); if (manifest == null) throw new IllegalArgumentException("The jar file contained no manifest"); - this.manifest = manifest; + this.manifest = new BundleManifest(manifest); } finally { try { @@ -55,6 +54,14 @@ public class BundleResource implements R } catch (IOException e) {} } + ExportPackageHeader eph = (ExportPackageHeader)manifest.getHeader(ExportPackageHeader.NAME); + if (eph != null) { + capabilities.addAll(eph.getCapabilities(this)); + } + ImportPackageHeader iph = (ImportPackageHeader)manifest.getHeader(ImportPackageHeader.NAME); + if (iph != null) { + requirements.addAll(iph.getRequirements(this)); + } } private BundleResource(URL content) throws IOException { @@ -79,16 +86,11 @@ public class BundleResource implements R } public List<Capability> getCapabilities(String namespace) { - if (namespace == null) { - return Collections.unmodifiableList(capabilities); - } ArrayList<Capability> result = new ArrayList<Capability>(capabilities.size()); for (Capability capability : capabilities) { - if (namespace.equals(capability.getNamespace())) { + if (namespace == null || namespace.equals(capability.getNamespace())) result.add(capability); - } } - result.trimToSize(); return result; } @@ -100,10 +102,9 @@ public class BundleResource implements R * Fragment-Host */ ArrayList<Requirement> result = new ArrayList<Requirement>(); - String importPackageHeaderStr = manifest.getMainAttributes().getValue(Constants.IMPORT_PACKAGE); - if (importPackageHeaderStr != null) { - ImportPackageHeader header = new ImportPackageHeader(importPackageHeaderStr); - result.addAll(header.getRequirements(this)); + for (Requirement requirement : requirements) { + if (namespace == null || namespace.equals(requirement.getNamespace())) + result.add(requirement); } return result; } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java Sun Aug 28 20:39:09 2011 @@ -19,24 +19,14 @@ import java.net.URISyntaxException; import java.net.URL; import org.osgi.framework.wiring.Resource; +import org.osgi.service.subsystem.SubsystemException; public class ResourceFactory { public Resource newResource(URL url) throws IOException, URISyntaxException { - File file = new File(url.toURI()); - if (file.exists()) - return newResource(file); - // TODO What next? - throw new IllegalArgumentException("Unsupported resource type: " + url); - } - - public Resource newResource(File file) throws IOException, URISyntaxException { - String name = file.getName(); - if (name.endsWith(".jar")) { - return BundleResource.newInstance(file.toURI().toURL()); - } - if (name.endsWith(".ssa")) { - return SubsystemResource.newInstance(file); - } - throw new IllegalArgumentException("Unsupported resource type: " + name); + if (url.getPath().endsWith(".jar")) + return BundleResource.newInstance(url); + if (url.getPath().endsWith(".ssa")) + return SubsystemResource.newInstance(new File(url.toURI())); + throw new SubsystemException("Unsupported resource type: " + url); } } Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java Sun Aug 28 20:39:09 2011 @@ -30,6 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.junit.JUnit4TestRunner; import org.osgi.service.subsystem.Subsystem; +import org.osgi.service.subsystem.SubsystemConstants; @RunWith(JUnit4TestRunner.class) public class FeatureTest extends SubsystemTest { @@ -71,19 +72,47 @@ public class FeatureTest extends Subsyst @Test public void testFeature1() throws Exception { Subsystem subsystem = installSubsystemFromFile("feature1.ssa"); + AssertionError error = null; try { assertSymbolicName("org.apache.aries.subsystem.feature1", subsystem); assertVersion("1.0.0", subsystem); - assertConstituents(3, subsystem); + assertConstituents(4, subsystem); + assertChildren(1, subsystem); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.INSTALLING, SubsystemConstants.EventType.INSTALLING, 5000); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.INSTALLED, SubsystemConstants.EventType.INSTALLED, 5000); + assertSymbolicName("org.apache.aries.subsystem.feature2", subsystem.getChildren().iterator().next()); + assertVersion("1.0.0", subsystem.getChildren().iterator().next()); + assertConstituents(1, subsystem.getChildren().iterator().next()); // TODO Test internal events for installation. startSubsystem(subsystem); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVING, SubsystemConstants.EventType.RESOLVING, 5000); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVED, SubsystemConstants.EventType.RESOLVED, 5000); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.STARTING, SubsystemConstants.EventType.STARTING, 5000); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.ACTIVE, SubsystemConstants.EventType.STARTED, 5000); // TODO Test internal events for starting. stopSubsystem(subsystem); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.STOPPING, SubsystemConstants.EventType.STOPPING, 5000); + assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVED, SubsystemConstants.EventType.STOPPED, 5000); // TODO Test internal events for stopping. } + catch (AssertionError e) { + error = e; + throw e; + } finally { - uninstallSubsystem(subsystem); - // TODO Test internal events for uninstalling. + try { + Subsystem child = subsystem.getChildren().iterator().next(); + uninstallSubsystem(subsystem); + assertEvent(child, Subsystem.State.UNINSTALLING, SubsystemConstants.EventType.UNINSTALLING, 5000); + assertEvent(child, Subsystem.State.UNINSTALLED, SubsystemConstants.EventType.UNINSTALLED, 5000); + // TODO Test internal events for uninstalling. + assertNotChild(subsystem, child); + } + catch (AssertionError e) { + if (error == null) + throw e; + e.printStackTrace(); + } } } } Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java Sun Aug 28 20:39:09 2011 @@ -18,6 +18,7 @@ */ package org.apache.aries.subsystem.itests; +import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.io.File; @@ -71,20 +72,9 @@ public class InstallTest extends Subsyst } @Test - public void testRejectSubsystemWithExistingLocation() throws Exception { - Subsystem subsystem = installSubsystemFromFile("feature1.ssa"); - try { - installSubsystemFromFile("feature1.ssa"); - fail("SubsystemException should have been thrown"); - } - catch (SubsystemException e) { - // Pass. - } - catch (Throwable t) { - fail("SubsystemException should have been thrown"); - } - finally { - uninstallSubsystem(subsystem); - } + public void testReturnExistingSubsystemWithSameLocation() throws Exception { + Subsystem subsystem1 = installSubsystemFromFile("feature1.ssa"); + Subsystem subsystem2 = subsystem1.install(subsystem1.getLocation()); + assertSame(subsystem1, subsystem2); } } Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java Sun Aug 28 20:39:09 2011 @@ -1,3 +1,16 @@ +/* + * 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; @@ -16,8 +29,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Dictionary; import java.util.EnumSet; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; +import java.util.Map; import org.apache.aries.subsystem.core.obr.felix.RepositoryAdminRepository; import org.apache.aries.subsystem.itests.util.RepositoryGenerator; @@ -35,40 +50,61 @@ import org.osgi.service.repository.Repos import org.osgi.service.subsystem.Subsystem; import org.osgi.service.subsystem.Subsystem.State; import org.osgi.service.subsystem.SubsystemConstants; +import org.osgi.service.subsystem.SubsystemConstants.EventType; public abstract class SubsystemTest extends IntegrationTest { protected static class SubsystemTestEventHandler implements EventHandler { - private final List<Event> events = new ArrayList<Event>(); + private final Map<Long, List<Event>> subsystemIdToEvents = new HashMap<Long, List<Event>>(); - public synchronized void clear() { - events.clear(); - } - - public synchronized Event get() { - if (events.isEmpty()) { - return null; + public void clear() { + synchronized (subsystemIdToEvents) { + subsystemIdToEvents.clear(); } - return events.remove(0); } - public synchronized void handleEvent(Event event) { - events.add(event); - notifyAll(); + public void handleEvent(Event event) { + Long subsystemId = (Long)event.getProperty(SubsystemConstants.SUBSYSTEM_ID); + synchronized (subsystemIdToEvents) { + List <Event> events = subsystemIdToEvents.get(subsystemId); + if (events == null) { + events = new ArrayList<Event>(); + subsystemIdToEvents.put(subsystemId, events); + } + synchronized (events) { + events.add(event); + events.notify(); + } + } } - public synchronized Event poll() throws InterruptedException { - return poll(0); + public Event poll(long subsystemId) throws InterruptedException { + return poll(subsystemId, 0); } - public synchronized Event poll(long timeout) throws InterruptedException { - if (events.isEmpty()) { - wait(timeout); + public Event poll(long subsystemId, long timeout) throws InterruptedException { + List<Event> events; + synchronized (subsystemIdToEvents) { + events = subsystemIdToEvents.get(subsystemId); + if (events == null) { + events = new ArrayList<Event>(); + subsystemIdToEvents.put(subsystemId, events); + } + } + synchronized (events) { + if (events.isEmpty()) { + events.wait(timeout); + if (events.isEmpty()) { + return null; + } + } + return events.remove(0); } - return get(); } - public synchronized int size() { - return events.size(); + public int size() { + synchronized (subsystemIdToEvents) { + return subsystemIdToEvents.size(); + } } } @@ -141,6 +177,10 @@ public abstract class SubsystemTest exte 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)); } @@ -149,10 +189,6 @@ public abstract class SubsystemTest exte assertEquals("Wrong number of constituents", size, subsystem.getConstituents().size()); } - protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemConstants.EventType type, Event event) { - assertEvent(subsystem, state, type, event, null); - } - protected void assertDirectory(Subsystem subsystem) { Bundle bundle = getSubsystemCoreBundle(); File file = bundle.getDataFile("subsystem" + subsystem.getSubsystemId()); @@ -166,14 +202,28 @@ public abstract class SubsystemTest exte assertNotNull("Subsystem data file was null", file); assertFalse("Subsystem data file exists", file.exists()); } + + protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemConstants.EventType type) throws InterruptedException { + assertEvent(subsystem, state, type, 0); + } + + protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemConstants.EventType type, long timeout) throws InterruptedException { + assertEvent(subsystem, state, type, subsystemEvents.poll(subsystem.getSubsystemId(), timeout)); + } + + protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemConstants.EventType type, Event event) { + assertEvent(subsystem, state, type, event, null); + } protected void assertEvent(Subsystem subsystem, Subsystem.State state, SubsystemConstants.EventType type, Event event, Throwable throwable) { assertNotNull("The event was null", event); assertTrue("Wrong topic: " + event.getTopic(), event.getTopic().endsWith(type.name())); assertEquals("Wrong ID", subsystem.getSubsystemId(), event.getProperty(SubsystemConstants.SUBSYSTEM_ID)); assertEquals("Wrong location", subsystem.getLocation(), event.getProperty(SubsystemConstants.SUBSYSTEM_LOCATION)); - assertEquals("Wrong symbolic name", subsystem.getSymbolicName(), event.getProperty(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME)); - assertEquals("Wrong version", String.valueOf(subsystem.getVersion()), event.getProperty(SubsystemConstants.SUBSYSTEM_VERSION)); + if (!EventType.INSTALLING.equals(type)) { + assertEquals("Wrong symbolic name", subsystem.getSymbolicName(), event.getProperty(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME)); + assertEquals("Wrong version", String.valueOf(subsystem.getVersion()), event.getProperty(SubsystemConstants.SUBSYSTEM_VERSION)); + } assertEquals("Wrong state", String.valueOf(state), event.getProperty("subsystem.state")); assertNotNull("Missing timestamp", event.getProperty(EventConstants.TIMESTAMP)); if (throwable == null) { @@ -234,24 +284,24 @@ public abstract class SubsystemTest exte 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, SubsystemConstants.EventType.INSTALLING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.INSTALLED, SubsystemConstants.EventType.INSTALLED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.INSTALLING, SubsystemConstants.EventType.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.INSTALLED, SubsystemConstants.EventType.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, SubsystemConstants.EventType.RESOLVING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.RESOLVED, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.STARTING, SubsystemConstants.EventType.STARTING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.ACTIVE, SubsystemConstants.EventType.STARTED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.RESOLVING, SubsystemConstants.EventType.RESOLVING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.STARTING, SubsystemConstants.EventType.STARTING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.ACTIVE, SubsystemConstants.EventType.STARTED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); subsystem.stop(); assertState(EnumSet.of(State.STOPPING, State.RESOLVED), subsystem.getState()); - assertEvent(subsystem, Subsystem.State.STOPPING, SubsystemConstants.EventType.STOPPING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.STOPPED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.STOPPING, SubsystemConstants.EventType.STOPPING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.STOPPED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); // TODO Add update. subsystem.uninstall(); assertState(EnumSet.of(State.UNINSTALLING, State.UNINSTALLED), subsystem.getState()); - assertEvent(subsystem, Subsystem.State.UNINSTALLING, SubsystemConstants.EventType.UNINSTALLING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.UNINSTALLED, SubsystemConstants.EventType.UNINSTALLED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.UNINSTALLING, SubsystemConstants.EventType.UNINSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.UNINSTALLED, SubsystemConstants.EventType.UNINSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); assertNotChild(rootSubsystem, subsystem); return subsystem; } @@ -308,6 +358,8 @@ public abstract class SubsystemTest exte subsystemEvents.clear(); Subsystem subsystem = rootSubsystem.install(location, content); assertSubsystemNotNull(subsystem); + assertEvent(subsystem, Subsystem.State.INSTALLING, SubsystemConstants.EventType.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.INSTALLED, SubsystemConstants.EventType.INSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); assertChild(parent, subsystem); assertLocation(location, subsystem); assertParent(parent, subsystem); @@ -315,8 +367,6 @@ public abstract class SubsystemTest exte assertLocation(location, subsystem); assertId(subsystem); assertDirectory(subsystem); - assertEvent(subsystem, Subsystem.State.INSTALLING, SubsystemConstants.EventType.INSTALLING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.INSTALLED, SubsystemConstants.EventType.INSTALLED, subsystemEvents.poll(5000)); assertState(State.INSTALLED, subsystem); return subsystem; } @@ -326,10 +376,10 @@ public abstract class SubsystemTest exte subsystemEvents.clear(); subsystem.start(); assertState(EnumSet.of(State.RESOLVING, State.RESOLVED, State.STARTING, State.ACTIVE), subsystem); - assertEvent(subsystem, Subsystem.State.RESOLVING, SubsystemConstants.EventType.RESOLVING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.RESOLVED, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.STARTING, SubsystemConstants.EventType.STARTING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.ACTIVE, SubsystemConstants.EventType.STARTED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.RESOLVING, SubsystemConstants.EventType.RESOLVING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.STARTING, SubsystemConstants.EventType.STARTING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.ACTIVE, SubsystemConstants.EventType.STARTED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); assertState(State.ACTIVE, subsystem); } @@ -338,20 +388,22 @@ public abstract class SubsystemTest exte subsystemEvents.clear(); subsystem.stop(); assertState(EnumSet.of(State.STOPPING, State.RESOLVED), subsystem); - assertEvent(subsystem, Subsystem.State.STOPPING, SubsystemConstants.EventType.STOPPING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.STOPPED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.STOPPING, SubsystemConstants.EventType.STOPPING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.RESOLVED, SubsystemConstants.EventType.STOPPED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); assertState(State.RESOLVED, subsystem); } protected void uninstallSubsystem(Subsystem subsystem) throws Exception { assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), subsystem); subsystemEvents.clear(); + Subsystem parent = subsystem.getParent(); subsystem.uninstall(); assertState(EnumSet.of(State.UNINSTALLED, State.UNINSTALLING), subsystem); - assertEvent(subsystem, Subsystem.State.UNINSTALLING, SubsystemConstants.EventType.UNINSTALLING, subsystemEvents.poll(5000)); - assertEvent(subsystem, Subsystem.State.UNINSTALLED, SubsystemConstants.EventType.UNINSTALLED, subsystemEvents.poll(5000)); + assertEvent(subsystem, Subsystem.State.UNINSTALLING, SubsystemConstants.EventType.UNINSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); + assertEvent(subsystem, Subsystem.State.UNINSTALLED, SubsystemConstants.EventType.UNINSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000)); assertState(State.UNINSTALLED, subsystem); - assertNotChild(rootSubsystem, subsystem); + assertConstituents(0, subsystem); + assertNotChild(parent, subsystem); assertNotDirectory(subsystem); } } Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/util/Utils.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/util/Utils.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/util/Utils.java (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/util/Utils.java Sun Aug 28 20:39:09 2011 @@ -1,3 +1,16 @@ +/* + * 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.util; import java.io.Closeable; Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java Sun Aug 28 20:39:09 2011 @@ -1,3 +1,16 @@ +/* + * 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.ops4j.pax.runner.platform.equinox.internal; import org.ops4j.pax.runner.platform.PlatformBuilder; Added: aries/trunk/subsystem/subsystem-itests/src/test/resources/application1/tb1.jar URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/application1/tb1.jar?rev=1162585&view=auto ============================================================================== Binary file - no diff available. Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/application1/tb1.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Modified: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF (original) +++ aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF Sun Aug 28 20:39:09 2011 @@ -4,5 +4,8 @@ Subsystem-SymbolicName: org.apache.aries Subsystem-Version: 1.0.0 Subsystem-Name: %feature1.name Subsystem-Description: %feature1.description -Subsystem-Content: org.apache.aries.subsystem.itests.tb1,derby;version=10.5.0,org.apache.felix.fileinstall;version="[2.0,3.0)" +Subsystem-Content: org.apache.aries.subsystem.itests.tb1, + derby;version=10.5.0, + org.apache.felix.fileinstall;version="[2.0,3.0)", + org.apache.aries.subsystem.feature2;version=1.0.0;type=osgi.subsystem;start-order:=2 Subsystem-Type: osgi.feature Added: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/tb1.jar URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/tb1.jar?rev=1162585&view=auto ============================================================================== Binary file - no diff available. Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/tb1.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/tb2.jar URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/tb2.jar?rev=1162585&view=auto ============================================================================== Binary file - no diff available. Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/tb2.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream
