Return-Path: X-Original-To: apmail-aries-commits-archive@www.apache.org Delivered-To: apmail-aries-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1EEF5853A for ; Sun, 28 Aug 2011 20:39:46 +0000 (UTC) Received: (qmail 50375 invoked by uid 500); 28 Aug 2011 20:39:45 -0000 Delivered-To: apmail-aries-commits-archive@aries.apache.org Received: (qmail 50320 invoked by uid 500); 28 Aug 2011 20:39:45 -0000 Mailing-List: contact commits-help@aries.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aries.apache.org Delivered-To: mailing list commits@aries.apache.org Received: (qmail 50312 invoked by uid 99); 28 Aug 2011 20:39:45 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 28 Aug 2011 20:39:45 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 28 Aug 2011 20:39:35 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 288EF238897D; Sun, 28 Aug 2011 20:39:12 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1162585 [1/2] - in /aries/trunk/subsystem: subsystem-api/src/main/java/org/apache/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-core/... Date: Sun, 28 Aug 2011 20:39:10 -0000 To: commits@aries.apache.org From: jwross@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110828203912.288EF238897D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jwross Date: Sun Aug 28 20:39:09 2011 New Revision: 1162585 URL: http://svn.apache.org/viewvc?rev=1162585&view=rev Log: ARIES-737: Provide initial support for embedded subsystems. Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java aries/trunk/subsystem/subsystem-itests/src/test/resources/application1/tb1.jar (with props) aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/tb1.jar (with props) aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/tb2.jar (with props) Modified: aries/trunk/subsystem/subsystem-api/src/main/java/org/apache/ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemFactory.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManager.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/ArchiveRepository.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/AbstractRuntimeResource.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleRuntimeResource.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceListener.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResource.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResourceFactory.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResourceFactoryImpl.java aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/SubsystemRuntimeResource.java aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/util/Utils.java aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java Sun Aug 28 20:39:09 2011 @@ -19,7 +19,7 @@ public abstract class AbstractAttribute } public StringBuilder appendToFilter(StringBuilder builder) { - return builder.append(getName()).append('=').append(getValue()); + return builder.append('(').append(getName()).append('=').append(getValue()).append(')'); } public String toString() { Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java Sun Aug 28 20:39:09 2011 @@ -23,20 +23,25 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.apache.aries.subsystem.core.resource.ResourceFactory; +import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.Requirement; import org.osgi.framework.wiring.Resource; +import org.osgi.service.repository.Repository; import org.osgi.service.subsystem.SubsystemException; -public class Archive { +public class Archive implements Repository { private DeploymentManifest deploymentManifest; private SubsystemManifest subsystemManifest; // private final DeploymentManifest deploymentManifest; private final File directory; - private final Collection resources = new ArrayList(); + private final Map resources = new HashMap(); // private final SubsystemManifest subsystemManifest; public Archive(String location, File dir, InputStream content) throws IOException, URISyntaxException { @@ -90,6 +95,21 @@ public class Archive { // deploymentManifest = new DeploymentManifest(file); // } + @Override + public Collection findProviders(Requirement requirement) { + Collection capabilities = new ArrayList(); + for (Resource resource : getResources()) + for (Capability capability : resource.getCapabilities(requirement.getNamespace())) + if (requirement.matches(capability)) + capabilities.add(capability); + return capabilities; + } + + @Override + public URL getContent(Resource resource) { + return resources.get(resource); + } + public synchronized DeploymentManifest getDeploymentManifest() { return deploymentManifest; } @@ -103,7 +123,7 @@ public class Archive { } public Collection getResources() { - return Collections.unmodifiableCollection(resources); + return Collections.unmodifiableCollection(resources.keySet()); } public Collection getResourceNames() { @@ -209,7 +229,7 @@ public class Archive { private void processResources() throws IOException, URISyntaxException { for (String name : getResourceNames()) { URL url = getURL(name); - resources.add(new ResourceFactory().newResource(url)); + resources.put(new ResourceFactory().newResource(url), url); } } } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java Sun Aug 28 20:39:09 2011 @@ -13,17 +13,8 @@ */ package org.apache.aries.subsystem.core.archive; -import java.io.IOException; -import java.io.InputStream; - -import org.osgi.framework.Constants; - public class BundleManifest extends Manifest { - public static final String IMPORT_PACKAGE = Constants.IMPORT_PACKAGE; - - public BundleManifest(InputStream in) throws IOException { - super(in); + public BundleManifest(java.util.jar.Manifest manifest) { + super(manifest); } - - } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java Sun Aug 28 20:39:09 2011 @@ -13,13 +13,12 @@ */ package org.apache.aries.subsystem.core.archive; -import org.osgi.framework.Constants; - public class DirectiveFactory { public static Directive createDirective(String name, String value) { - if (Constants.RESOLUTION_DIRECTIVE.equals(name)) { + if (ResolutionDirective.NAME.equals(name)) return ResolutionDirective.getInstance(value); - } + if (StartOrderDirective.NAME.equals(name)) + return new StartOrderDirective(value); return new GenericDirective(name, value); } } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java Sun Aug 28 20:39:09 2011 @@ -13,5 +13,66 @@ */ package org.apache.aries.subsystem.core.archive; -public class ExportPackageHeader { +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Constants; +import org.osgi.framework.Version; +import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.Resource; +import org.osgi.framework.wiring.ResourceConstants; + +public class ExportPackageHeader extends AbstractHeader { + public static final String NAME = Constants.EXPORT_PACKAGE; + + public ExportPackageHeader(String value) { + super(NAME, value); + } + + public List getCapabilities(final Resource resource) { + List capabilities = new ArrayList(clauses.size()); + for (final Clause clause : clauses) { + String[] exportedPackages = clause.getPath().split(";"); + for (final String exportedPackage : exportedPackages) { + capabilities.add(new Capability() { + @Override + public String getNamespace() { + return ResourceConstants.WIRING_PACKAGE_NAMESPACE; + } + + @Override + public Map getDirectives() { + Collection directives = clause.getDirectives(); + Map result = new HashMap(directives.size()); + for (Directive directive : directives) + result.put(directive.getName(), directive.getValue()); + return result; + } + + @Override + public Map getAttributes() { + Collection attributes = clause.getAttributes(); + Map result = new HashMap(attributes.size() + 1); + for (Attribute attribute : attributes) + result.put(attribute.getName(), attribute.getValue()); + // Add the namespace attribute. + result.put(ResourceConstants.WIRING_PACKAGE_NAMESPACE, exportedPackage); + // Add the default version, if necessary. + if (result.get(Constants.VERSION_ATTRIBUTE) == null) + result.put(Constants.VERSION_ATTRIBUTE, Version.emptyVersion); + return result; + } + + @Override + public Resource getResource() { + return resource; + } + }); + } + } + return capabilities; + } } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java Sun Aug 28 20:39:09 2011 @@ -85,9 +85,12 @@ public class HeaderFactory { return new SubsystemVersionHeader(value); if (name.equals(SubsystemContentHeader.NAME)) return new SubsystemContentHeader(value); - // TODO Add to constants. if (name.equals(SubsystemTypeHeader.NAME)) return new SubsystemTypeHeader(value); + if (ExportPackageHeader.NAME.equals(name)) + return new ExportPackageHeader(value); + if (ImportPackageHeader.NAME.equals(name)) + return new ImportPackageHeader(value); return new GenericHeader(name, value); } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java Sun Aug 28 20:39:09 2011 @@ -65,7 +65,7 @@ public class ImportPackageHeader impleme if (directive == null) { StringBuilder builder = new StringBuilder("(&"); for (Attribute a : getAttributes()) { - a.appendToFilter(builder.append('(')).append(')'); + a.appendToFilter(builder); } directive = new GenericDirective(Constants.FILTER_DIRECTIVE, builder.append(')').toString()); myParameters.put(directive.getName(), directive); @@ -186,6 +186,8 @@ public class ImportPackageHeader impleme } } + public static final String NAME = Constants.IMPORT_PACKAGE; + private static final String REGEX = '(' + Grammar.IMPORT + ")(?:\\,(" + Grammar.IMPORT + "))*"; private static final Pattern PATTERN = Pattern.compile(REGEX); Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java Sun Aug 28 20:39:09 2011 @@ -31,11 +31,17 @@ public abstract class Manifest { protected final java.util.jar.Manifest manifest; public Manifest(InputStream in) throws IOException { - manifest = ManifestProcessor.parseManifest(in); + this(ManifestProcessor.parseManifest(in)); + } + + public Manifest(java.util.jar.Manifest manifest) { + this.manifest = manifest; for (Map.Entry entry : manifest.getMainAttributes().entrySet()) { Header header = HeaderFactory.createHeader(String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); headers.put(header.getName(), header); } + if (headers.get(ManifestVersionHeader.NAME) == null) + headers.put(ManifestVersionHeader.NAME, ManifestVersionHeader.DEFAULT); } public Manifest(File manifestFile) throws IOException { Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java Sun Aug 28 20:39:09 2011 @@ -19,6 +19,8 @@ public class ManifestVersionHeader exten public static final String DEFAULT_VALUE = "1.0"; public static final String NAME = Attributes.Name.MANIFEST_VERSION.toString(); + public static final ManifestVersionHeader DEFAULT = new ManifestVersionHeader(DEFAULT_VALUE); + public ManifestVersionHeader() { this(DEFAULT_VALUE); } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java Sun Aug 28 20:39:09 2011 @@ -16,7 +16,7 @@ package org.apache.aries.subsystem.core. import org.osgi.framework.Constants; public class ResolutionDirective extends AbstractDirective { - public static final String NAME = "resolution"; + public static final String NAME = Constants.RESOLUTION_DIRECTIVE; public static final ResolutionDirective MANDATORY = new ResolutionDirective(true); public static final ResolutionDirective OPTIONAL = new ResolutionDirective(false); @@ -37,7 +37,7 @@ public class ResolutionDirective extends private final boolean mandatory; private ResolutionDirective(boolean mandatory) { - super(Constants.RESOLUTION_DIRECTIVE, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL); + super(NAME, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL); this.mandatory = mandatory; } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java Sun Aug 28 20:39:09 2011 @@ -16,6 +16,8 @@ package org.apache.aries.subsystem.core. import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; +import java.util.List; import org.osgi.framework.Constants; import org.osgi.framework.Version; @@ -25,20 +27,26 @@ public class SubsystemContentHeader exte public static class Content { private final boolean mandatory; private final String name; + private final int startOrder; private final String type; private final VersionRange versionRange; - public Content(boolean mandatory, String name, String type, VersionRange versionRange) { + public Content(boolean mandatory, String name, String type, VersionRange versionRange, int startOrder) { this.mandatory = mandatory; this.name = name; this.type = type; this.versionRange = versionRange; + this.startOrder = startOrder; } public String getName() { return name; } + public int getStartOrder() { + return startOrder; + } + public String getType() { return type; } @@ -65,6 +73,10 @@ public class SubsystemContentHeader exte .append(ResolutionDirective.NAME) .append(":=") .append(isMandatory()) + .append(';') + .append(StartOrderDirective.NAME) + .append(":=") + .append(getStartOrder()) .toString(); } } @@ -72,7 +84,7 @@ public class SubsystemContentHeader exte // TODO Add to constants. public static final String NAME = "Subsystem-Content"; - private final Collection contents; + private final List contents; public SubsystemContentHeader(String value) { super(NAME, value); @@ -93,8 +105,18 @@ public class SubsystemContentHeader exte if (attribute != null) { versionRange = new VersionRange(attribute.getValue()); } - contents.add(new Content(mandatory, name, type, versionRange)); + int startOrder = StartOrderDirective.DEFAULT_VALUE; + directive = clause.getDirective(StartOrderDirective.NAME); + if (directive != null) + startOrder = ((StartOrderDirective)directive).getStartOrder(); + contents.add(new Content(mandatory, name, type, versionRange, startOrder)); } + Collections.sort(contents, new Comparator() { + @Override + public int compare(Content content1, Content content2) { + return ((Integer)content1.getStartOrder()).compareTo(content2.getStartOrder()); + } + }); } public Collection getContents() { Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java Sun Aug 28 20:39:09 2011 @@ -15,17 +15,12 @@ package org.apache.aries.subsystem.core. import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Dictionary; -import java.util.HashMap; import java.util.Hashtable; import java.util.List; -import java.util.Map; import java.util.concurrent.Executor; -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.apache.aries.subsystem.core.obr.SubsystemResolver; import org.apache.felix.bundlerepository.RepositoryAdmin; import org.eclipse.equinox.region.RegionDigraph; import org.osgi.framework.BundleActivator; @@ -35,21 +30,14 @@ import org.osgi.framework.InvalidSyntaxE import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.hooks.resolver.ResolverHookFactory; -import org.osgi.framework.wiring.Capability; import org.osgi.framework.wiring.FrameworkWiring; -import org.osgi.framework.wiring.Requirement; -import org.osgi.framework.wiring.Resource; -import org.osgi.framework.wiring.Wire; import org.osgi.service.coordinator.Coordinator; import org.osgi.service.event.EventAdmin; import org.osgi.service.event.EventConstants; import org.osgi.service.event.EventHandler; import org.osgi.service.repository.Repository; -import org.osgi.service.resolver.Environment; -import org.osgi.service.resolver.ResolutionException; import org.osgi.service.resolver.Resolver; import org.osgi.service.subsystem.Subsystem; -import org.osgi.service.subsystem.SubsystemException; import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +50,6 @@ public class Activator implements Bundle private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class); private static BundleContext context; - private static SubsystemManager subsystemManager = new SubsystemManager(); public static BundleContext getBundleContext() { return context; @@ -129,59 +116,56 @@ public class Activator implements Bundle * A naive implementation serving as a placeholder until a real Resolver comes along. */ public static Resolver getResolver() { - return new Resolver() { - @Override - public Map> resolve(Environment environment, Requirement... requirements) throws ResolutionException { - Collection capabilities = new ArrayList(); - for (Requirement requirement : requirements) - capabilities.addAll(environment.findProviders(requirement)); - List resources = new ArrayList(capabilities.size()); - for (Capability capability : capabilities) - resources.add(capability.getResource()); - org.apache.felix.bundlerepository.Resolver resolver = 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> result = new HashMap>(resources.size()); - for (Resource resource : resources) - result.put(resource, Collections.EMPTY_LIST); - return result; - } - }; - } - - public static SubsystemManager getSubsystemManager() { - return subsystemManager; + return new SubsystemResolver(); +// return new Resolver() { +// @Override +// public Map> resolve(Environment environment, Requirement... requirements) throws ResolutionException { +// Collection capabilities = new ArrayList(); +// for (Requirement requirement : requirements) +// capabilities.addAll(environment.findProviders(requirement)); +// List resources = new ArrayList(capabilities.size()); +// for (Capability capability : capabilities) +// resources.add(capability.getResource()); +// org.apache.felix.bundlerepository.Resolver resolver = 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> result = new HashMap>(resources.size()); +// for (Resource resource : resources) +// result.put(resource, Collections.EMPTY_LIST); +// return result; +// } +// }; } private final BundleListener bundleListener = new SubsystemSynchronousBundleListener(); Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java Sun Aug 28 20:39:09 2011 @@ -14,20 +14,25 @@ package org.apache.aries.subsystem.core.internal; import java.io.File; +import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; +import org.apache.aries.subsystem.core.ResourceHelper; import org.apache.aries.subsystem.core.archive.Archive; import org.apache.aries.subsystem.core.archive.DeployedContentHeader; import org.apache.aries.subsystem.core.archive.DeployedContentHeader.DeployedContent; @@ -39,45 +44,49 @@ import org.apache.aries.subsystem.core.a import org.apache.aries.subsystem.core.archive.SubsystemSymbolicNameHeader; import org.apache.aries.subsystem.core.archive.VersionHeader; import org.apache.aries.subsystem.core.obr.SubsystemEnvironment; -import org.apache.aries.subsystem.core.resource.BundleRuntimeResource; -import org.apache.aries.subsystem.core.resource.RuntimeResource; -import org.apache.aries.subsystem.core.resource.RuntimeResourceFactoryImpl; import org.eclipse.equinox.region.Region; import org.eclipse.equinox.region.RegionFilter; import org.osgi.framework.Bundle; import org.osgi.framework.BundleEvent; import org.osgi.framework.BundleException; import org.osgi.framework.Version; +import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.Requirement; import org.osgi.framework.wiring.Resource; +import org.osgi.framework.wiring.ResourceConstants; import org.osgi.service.coordinator.Coordination; import org.osgi.service.coordinator.CoordinationException; +import org.osgi.service.coordinator.Participant; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; import org.osgi.service.event.EventConstants; import org.osgi.service.subsystem.Subsystem; import org.osgi.service.subsystem.SubsystemConstants; import org.osgi.service.subsystem.SubsystemException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class AriesSubsystem implements Subsystem { - public static AriesSubsystem newInstance(String location, InputStream content, AriesSubsystem parent) throws Exception { - AriesSubsystem subsystem = new AriesSubsystem(location, content, parent); - Archive archive = subsystem.getArchive(); - subsystem.environment = new SubsystemEnvironment(subsystem); - if (archive.getSubsystemManifest() == null) { - SubsystemUri uri = new SubsystemUri(location); - archive.setSubsystemManifest(SubsystemManifest.newInstance(uri.getSymbolicName(), uri.getVersion(), archive.getResources())); - } - if (archive.getDeploymentManifest() == null) { - archive.setDeploymentManifest(DeploymentManifest.newInstance(archive.getSubsystemManifest(), subsystem.environment)); - } - return subsystem; - } - +public class AriesSubsystem implements Subsystem, Resource { + private static final Logger LOGGER = LoggerFactory.getLogger(AriesSubsystem.class); private static final String ROOT_LOCATION = "root"; private static final String ROOT_SYMBOLIC_NAME = "org.apache.aries.subsystem.root"; private static final Version ROOT_VERSION = Version.parseVersion("1.0.0"); + private static final Map locationToSubsystem = new HashMap(); + private static final Map> resourceToSubsystems = new HashMap>(); + + static synchronized Collection getSubsystems(Resource resource) { + ArrayList result = new ArrayList(locationToSubsystem.size()); + for (AriesSubsystem subsystem : locationToSubsystem.values()) { + if (subsystem.contains(resource)) { + result.add(subsystem); + } + } + result.trimToSize(); + return result; + } + private static long lastId; private static void deleteFile(File file) { @@ -109,8 +118,14 @@ public class AriesSubsystem implements S Map map = new HashMap(); map.put(SubsystemConstants.SUBSYSTEM_ID, subsystem.getSubsystemId()); map.put(SubsystemConstants.SUBSYSTEM_LOCATION, subsystem.getLocation()); - map.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, subsystem.getSymbolicName()); - map.put(SubsystemConstants.SUBSYSTEM_VERSION, String.valueOf(subsystem.getVersion())); + try { + map.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, subsystem.getSymbolicName()); + } + catch (IllegalStateException e) {} + try { + map.put(SubsystemConstants.SUBSYSTEM_VERSION, String.valueOf(subsystem.getVersion())); + } + catch (IllegalStateException e) {} // TODO This needs to be defined as a constant. map.put("subsystem.state", String.valueOf(subsystem.getState())); map.put(EventConstants.TIMESTAMP, System.currentTimeMillis()); @@ -125,15 +140,15 @@ public class AriesSubsystem implements S } } - private final Archive archive; private final Set constituents = Collections.synchronizedSet(new HashSet()); - private final Set children = new HashSet(); + private final Set children = Collections.synchronizedSet(new HashSet()); private volatile SubsystemEnvironment environment; private final long id; private final String location; private final AriesSubsystem parent; - private final Region region; + private Archive archive; + private Region region; private Subsystem.State state; public AriesSubsystem() throws Exception { @@ -147,32 +162,10 @@ public class AriesSubsystem implements S environment = null; } - private AriesSubsystem(String location, InputStream content, AriesSubsystem parent) throws Exception { + private AriesSubsystem(String location, /*InputStream content,*/ AriesSubsystem parent) /*throws Exception*/ { this.location = location; this.parent = parent; - if (content == null) { - content = new URL(location).openStream(); - } - File rootDirectory = Activator.getBundleContext().getDataFile(""); id = getNextId(); - File subsystemDirectory = new File(rootDirectory, "subsystem" + id + System.getProperty("file.separator")); - // TODO Leaking reference. Issues? -// environment = new SubsystemEnvironment(this); -// archive = new Archive(location, subsystemDirectory, content, environment); - archive = new Archive(location, subsystemDirectory, content); - if (isFeature()) { - // Features do not have regions. - region = null; - } - else { - // Applications and composites have regions. - region = createRegion(); - } - - } - - public void addConstituent(Resource resource) { - constituents.add(resource); } @Override @@ -180,10 +173,16 @@ public class AriesSubsystem implements S // TODO Auto-generated method stub } - public Archive getArchive() { + public synchronized Archive getArchive() { return archive; } + @Override + public List getCapabilities(String namespace) { + Capability capability = new OsgiIdentityCapability(this, getSymbolicName(), getVersion(), "osgi.subsystem"); + return Arrays.asList(new Capability[]{capability}); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) public Collection getChildren() { return (Collection)(Collection)Collections.unmodifiableSet(children); @@ -191,10 +190,36 @@ public class AriesSubsystem implements S @Override public Collection getConstituents() { - return Collections.unmodifiableSet(constituents); + /* + * TODO The definition of constituents needs to be worked out from both a design and implementation perspective. + * (1) In general, any Resource type except for osgi.subsystem. + * (2) A transitive dependency if this is the root subsystem or provision-policy:=acceptTransitive. + * (3) A content Resource of this subsystem if the Resource is not also a subsystem (also, doesn't apply to + * the root subsystem since it has no content resources). + * (4) A bundle Resource installed into a region by means other than the subsystem API (primarily for the + * root subsystem which shares the kernel region but could apply to any subsystem). + * (5) Caution with 4: this does not include feature content resources installed into a non-feature subsystem region. + * These are constituents of the feature itself. + */ + if (isRoot()) { + // TODO This does not take into account the possibility that resource types other than bundle became part of the root subsystem. + Set bundleIds = region.getBundleIds(); + Collection resources = new ArrayList(bundleIds.size()); + for (Long bundleId : bundleIds) + resources.add(Activator.getBundleContext().getBundle(bundleId).adapt(BundleRevision.class)); + return resources; + } + return Collections.unmodifiableCollection(constituents); } - public SubsystemEnvironment getEnvironment() { + public DeploymentManifest getDeploymentManifest() throws IOException { + if (archive.getDeploymentManifest() == null) { + archive.setDeploymentManifest(DeploymentManifest.newInstance(archive.getSubsystemManifest(), environment)); + } + return archive.getDeploymentManifest(); + } + + public synchronized SubsystemEnvironment getEnvironment() { return environment; } @@ -219,7 +244,7 @@ public class AriesSubsystem implements S Map result = new HashMap(headers.size()); for (Header header : headers) { String value = header.getValue(); - if (value.startsWith("%")) { + if (rb != null && value.startsWith("%")) { value = value.substring(1); String translation = null; try { @@ -243,9 +268,10 @@ public class AriesSubsystem implements S public AriesSubsystem getParent() { return parent; } - - public Region getRegion() { - return region; + + @Override + public List getRequirements(String namespace) { + return Collections.emptyList(); } @Override @@ -261,6 +287,11 @@ public class AriesSubsystem implements S @Override public String getSymbolicName() { if (archive == null) { + // If the archive is null, this is either the root subsystem or an installing subsystem not yet initialized. + if (State.INSTALLING.equals(getState())) + // The root subsystem's state will never be INSTALLING, so this is an uninitialized subsystem. + throw new IllegalStateException(); + // This is the root subsystem. return ROOT_SYMBOLIC_NAME; } return ((SubsystemSymbolicNameHeader)archive.getSubsystemManifest().getSubsystemSymbolicName()).getSymbolicName(); @@ -269,6 +300,11 @@ public class AriesSubsystem implements S @Override public Version getVersion() { if (archive == null) { + // If the archive is null, this is either the root subsystem or an installing subsystem not yet initialized. + if (State.INSTALLING.equals(getState())) + // The root subsystem's state will never be INSTALLING, so this is an uninitialized subsystem. + throw new IllegalStateException(); + // This is the root subsystem. return ROOT_VERSION; } return ((VersionHeader)archive.getSubsystemManifest().getSubsystemVersion()).getVersion(); @@ -280,21 +316,23 @@ public class AriesSubsystem implements S } @Override - public Subsystem install(String location, InputStream content) throws SubsystemException { + public synchronized Subsystem install(String location, final InputStream content) throws SubsystemException { final AriesSubsystem subsystem; - try { - subsystem = Activator.getSubsystemManager().newSubsystem(location, content, this); - } - catch (Exception e) { - throw new SubsystemException(e); - } - children.add(subsystem); + if (locationToSubsystem.containsKey(location)) + return locationToSubsystem.get(location); + subsystem = new AriesSubsystem(location, this); + locationToSubsystem.put(location, subsystem); subsystem.setState(Subsystem.State.INSTALLING); postEvent(subsystem, SubsystemConstants.EventType.INSTALLING); + children.add(subsystem); + constituents.add(subsystem); Activator.getExecutor().execute(new Runnable() { public void run() { try { - subsystem.installAsync(); + subsystem.initialize(content); + subsystem.install(); + subsystem.setState(Subsystem.State.INSTALLED); + postEvent(subsystem, SubsystemConstants.EventType.INSTALLED); } catch (Exception e) { postEvent(subsystem, SubsystemConstants.EventType.FAILED, e); @@ -321,11 +359,8 @@ public class AriesSubsystem implements S return "osgi.feature".equals(archive.getSubsystemManifest().getSubsystemType().getValue()); } - public boolean isTransitive(Resource resource) { - SubsystemEnvironment environment = getEnvironment(); - if (environment == null) - return true; - return !environment.isContentResource(resource); + public void removeConstituent(Resource resource) { + constituents.remove(resource); } /* INSTALLING Wait, Start @@ -364,7 +399,52 @@ public class AriesSubsystem implements S } Activator.getExecutor().execute(new Runnable() { public void run() { - startAsync(); + // TODO Need to hold a lock here to guarantee that another start operation can't occur when the state goes to RESOLVED. + // Resolve the subsystem, if necessary. + if (getState() == State.RESOLVING) { // Otherwise, the state will be STARTING. + try { + setImportIsolationPolicy(); + // TODO I think this is insufficient. Do we need both pre-install and post-install environments for the Resolver? + if (!Activator.getFrameworkWiring().resolveBundles(getBundles())) { + throw new Exception("Framework could not resolve the bundles"); + } + setExportIsolationPolicy(); + // TODO Could avoid calling setState (and notifyAll) here and avoid the need for a lock. + setState(State.RESOLVED); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.RESOLVED); + setState(State.STARTING); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTING); + } + catch (Exception e) { + setState(State.INSTALLED); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + return; + } + } + // Start the subsystem. + Coordination coordination = Activator.getCoordinator().create(getSymbolicName() + '-' + getSubsystemId(), 0); + try { + // TODO Need to make sure the consitutents are ordered by start level. + for (Resource resource : constituents) { + startResource(resource, coordination); + } + setState(State.ACTIVE); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTED); + } + catch (Exception e) { + coordination.fail(e); + // TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED. + } + finally { + try { + coordination.end(); + } + catch (CoordinationException e) { + LOGGER.error("An error occurred while starting in a resource in subsystem " + this, e); + setState(State.RESOLVED); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + } + } } }); } @@ -398,7 +478,20 @@ public class AriesSubsystem implements S // TODO Need to store the task for cancellation. Activator.getExecutor().execute(new Runnable() { public void run() { - stopAsync(); + // TODO Persist stop state. + for (Resource resource : constituents) { + try { + stopResource(resource); + } + catch (Exception e) { + LOGGER.error("An error occurred while stopping resource " + resource + " of subsystem " + this, e); + // TODO Should FAILED go out for each failure? + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + } + } + // TODO Can we automatically assume it actually is resolved? + setState(State.RESOLVED); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STOPPED); } }); } @@ -433,7 +526,23 @@ public class AriesSubsystem implements S postEvent(this, SubsystemConstants.EventType.UNINSTALLING); Activator.getExecutor().execute(new Runnable() { public void run() { - uninstallAsync(); + for (Iterator iterator = constituents.iterator(); iterator.hasNext();) { + Resource resource = iterator.next(); + try { + uninstallResource(resource); + } + catch (Exception e) { + LOGGER.error("An error occurred while uninstalling resource " + resource + " of subsystem " + this, e); + // TODO Should FAILED go out for each failure? + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + } + iterator.remove(); + } + parent.children.remove(AriesSubsystem.this); + locationToSubsystem.remove(location); + deleteFile(Activator.getBundleContext().getDataFile("subsystem" + id + System.getProperty("file.separator"))); + setState(State.UNINSTALLED); + postEvent(AriesSubsystem.this, SubsystemConstants.EventType.UNINSTALLED); } }); } @@ -465,56 +574,11 @@ public class AriesSubsystem implements S return constituents.contains(resource); } -// protected Resource findContentResource(String namespace, String symbolicName, String version) { -// Requirement requirement = new OsgiIdentityRequirement(null, symbolicName, Version.parseVersion(version), namespace); -// Resource result = null; -// /* Root */ -// if (isRoot()) { -// // For the root subsystem, simply look for a resource in the system repository. -// result = ResourceHelper.getResource(requirement, repository); -// } -// /* Features */ -// else if (isFeature()) { -// // Check for existing, accessible resources first. -// result = parent.findContentResource(namespace, symbolicName, version); -// // If necessary, look for the resource in the subsystem repository. -// if (result == null) { -// if (repository != null) { -// // Repository will be null if the subsystem contained no resources. -// result = ResourceHelper.getResource(requirement, repository); -// } -// // Finally, if necessary, look for the resource in other repositories. -// if (result == null) { -// result = Activator.getResourceResolver().find(symbolicName + ";version=" + version); -// } -// } -// -// } -// /* Applications */ -// else if (isApplication()) { -// // For applications, we never want to reuse an existing resource. -// // Favor resources included with the subsystem definition. -// if (repository != null) { -// // Repository will be null if the subsystem contained no resources. -// result = ResourceHelper.getResource(requirement, repository); -// } -// // If necessary, look for the resource in other repositories. -// if (result == null) { -// result = Activator.getResourceResolver().find(symbolicName + ";version=" + version); -// } -// } -// /* Composites */ -// else { -// // TODO Implement composite behavior. -// } -// return result; -// } - protected Collection getBundles() { ArrayList result = new ArrayList(constituents.size()); for (Resource resource : constituents) { - if (resource instanceof BundleRuntimeResource) - result.add(((BundleRuntimeResource)resource).getBundle()); + if (resource instanceof BundleRevision) + result.add(((BundleRevision)resource).getBundle()); } result.trimToSize(); return result; @@ -542,80 +606,65 @@ public class AriesSubsystem implements S private Region createRegion() throws BundleException { if (isRoot()) - return Activator.getRegionDigraph().getRegion(0); + // The root subsystem's region should be the same one the subsystem bundle was installed into. + return Activator.getRegionDigraph().getRegion(Activator.getBundleContext().getBundle()); + if (isFeature()) + // Feature subsystems do not have regions because they are not isolated. + return null; + // All other subsystems get a dedicated region for isolation. return Activator.getRegionDigraph().createRegion(getSymbolicName() + ';' + getVersion()); } - private void install(Resource resource, Coordination coordination, boolean transitive) { -// String content = ResourceHelper.getContentAttribute(resource); -// String location = getSubsystemId() + '@' + getSymbolicName() + '@' + content; - try { -// final RuntimeResource runtimeResource; -// final Bundle bundle; -// if (transitive) { - // Transitive dependencies should be provisioned into the highest possible level. - // Transitive dependencies do not become a constituent. - // TODO Assumes root is always the appropriate level. -// AriesSubsystem subsystem = this; -// while (subsystem.parent != null) -// subsystem = subsystem.parent; - RuntimeResource runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this); - runtimeResource.install(coordination); -// subsystem.constituents.add(runtimeResource); -// bundle = subsystem.region.installBundle(location, new URL(content).openStream()); -// } -// else if (region == null) { - // Feature resources should be provisioned into the parent, unless the parent is also a feature. - // TODO Assumes parent is always highest possible level. -// AriesSubsystem subsystem = this.parent; -// while (subsystem.region == null) -// subsystem = subsystem.parent; -// runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this); -// runtimeResource.install(coordination); -// bundle = subsystem.region.installBundle(location, new URL(content).openStream()); - // Features retain their constituents. -// constituents.add(runtimeResource); -// } -// else { - // Constituent (non-transitive) resources must be provisioned into the owning subsystem, except for features. - // We know this isn't a feature because the region was not null. -// runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this); -// runtimeResource.install(coordination); -// bundle = region.installBundle(location, new URL(content).openStream()); -// constituents.add(runtimeResource); -// } -// coordination.addParticipant(new Participant() { -// public void ended(Coordination coordination) throws Exception { -// // noop -// } -// -// public void failed(Coordination coordination) throws Exception { -// constituents.remove(bundle.adapt(BundleRevision.class)); -// region.removeBundle(bundle); -// } -// }); + private AriesSubsystem getConstituentOf(Resource resource, AriesSubsystem provisionTo, boolean transitive) { + // Application and composite resources become constituents of the application or composite. + AriesSubsystem constituentOf; + if (transitive) { + // Transitive dependencies become constituents of the subsystem into which they were provisioned. + constituentOf = provisionTo; + } + else { + // All other resources become constituents of the subsystem in which they were declared. + constituentOf = this; } - catch (Exception e) { - throw new SubsystemException(e); + return constituentOf; + } + + private AriesSubsystem getProvisionTo(Resource resource, boolean transitive) { + // Application and composite resources are provisioned into the application or composite. + AriesSubsystem provisionTo = this; + if (transitive) { + // Transitive dependencies should be provisioned into the highest possible level. + // TODO Assumes root is always the appropriate level. + while (provisionTo.getParent() != null) + provisionTo = provisionTo.getParent(); + } + else { + if (provisionTo.isFeature()) + // Feature resources should be provisioned into the first parent that's not a feature. + while (provisionTo.region == null) + provisionTo = provisionTo.getParent(); } + return provisionTo; } - private synchronized void installAsync() throws Exception { + private synchronized void initialize(InputStream content) throws BundleException, IOException, URISyntaxException { + if (content == null) + content = new URL(location).openStream(); + File rootDirectory = Activator.getBundleContext().getDataFile(""); + File subsystemDirectory = new File(rootDirectory, "subsystem" + id + System.getProperty("file.separator")); + archive = new Archive(location, subsystemDirectory, content); + region = createRegion(); + environment = new SubsystemEnvironment(this); + if (archive.getSubsystemManifest() == null) { + SubsystemUri uri = new SubsystemUri(location); + archive.setSubsystemManifest(SubsystemManifest.newInstance(uri.getSymbolicName(), uri.getVersion(), archive.getResources())); + } + } + + private synchronized void install() throws Exception { List contentResources = new ArrayList(); List transitiveDependencies = new ArrayList(); -// // Get the resources included within the archive. -// contentResources.addAll(archive.getResources()); -// // Create a subsystem repository from the contents of the subsystem archive. -// if (!contentResources.isEmpty()) { -// Document document = RepositoryDescriptorGenerator.generateRepositoryDescriptor("subsystem" + getSubsystemId(), contentResources); -// File file = new File(archive.getDirectory() + "/repository.xml"); -// FileOutputStream fout = new FileOutputStream(file); -// TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(fout)); -// fout.close(); -// repository = new RepositoryFactory().newRepository(file.toURI().toURL()); -// } -// contentResources.clear(); - DeploymentManifest manifest = archive.getDeploymentManifest(); + DeploymentManifest manifest = getDeploymentManifest(); DeployedContentHeader contentHeader = manifest.getDeployedContent(); for (DeployedContent content : contentHeader.getDeployedContents()) { Collection capabilities = environment.findProviders( @@ -624,12 +673,6 @@ public class AriesSubsystem implements S throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion()); Resource resource = capabilities.iterator().next().getResource(); contentResources.add(resource); - -// // Find the most appropriate resource based on subsystem type. -// Resource resource = findContentResource(content.getNamespace(), content.getName(), String.valueOf(content.getDeployedVersion())); -// if (resource == null) -// throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion()); -// contentResources.add(resource); } ProvisionResourceHeader resourceHeader = manifest.getProvisionResource(); if (resourceHeader != null) { @@ -640,12 +683,6 @@ public class AriesSubsystem implements S throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion()); Resource resource = capabilities.iterator().next().getResource(); transitiveDependencies.add(resource); - -// // Find the most appropriate resource based on subsystem type. -// Resource resource = findContentResource(content.getNamespace(), content.getName(), String.valueOf(content.getDeployedVersion())); -// if (resource == null) -// throw new SubsystemException("Subsystem transitive dependency does not exist: " + content.getName() + ";version=" + content.getDeployedVersion()); -// transitiveDependencies.add(resource); } } // Install content resources and transitive dependencies. @@ -654,11 +691,11 @@ public class AriesSubsystem implements S try { // Install the content resources. for (Resource resource : contentResources) { - install(resource, coordination, false); + installResource(resource, coordination, false); } // Discover and install transitive dependencies. for (Resource resource : transitiveDependencies) { - install(resource, coordination, true); + installResource(resource, coordination, true); } } catch (Exception e) { @@ -668,10 +705,88 @@ public class AriesSubsystem implements S coordination.end(); } } - setState(Subsystem.State.INSTALLED); - postEvent(this, SubsystemConstants.EventType.INSTALLED); } + private void installBundleResource(Resource resource, Coordination coordination, boolean transitive) throws BundleException, IOException { + AriesSubsystem provisionTo; + Bundle bundle; + synchronized (resourceToSubsystems) { + if (resource instanceof BundleRevision) { + resourceToSubsystems.get(resource).add(this); + return; + } + provisionTo = getProvisionTo(resource, transitive); + URL content = environment.getContent(resource); + String location = provisionTo.getSubsystemId() + '@' + provisionTo.getSymbolicName() + '@' + content; + bundle = provisionTo.region.installBundle(location, content.openStream()); + final BundleRevision revision = bundle.adapt(BundleRevision.class); + Set subsystems = new HashSet(); + subsystems.add(this); + resourceToSubsystems.put(revision, subsystems); + } + final AriesSubsystem constituentOf = getConstituentOf(resource, provisionTo, transitive); + final BundleRevision revision = bundle.adapt(BundleRevision.class); + coordination.addParticipant(new Participant() { + public void ended(Coordination coordination) throws Exception { + constituentOf.constituents.add(revision); + } + + public void failed(Coordination coordination) throws Exception { + revision.getBundle().uninstall(); + synchronized (resourceToSubsystems) { + Set subsystems = resourceToSubsystems.get(revision); + subsystems.remove(AriesSubsystem.this); + if (subsystems.isEmpty()) { + resourceToSubsystems.remove(revision); + } + } + } + }); + } + + private void installResource(Resource resource, Coordination coordination, boolean transitive) throws IOException, BundleException { + String type = ResourceHelper.getTypeAttribute(resource); + // TODO Add to constants. + if ("osgi.subsystem".equals(type)) + installSubsystemResource(resource, coordination, transitive); + else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type)) + installBundleResource(resource, coordination, transitive); + else + throw new SubsystemException("Unsupported resource type: " + type); + } + + private void installSubsystemResource(Resource resource, Coordination coordination, boolean transitive) throws IOException { + final AriesSubsystem subsystem; + synchronized (resourceToSubsystems) { + if (resource instanceof Subsystem) { + resourceToSubsystems.get(resource).add(this); + return; + } + URL content = environment.getContent(resource); + String location = id + '@' + getSymbolicName() + '@' + content; + subsystem = (AriesSubsystem)install(location, content.openStream()); + Set subsystems = new HashSet(); + subsystems.add(this); + resourceToSubsystems.put(subsystem, subsystems); + } + coordination.addParticipant(new Participant() { + public void ended(Coordination coordination) throws Exception { + // noop + } + + public void failed(Coordination coordination) throws Exception { + subsystem.uninstall(); + synchronized (resourceToSubsystems) { + Set subsystems = resourceToSubsystems.get(subsystem); + subsystems.remove(AriesSubsystem.this); + if (subsystems.isEmpty()) { + resourceToSubsystems.remove(subsystem); + } + } + } + }); + } + private boolean isRoot() { return ROOT_LOCATION.equals(getLocation()); } @@ -696,7 +811,7 @@ public class AriesSubsystem implements S // Applications have an implicit import policy equating to "import everything that I require", which is not the same as features. // This must be computed from the application requirements and will be done using the Wires returned by the Resolver, when one is available. region.connectRegion( - parent.getRegion(), + parent.region, region.getRegionDigraph().createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_ALL_NAMESPACE).build()); } else if (isComposite()) { @@ -704,137 +819,101 @@ public class AriesSubsystem implements S // Composites specify an explicit import policy in their subsystem and deployment manifests. } } - -// private void start(Resource resource, Coordination coordination) throws BundleException { -// if (!(resource instanceof BundleRevision)) { -// throw new SubsystemException("Unsupported resource type: " + resource); -// } -// final Bundle bundle = ((BundleRevision)resource).getBundle(); -// // We don't want the bundles to autostart. Starting bundles must be under the control of the -// // subsystem in order to guarantee ordering. -// bundle.start(Bundle.START_TRANSIENT); -// coordination.addParticipant(new Participant() { -// public void ended(Coordination coordination) throws Exception { -// // noop -// } -// -// public void failed(Coordination coordination) throws Exception { -// bundle.stop(); -// } -// }); -// } - - private void startAsync() { - // TODO Need to hold a lock here to guarantee that another start operation can't occur when the state goes to RESOLVED. - // Resolve the subsystem, if necessary. - if (getState() == State.RESOLVING) { // Otherwise, the state will be STARTING. - try { - setImportIsolationPolicy(); - if (!Activator.getFrameworkWiring().resolveBundles(getBundles())) { - throw new Exception("Framework could not resolve the bundles"); - } - setExportIsolationPolicy(); - // TODO Could avoid calling setState (and notifyAll) here and avoid the need for a lock. - setState(State.RESOLVED); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.RESOLVED); - setState(State.STARTING); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTING); - } - catch (Exception e) { - setState(State.INSTALLED); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); - return; - } - } - // Start the subsystem. - Coordination coordination = Activator.getCoordinator().create(getSymbolicName() + '-' + getSubsystemId(), 0); - try { - for (Resource resource : constituents) { - ((RuntimeResource)resource).start(coordination); - } - } - catch (Exception e) { - coordination.fail(e); - // TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED. - } - finally { - try { - coordination.end(); + + private void startBundleResource(Resource resource, Coordination coordination) throws BundleException { + final Bundle bundle = ((BundleRevision)resource).getBundle(); + bundle.start(Bundle.START_TRANSIENT); + if (coordination == null) + return; + coordination.addParticipant(new Participant() { + public void ended(Coordination coordination) throws Exception { + // noop } - catch (CoordinationException e) { - setState(State.RESOLVED); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + + public void failed(Coordination coordination) throws Exception { + bundle.stop(); } - } -// try { -// for (Resource resource : constituents) { -// start(resource, coordination); -// } -// } -// catch (Exception e) { -// coordination.fail(e); -// // TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED. -// } -// finally { -// try { -// coordination.end(); -// } -// catch (CoordinationException e) { -// setState(State.RESOLVED); -// postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); -// } -// } - setState(State.ACTIVE); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTED); - } - - private void stop(Resource resource) throws Exception { - ((RuntimeResource)resource).stop(null); -// if (!(resource instanceof BundleRevision)) { -// throw new SubsystemException("Unsupported resource type: " + resource); -// } -// final Bundle bundle = ((BundleRevision)resource).getBundle(); -// bundle.stop(); + }); } + + private void startResource(Resource resource, Coordination coordination) throws BundleException { + String type = ResourceHelper.getTypeAttribute(resource); + // TODO Add to constants. + if ("osgi.subsystem".equals(type)) + startSubsystemResource(resource, coordination); + else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type)) + startBundleResource(resource, coordination); + else + throw new SubsystemException("Unsupported resource type: " + type); + } + + private void startSubsystemResource(Resource resource, Coordination coordination) { + final Subsystem subsystem = (Subsystem)resource; + subsystem.start(); + if (coordination == null) + return; + coordination.addParticipant(new Participant() { + public void ended(Coordination coordination) throws Exception { + // noop + } - private void stopAsync() { - // TODO Persist stop state. - for (Resource resource : constituents) { - try { - stop(resource); + public void failed(Coordination coordination) throws Exception { + subsystem.stop(); } - catch (Exception e) { - // TODO Should FAILED go out for each failure? - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + }); + } + + private void stopBundleResource(Resource resource) throws BundleException { + ((BundleRevision)resource).getBundle().stop(); + } + + private void stopResource(Resource resource) throws BundleException { + String type = ResourceHelper.getTypeAttribute(resource); + // TODO Add to constants. + if ("osgi.subsystem".equals(type)) + stopSubsystemResource(resource); + else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type)) + stopBundleResource(resource); + else + throw new SubsystemException("Unsupported resource type: " + type); + } + + private void stopSubsystemResource(Resource resource) { + ((Subsystem)resource).stop(); + } + + private void uninstallBundleResource(Resource resource) throws BundleException { + synchronized (resourceToSubsystems) { + Set subsystems = resourceToSubsystems.get(resource); + subsystems.remove(this); + if (!subsystems.isEmpty()) { + return; } + subsystems.remove(resource); } - // TODO Can we automatically assume it actually is resolved? - setState(State.RESOLVED); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STOPPED); + ((BundleRevision)resource).getBundle().uninstall(); } - - private void uninstall(Resource resource) throws Exception { - ((RuntimeResource)resource).uninstall(null); -// if (!(resource instanceof BundleRevision)) { -// throw new SubsystemException("Unsupported resource type: " + resource); -// } -// final Bundle bundle = ((BundleRevision)resource).getBundle(); -// bundle.uninstall(); + + private void uninstallResource(Resource resource) throws BundleException { + String type = ResourceHelper.getTypeAttribute(resource); + // TODO Add to constants. + if ("osgi.subsystem".equals(type)) + uninstallSubsystemResource(resource); + else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type)) + uninstallBundleResource(resource); + else + throw new SubsystemException("Unsupported resource type: " + type); } - - private void uninstallAsync() { - for (Resource resource : constituents) { - try { - uninstall(resource); - } - catch (Exception e) { - // TODO Should FAILED go out for each failure? - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e); + + private void uninstallSubsystemResource(Resource resource) { + synchronized (resourceToSubsystems) { + Set subsystems = resourceToSubsystems.get(resource); + subsystems.remove(this); + if (!subsystems.isEmpty()) { + return; } + subsystems.remove(resource); } - parent.children.remove(this); - deleteFile(Activator.getBundleContext().getDataFile("subsystem" + id + System.getProperty("file.separator"))); - setState(State.UNINSTALLED); - postEvent(AriesSubsystem.this, SubsystemConstants.EventType.UNINSTALLED); + ((Subsystem)resource).uninstall(); } } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java Sun Aug 28 20:39:09 2011 @@ -34,7 +34,7 @@ public class BundleEventHandler implemen } Bundle bundle = (Bundle)event.getProperty(EventConstants.BUNDLE); Resource resource = bundle.adapt(BundleRevision.class); - Collection subsystems = Activator.getSubsystemManager().getSubsystems(resource); + Collection subsystems = AriesSubsystem.getSubsystems(resource); for (AriesSubsystem subsystem : subsystems) { Map map = new HashMap(); for (String propertyName : event.getPropertyNames()) { Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java Sun Aug 28 20:39:09 2011 @@ -16,8 +16,8 @@ package org.apache.aries.subsystem.core. import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.jar.Manifest; +import org.apache.aries.subsystem.core.archive.BundleManifest; import org.apache.aries.subsystem.core.archive.SubsystemManifest; import org.osgi.framework.Constants; import org.osgi.framework.Version; @@ -56,14 +56,15 @@ public class OsgiIdentityCapability impl resource, manifest.getSubsystemSymbolicName().getSymbolicName(), manifest.getSubsystemVersion().getVersion(), - manifest.getSubsystemType().getValue()); + // TODO Add to constants. + "osgi.subsystem"); } - public OsgiIdentityCapability(Resource resource, Manifest manifest) { + public OsgiIdentityCapability(Resource resource, BundleManifest manifest) { this( resource, - manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME), - Version.parseVersion(manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION)), + manifest.getHeader(Constants.BUNDLE_SYMBOLICNAME).getValue(), + Version.parseVersion(manifest.getHeader(Constants.BUNDLE_VERSION).getValue()), ResourceConstants.IDENTITY_TYPE_BUNDLE); } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java Sun Aug 28 20:39:09 2011 @@ -19,8 +19,7 @@ import org.osgi.framework.wiring.BundleR public class SubsystemBundleListener implements BundleListener { public void bundleChanged(BundleEvent event) { - SubsystemManager manager = Activator.getSubsystemManager(); - for (AriesSubsystem subsystem : manager.getSubsystems(event.getBundle().adapt(BundleRevision.class))) { + for (AriesSubsystem subsystem : AriesSubsystem.getSubsystems(event.getBundle().adapt(BundleRevision.class))) { // TODO Anything? } } Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java Sun Aug 28 20:39:09 2011 @@ -22,8 +22,12 @@ import org.osgi.framework.wiring.BundleR import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.Resource; import org.osgi.service.subsystem.Subsystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SubsystemResolverHook implements ResolverHook { + private static final Logger LOGGER = LoggerFactory.getLogger(SubsystemResolverHook.class); + public void end() { // noop } @@ -33,22 +37,26 @@ public class SubsystemResolverHook imple } public void filterResolvable(Collection candidates) { - SubsystemManager manager = Activator.getSubsystemManager(); - for (Resource candidate : candidates) { - Collection subsystems = manager.getSubsystems(candidate); - for (AriesSubsystem subsystem : subsystems) { - // TODO Uncomment when features are implemented. -// if (subsystem instanceof FeatureSubsystem) { -// // Feature subsystems require no isolation. -// continue; -// } - // Otherwise, the candidate is part of an application or composite subsystem requiring isolation. - // But only when in the INSTALLING or INSTALLED state. - if (EnumSet.of(Subsystem.State.INSTALLING, Subsystem.State.INSTALLED).contains(subsystem.getState())) { - candidates.remove(candidate); + try { + for (Resource candidate : candidates) { + Collection subsystems = AriesSubsystem.getSubsystems(candidate); + for (AriesSubsystem subsystem : subsystems) { + if (subsystem.isFeature()) { + // Feature subsystems require no isolation. + continue; + } + // Otherwise, the candidate is part of an application or composite subsystem requiring isolation. + // But only when in the INSTALLING or INSTALLED state. + if (EnumSet.of(Subsystem.State.INSTALLING, Subsystem.State.INSTALLED).contains(subsystem.getState())) { + candidates.remove(candidate); + } } } } + catch (RuntimeException e) { + // This try/catch block is in place because exceptions occurring here are not showing up in the console during testing. + LOGGER.debug("Unexpected exception while filtering resolution candidates: " + candidates, e); + } } public void filterSingletonCollisions(BundleCapability singleton, Collection collisionCandidates) { Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java?rev=1162585&r1=1162584&r2=1162585&view=diff ============================================================================== --- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java (original) +++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java Sun Aug 28 20:39:09 2011 @@ -29,7 +29,7 @@ public class SubsystemSynchronousBundleL return; } Resource resource = bundle.adapt(BundleRevision.class); - Collection subsystems = Activator.getSubsystemManager().getSubsystems(resource); + Collection subsystems = AriesSubsystem.getSubsystems(resource); for (AriesSubsystem subsystem : subsystems) { subsystem.bundleChanged(event); }