/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.subsystem.core.internal;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.aries.subsystem.core.archive.AriesSubsystemParentsHeader;
import org.apache.aries.subsystem.core.archive.Attribute;
import org.apache.aries.subsystem.core.archive.DeployedContentHeader;
import org.apache.aries.subsystem.core.archive.DeploymentManifest;
import org.apache.aries.subsystem.core.archive.Header;
import org.apache.aries.subsystem.core.archive.ImportPackageHeader;
import org.apache.aries.subsystem.core.archive.ImportPackageRequirement;
import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
import org.apache.aries.subsystem.core.archive.RequireBundleHeader;
import org.apache.aries.subsystem.core.archive.RequireBundleRequirement;
import org.apache.aries.subsystem.core.archive.RequireCapabilityHeader;
import org.apache.aries.subsystem.core.archive.RequireCapabilityRequirement;
import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
import org.apache.aries.subsystem.core.archive.SubsystemExportServiceHeader;
import org.apache.aries.subsystem.core.archive.SubsystemImportServiceHeader;
import org.apache.aries.subsystem.core.archive.SubsystemImportServiceRequirement;
import org.apache.aries.subsystem.core.archive.SubsystemManifest;
import org.apache.aries.util.filesystem.FileSystem;
import org.apache.aries.util.filesystem.IDirectory;
import org.eclipse.equinox.region.Region;
import org.eclipse.equinox.region.RegionDigraph;
import org.eclipse.equinox.region.RegionFilter;
import org.eclipse.equinox.region.RegionFilterBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.resource.Wire;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.resolver.ResolveContext;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.SubsystemConstants;
import org.osgi.service.subsystem.SubsystemException;
public class SubsystemResource implements Resource {
private Region region;
private final List<Capability> capabilities;
private final DeploymentManifest deploymentManifest;
private final Collection<Resource> installableContent = new HashSet<Resource>();
private final Collection<Resource> installableDependencies = new HashSet<Resource>();
private final Collection<Resource> mandatoryResources = new HashSet<Resource>();
private final Collection<DeployedContentHeader.Clause> missingResources = new HashSet<DeployedContentHeader.Clause>();
private final Collection<Resource> optionalResources = new HashSet<Resource>();
private final BasicSubsystem parent;
private final RawSubsystemResource resource;
private final Collection<Resource> sharedContent = new HashSet<Resource>();
private final Collection<Resource> sharedDependencies = new HashSet<Resource>();
public SubsystemResource(String location, IDirectory content, BasicSubsystem parent, Coordination coordination) throws URISyntaxException, IOException, ResolutionException, BundleException, InvalidSyntaxException {
this(new RawSubsystemResource(location, content, parent), parent, coordination);
}
public SubsystemResource(RawSubsystemResource resource, BasicSubsystem parent, Coordination coordination) throws IOException, BundleException, InvalidSyntaxException, URISyntaxException {
this.parent = parent;
this.resource = resource;
computeContentResources(resource.getDeploymentManifest());
capabilities = computeCapabilities();
if (this.getSubsystemManifest().getSubsystemTypeHeader().getAriesProvisionDependenciesDirective().isInstall()) {
/* compute dependencies now only if we intend to provision them during install */
computeDependencies(resource.getDeploymentManifest(), coordination);
}
deploymentManifest = computeDeploymentManifest();
}
public SubsystemResource(File file) throws IOException, URISyntaxException, ResolutionException, BundleException, InvalidSyntaxException {
this(null, FileSystem.getFSRoot(file));
}
public SubsystemResource(BasicSubsystem subsystem, IDirectory directory) throws IOException, URISyntaxException, ResolutionException, BundleException, InvalidSyntaxException {
if (subsystem == null) {
// This is intended to only support the case where the root subsystem
// is being initialized from a non-persistent state.
parent = null;
}
else {
parent = Utils.findScopedSubsystemInRegion(subsystem);
}
resource = new RawSubsystemResource(directory, parent);
deploymentManifest = resource.getDeploymentManifest();
computeContentResources(deploymentManifest);
capabilities = computeCapabilities();
if (getSubsystemManifest().getSubsystemTypeHeader().getAriesProvisionDependenciesDirective().isInstall()) {
/* compute dependencies if we intend to provision them during install */
computeDependencies(resource.getDeploymentManifest(), null);
}
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof SubsystemResource))
return false;
SubsystemResource that = (SubsystemResource)o;
return getLocation().equals(that.getLocation());
}
@Override
public List<Capability> getCapabilities(String namespace) {
return Collections.unmodifiableList(capabilities);
}
private List<Capability> computeCapabilities() throws InvalidSyntaxException {
List<Capability> capabilities = new ArrayList<Capability>();
if (isScoped())
computeScopedCapabilities(capabilities);
else
computeUnscopedCapabilities(capabilities);
return capabilities;
}
private void computeUnscopedCapabilities(List<Capability> capabilities) {
capabilities.addAll(resource.getCapabilities(null));
for (Resource r : getContentResources())
capabilities.addAll(r.getCapabilities(null));
}
private void computeScopedCapabilities(List<Capability> capabilities) throws InvalidSyntaxException {
capabilities.addAll(resource.getCapabilities(null));
computeOsgiServiceCapabilities(capabilities);
}
private void computeOsgiServiceCapabilities(List<Capability> capabilities) throws InvalidSyntaxException {
SubsystemExportServiceHeader header = getSubsystemManifest().getSubsystemExportServiceHeader();
if (header == null)
return;
for (Resource resource : getContentResources())
capabilities.addAll(header.toCapabilities(resource));
}
public DeploymentManifest getDeploymentManifest() {
return deploymentManifest;
}
public long getId() {
return resource.getId();
}
public Collection<Resource> getInstallableContent() {
return installableContent;
}
public Collection<Resource> getInstallableDependencies() {
return installableDependencies;
}
public org.apache.aries.subsystem.core.repository.Repository getLocalRepository() {
return resource.getLocalRepository();
}
public String getLocation() {
return resource.getLocation().getValue();
}
Collection<Resource> getMandatoryResources() {
return mandatoryResources;
}
public Collection<DeployedContentHeader.Clause> getMissingResources() {
return missingResources;
}
Collection<Resource> getOptionalResources() {
return optionalResources;
}
public Collection<BasicSubsystem> getParents() {
if (parent == null) {
AriesSubsystemParentsHeader header = getDeploymentManifest().getAriesSubsystemParentsHeader();
if (header == null)
return Collections.emptyList();
Collection<AriesSubsystemParentsHeader.Clause> clauses = header.getClauses();
Collection<BasicSubsystem> result = new ArrayList<BasicSubsystem>(clauses.size());
Subsystems subsystems = Activator.getInstance().getSubsystems();
for (AriesSubsystemParentsHeader.Clause clause : clauses) {
result.add(subsystems.getSubsystemById(clause.getId()));
}
return result;
}
return Collections.singleton(parent);
}
public synchronized Region getRegion() throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
if (region == null) {
region = createRegion(getId());
Coordination coordination = Activator.getInstance().getCoordinator().peek();
coordination.addParticipant(new Participant() {
@Override
public void ended(Coordination arg0) throws Exception {
// Nothing.
}
@Override
public void failed(Coordination arg0) throws Exception {
if (isScoped())
region.getRegionDigraph().removeRegion(region);
}
});
if (!isApplication()) {
setImportIsolationPolicy();
}
}
return region;
}
@Override
public List<Requirement> getRequirements(String namespace) {
if (isScoped())
return resource.getRequirements(namespace);
else {
ArrayList<Requirement> result = new ArrayList<Requirement>();
result.addAll(resource.getRequirements(namespace));
for (Resource r : getContentResources())
result.addAll(r.getRequirements(namespace));
result.trimToSize();
return result;
}
}
public Collection<Resource> getSharedContent() {
return sharedContent;
}
public Collection<Resource> getSharedDependencies() {
return sharedDependencies;
}
public SubsystemManifest getSubsystemManifest() {
return resource.getSubsystemManifest();
}
public Collection<TranslationFile> getTranslations() {
return resource.getTranslations();
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + getLocation().hashCode();
return result;
}
private void addContentResource(Resource resource) {
if (resource == null)
return;
if (isMandatory(resource))
mandatoryResources.add(resource);
else
optionalResources.add(resource);
if (isInstallable(resource))
installableContent.add(resource);
else
sharedContent.add(resource);
}
private void addMissingResource(DeployedContentHeader.Clause resource) {
missingResources.add(resource);
}
private void addSubsystemServiceImportToSharingPolicy(
RegionFilterBuilder builder) throws InvalidSyntaxException, BundleException, IOException, URISyntaxException {
builder.allow(
RegionFilter.VISIBLE_SERVICE_NAMESPACE,
new StringBuilder("(&(")
.append(org.osgi.framework.Constants.OBJECTCLASS)
.append('=').append(Subsystem.class.getName())
.append(")(")
.append(Constants.SubsystemServicePropertyRegions)
.append('=').append(getRegion().getName())
.append("))").toString());
}
private void addSubsystemServiceImportToSharingPolicy(RegionFilterBuilder builder, Region to)
throws InvalidSyntaxException, BundleException, IOException, URISyntaxException {
Region root = Activator.getInstance().getSubsystems().getRootSubsystem().getRegion();
if (to.getName().equals(root.getName()))
addSubsystemServiceImportToSharingPolicy(builder);
else {
to = root;
builder = to.getRegionDigraph().createRegionFilterBuilder();
addSubsystemServiceImportToSharingPolicy(builder);
RegionFilter regionFilter = builder.build();
getRegion().connectRegion(to, regionFilter);
}
}
private void computeContentResources(DeploymentManifest manifest) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
if (manifest == null)
computeContentResources(getSubsystemManifest());
else {
DeployedContentHeader header = manifest.getDeployedContentHeader();
if (header == null)
return;
for (DeployedContentHeader.Clause clause : header.getClauses()) {
Resource resource = findContent(clause);
if (resource == null)
addMissingResource(clause);
else
addContentResource(resource);
}
}
}
private void computeContentResources(SubsystemManifest manifest) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
SubsystemContentHeader contentHeader = manifest.getSubsystemContentHeader();
if (contentHeader == null)
return;
for (SubsystemContentHeader.Clause clause : contentHeader.getClauses()) {
Requirement requirement = clause.toRequirement(this);
Resource resource = findContent(requirement);
if (resource == null) {
if (clause.isMandatory())
throw new SubsystemException("A required content resource could not be found. This means the resource was either missing or not recognized as a supported resource format due to, for example, an invalid bundle manifest or blueprint XML file. Turn on debug logging for more information. The resource was: " + requirement);
continue;
}
addContentResource(resource);
}
}
void computeDependencies(DeploymentManifest manifest, Coordination coordination) {
if (manifest == null) {
computeDependencies(getSubsystemManifest(), coordination);
}
else {
ProvisionResourceHeader header = manifest.getProvisionResourceHeader();
if (header == null)
return;
for (ProvisionResourceHeader.Clause clause : header.getClauses()) {
Resource resource = findDependency(clause);
if (resource == null)
throw new SubsystemException("A required dependency could not be found. This means the resource was either missing or not recognized as a supported resource format due to, for example, an invalid bundle manifest or blueprint XML file. Turn on debug logging for more information. The resource was: " + resource);
addDependency(resource);
}
}
}
private void addDependency(Resource resource) {
if (resource == null)
return;
if (isInstallable(resource))
installableDependencies.add(resource);
else
sharedDependencies.add(resource);
}
private void computeDependencies(SubsystemManifest manifest, Coordination coordination) {
try {
// The following line is necessary in order to ensure that the
// export sharing policies of composites are in place for capability
// validation.
StartAction.setExportPolicyOfAllInstallingSubsystemsWithProvisionDependenciesResolve(coordination);
Map<Resource, List<Wire>> resolution = Activator.getInstance().getResolver().resolve(createResolveContext());
setImportIsolationPolicy(resolution);
addDependencies(resolution);
}
catch (Exception e) {
Utils.handleTrowable(e);
}
}
private void addDependencies(Map<Resource, List<Wire>> resolution) {
for (Map.Entry<Resource, List<Wire>> entry : resolution.entrySet()) {
addDependencies(entry, resolution);
}
}
private void addDependencies(Map.Entry<Resource, List<Wire>> entry, Map<Resource, List<Wire>> resolution) {
addDependencies(entry.getKey(), entry, resolution);
}
private void addDependencies(Resource resource, Map.Entry<Resource, List<Wire>> entry, Map<Resource, List<Wire>> resolution) {
String type = ResourceHelper.getTypeAttribute(resource);
SubsystemContentHeader contentHeader = getSubsystemManifest().getSubsystemContentHeader();
if (!Constants.ResourceTypeSynthesized.equals(type) // Do not include synthetic resources as dependencies.
&& !contentHeader.contains(resource)) { // Do not include content as dependencies.
addDependency(resource);
}
}
private DeployedContentHeader computeDeployedContentHeader() {
Collection<Resource> content = getContentResources();
if (content.isEmpty())
return null;
return DeployedContentHeader.newInstance(content);
}
private DeploymentManifest computeDeploymentManifest() throws IOException {
DeploymentManifest result = computeExistingDeploymentManifest();
if (result != null)
return result;
result = new DeploymentManifest.Builder().manifest(resource.getSubsystemManifest())
.header(computeDeployedContentHeader())
.header(computeProvisionResourceHeader()).build();
return result;
}
private DeploymentManifest computeExistingDeploymentManifest() throws IOException {
return resource.getDeploymentManifest();
}
ProvisionResourceHeader computeProvisionResourceHeader() {
Collection<Resource> dependencies = getDependencies();
if (dependencies.isEmpty())
return null;
return ProvisionResourceHeader.newInstance(dependencies);
}
private Region createRegion(long id) throws BundleException {
if (!isScoped())
return getParents().iterator().next().getRegion();
Activator activator = Activator.getInstance();
RegionDigraph digraph = activator.getRegionDigraph();
if (getParents().isEmpty())
// This is the root subsystem. Associate it with the region in which
// the subsystems implementation bundle was installed.
return digraph.getRegion(activator.getBundleContext().getBundle());
String name = getSubsystemManifest()
.getSubsystemSymbolicNameHeader().getSymbolicName()
+ ';'
+ getSubsystemManifest().getSubsystemVersionHeader()
.getVersion()
+ ';'
+ getSubsystemManifest().getSubsystemTypeHeader()
.getType() + ';' + Long.toString(id);
Region region = digraph.getRegion(name);
// TODO New regions need to be cleaned up if this subsystem fails to
// install, but there's no access to the coordination here.
if (region == null)
return digraph.createRegion(name);
return region;
}
private ResolveContext createResolveContext() {
return new org.apache.aries.subsystem.core.internal.ResolveContext(this);
}
private Resource findContent(Requirement requirement) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
Map<Requirement, Collection<Capability>> map;
// TODO System repository for scoped subsystems should be searched in
// the case of a persisted subsystem.
if (isUnscoped()) {
map = Activator.getInstance().getSystemRepository().findProviders(Collections.singleton(requirement));
if (map.containsKey(requirement)) {
Collection<Capability> capabilities = map.get(requirement);
for (Capability capability : capabilities) {
Resource provider = capability.getResource();
if (provider instanceof BundleRevision) {
if (getRegion().contains(((BundleRevision)provider).getBundle())) {
return provider;
}
}
else if (provider instanceof BasicSubsystem) {
if (getRegion().equals(((BasicSubsystem)provider).getRegion())) {
return provider;
}
}
}
}
}
// First search the local repository.
map = resource.getLocalRepository().findProviders(Collections.singleton(requirement));
Collection<Capability> capabilities = map.get(requirement);
if (capabilities.isEmpty()) {
// Nothing found in the local repository so search the repository services.
capabilities = new RepositoryServiceRepository().findProviders(requirement);
}
if (capabilities.isEmpty()) {
// Nothing found period.
return null;
}
for (Capability capability : capabilities) {
if (!IdentityNamespace.TYPE_FRAGMENT.equals(
capability.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE))) {
// Favor the first resource that is not a fragment bundle.
// See ARIES-1425.
return capability.getResource();
}
}
// Nothing here but fragment bundles. Return the first one.
return capabilities.iterator().next().getResource();
}
private Resource findContent(DeployedContentHeader.Clause clause) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
Attribute attribute = clause.getAttribute(DeployedContentHeader.Clause.ATTRIBUTE_RESOURCEID);
long resourceId = attribute == null ? -1 : Long.parseLong(String.valueOf(attribute.getValue()));
if (resourceId != -1) {
String type = clause.getType();
if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type)) {
Bundle resource = Activator.getInstance().getBundleContext().getBundle(0).getBundleContext().getBundle(resourceId);
if (resource == null)
return null;
return resource.adapt(BundleRevision.class);
}
else
return Activator.getInstance().getSubsystems().getSubsystemById(resourceId);
}
return findContent(clause.toRequirement(this));
}
private Resource findDependency(ProvisionResourceHeader.Clause clause) {
Attribute attribute = clause.getAttribute(DeployedContentHeader.Clause.ATTRIBUTE_RESOURCEID);
long resourceId = attribute == null ? -1 : Long.parseLong(String.valueOf(attribute.getValue()));
if (resourceId != -1) {
String type = clause.getType();
if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type))
return Activator.getInstance().getBundleContext().getBundle(0).getBundleContext().getBundle(resourceId).adapt(BundleRevision.class);
else
return Activator.getInstance().getSubsystems().getSubsystemById(resourceId);
}
OsgiIdentityRequirement requirement = new OsgiIdentityRequirement(
clause.getPath(), clause.getDeployedVersion(),
clause.getType(), true);
List<Capability> capabilities = createResolveContext().findProviders(requirement);
if (capabilities.isEmpty())
return null;
return capabilities.get(0).getResource();
}
private Collection<Resource> getContentResources() {
Collection<Resource> result = new ArrayList<Resource>(installableContent.size() + sharedContent.size());
result.addAll(installableContent);
result.addAll(sharedContent);
return result;
}
private Collection<Resource> getDependencies() {
Collection<Resource> result = new ArrayList<Resource>(installableDependencies.size() + sharedDependencies.size());
result.addAll(installableDependencies);
result.addAll(sharedDependencies);
return result;
}
boolean isApplication() {
String type = resource.getSubsystemManifest().getSubsystemTypeHeader().getType();
return SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type);
}
boolean isComposite() {
String type = resource.getSubsystemManifest().getSubsystemTypeHeader().getType();
return SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type);
}
boolean isContent(Resource resource) {
if (installableContent.contains(resource) || sharedContent.contains(resource)) {
return true;
}
// Allow for implicit subsystem installations. An implicit installation
// occurs when a subsystem containing other subsystems as content is
// installed. When identifying the region to be used for validation
// purposes during resolution, resources that are content of children
// must be treated as content of this subsystem. See ResolveContext.isValid().
for (Resource installableResource : installableContent) {
if (installableResource instanceof RawSubsystemResource) {
if (((RawSubsystemResource)installableResource).getSubsystemManifest().getSubsystemContentHeader().contains(resource)) {
return true;
}
}
}
return false;
}
private boolean isInstallable(Resource resource) {
return !isShared(resource);
}
private boolean isMandatory(Resource resource) {
SubsystemContentHeader header = this.resource.getSubsystemManifest().getSubsystemContentHeader();
if (header == null)
return false;
return header.isMandatory(resource);
}
boolean isRoot() {
return BasicSubsystem.ROOT_LOCATION.equals(getLocation());
}
private boolean isShared(Resource resource) {
return Utils.isSharedResource(resource);
}
private boolean isScoped() {
return isApplication() || isComposite();
}
private boolean isUnscoped() {
return !isScoped();
}
private void setImportIsolationPolicy(Map<Resource, List<Wire>> resolution) throws Exception {
if (!isApplication()) {
return;
}
SubsystemContentHeader contentHeader = getSubsystemManifest().getSubsystemContentHeader();
// Prepare the regions and filter builder to set the sharing policy.
Region from = getRegion();
Region to = ((BasicSubsystem)getParents().iterator().next()).getRegion();
RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
// Always provide visibility to this subsystem's service registration.
addSubsystemServiceImportToSharingPolicy(builder, to);
for (Resource resource : resolution.keySet()) {
if (!contentHeader.contains(resource)) {
continue;
}
// If the resource is content but the wire provider is not,
// the sharing policy must be updated.
List<Wire> wires = resolution.get(resource);
for (Wire wire : wires) {
Resource provider = wire.getProvider();
// First check: If the provider is content there is no need to
// update the sharing policy because the capability is already
// visible.
if (contentHeader.contains(provider)) {
continue;
}
// Second check: If the provider is synthesized but not offering
// a MissingCapability, then the resource is acting as a
// placeholder as part of the Application-ImportService header
// functionality, and the sharing policy does not need to be
// updated.
// Do not exclude resources providing a MissingCapability
// even though they are synthesized. These are added by the
// resolve context to ensure that unsatisfied optional
// requirements become part of the sharing policy.
if (!(wire.getCapability() instanceof DependencyCalculator.MissingCapability)
&& Constants.ResourceTypeSynthesized.equals(ResourceHelper.getTypeAttribute(provider))) {
continue;
}
// The requirement must be added to the sharing policy.
Requirement requirement = wire.getRequirement();
List<String> namespaces = new ArrayList<String>(2);
namespaces.add(requirement.getNamespace());
if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespaces.get(0))) {
// Both service capabilities and services must be visible.
namespaces.add(RegionFilter.VISIBLE_SERVICE_NAMESPACE);
}
String filter = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
if (filter == null) {
for (String namespace : namespaces)
builder.allowAll(namespace);
}
else {
for (String namespace : namespaces)
builder.allow(namespace, filter);
}
}
}
// Always add access to osgi.ee and osgi.native namespaces
setImplicitAccessToNativeAndEECapabilities(builder);
// Now set the sharing policy, if the regions are different.
RegionFilter regionFilter = builder.build();
from.connectRegion(to, regionFilter);
}
private void setImportIsolationPolicy() throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
if (isRoot() || !isScoped())
return;
Region region = getRegion();
Region from = region;
RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
Region to = getParents().iterator().next().getRegion();
addSubsystemServiceImportToSharingPolicy(builder, to);
// TODO Is this check really necessary? Looks like it was done at the beginning of this method.
if (isScoped()) {
// Both applications and composites have Import-Package headers that require processing.
// In the case of applications, the header is generated.
Header<?> header = getSubsystemManifest().getImportPackageHeader();
setImportIsolationPolicy(builder, (ImportPackageHeader)header);
// Both applications and composites have Require-Capability headers that require processing.
// In the case of applications, the header is generated.
header = getSubsystemManifest().getRequireCapabilityHeader();
setImportIsolationPolicy(builder, (RequireCapabilityHeader)header);
// Both applications and composites have Subsystem-ImportService headers that require processing.
// In the case of applications, the header is generated.
header = getSubsystemManifest().getSubsystemImportServiceHeader();
setImportIsolationPolicy(builder, (SubsystemImportServiceHeader)header);
header = getSubsystemManifest().getRequireBundleHeader();
setImportIsolationPolicy(builder, (RequireBundleHeader)header);
// Always add access to osgi.ee and osgi.native namespaces
setImplicitAccessToNativeAndEECapabilities(builder);
}
RegionFilter regionFilter = builder.build();
from.connectRegion(to, regionFilter);
}
private void setImportIsolationPolicy(RegionFilterBuilder builder, ImportPackageHeader header) throws InvalidSyntaxException {
String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
if (header == null)
return;
for (ImportPackageHeader.Clause clause : header.getClauses()) {
ImportPackageRequirement requirement = new ImportPackageRequirement(clause, this);
String filter = requirement.getDirectives().get(ImportPackageRequirement.DIRECTIVE_FILTER);
builder.allow(policy, filter);
}
}
private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireBundleHeader header) throws InvalidSyntaxException {
if (header == null)
return;
for (RequireBundleHeader.Clause clause : header.getClauses()) {
RequireBundleRequirement requirement = new RequireBundleRequirement(clause, this);
String policy = RegionFilter.VISIBLE_REQUIRE_NAMESPACE;
String filter = requirement.getDirectives().get(RequireBundleRequirement.DIRECTIVE_FILTER);
builder.allow(policy, filter);
}
}
private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireCapabilityHeader header) throws InvalidSyntaxException {
if (header == null)
return;
for (RequireCapabilityHeader.Clause clause : header.getClauses()) {
RequireCapabilityRequirement requirement = new RequireCapabilityRequirement(clause, this);
String policy = requirement.getNamespace();
String filter = requirement.getDirectives().get(RequireCapabilityRequirement.DIRECTIVE_FILTER);
if (filter == null)
// A null filter directive means the requirement matches any
// capability from the same namespace.
builder.allowAll(policy);
else
// Otherwise, the capabilities must be filtered accordingly.
builder.allow(policy, filter);
}
}
private void setImplicitAccessToNativeAndEECapabilities(RegionFilterBuilder builder) {
builder.allowAll(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
builder.allowAll(NativeNamespace.NATIVE_NAMESPACE);
}
private void setImportIsolationPolicy(RegionFilterBuilder builder, SubsystemImportServiceHeader header) throws InvalidSyntaxException {
if (header == null)
return;
for (SubsystemImportServiceHeader.Clause clause : header.getClauses()) {
SubsystemImportServiceRequirement requirement = new SubsystemImportServiceRequirement(clause, this);
String policy = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
String filter = requirement.getDirectives().get(SubsystemImportServiceRequirement.DIRECTIVE_FILTER);
builder.allow(policy, filter);
}
}
}