/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aries.subsystem.core.internal; import java.util.Collection; import java.util.Map; import org.apache.aries.subsystem.core.archive.DeploymentManifest; import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader; import org.apache.aries.subsystem.core.archive.SubsystemContentHeader; import org.apache.aries.subsystem.core.archive.SubsystemManifest; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.framework.wiring.BundleRevision; import org.osgi.resource.Namespace; import org.osgi.resource.Requirement; import org.osgi.resource.Resource; import org.osgi.service.coordinator.Coordination; import org.osgi.service.coordinator.CoordinationException; import org.osgi.service.subsystem.Subsystem; import org.osgi.service.subsystem.SubsystemConstants; import org.osgi.service.subsystem.SubsystemException; import org.osgi.service.subsystem.Subsystem.State; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Utils { private static final Logger logger = LoggerFactory.getLogger(Utils.class); public static String computeCoordinationName(Subsystem subsystem) { return subsystem.getSymbolicName() + '-' + subsystem.getSubsystemId(); } public static Coordination createCoordination() { return Activator.getInstance().getCoordinator().begin(BasicSubsystem.ROOT_SYMBOLIC_NAME + "-0", 0); } public static Coordination createCoordination(BasicSubsystem subsystem) { return Activator.getInstance().getCoordinator().begin(computeCoordinationName(subsystem), 0); } public static BasicSubsystem findFirstSubsystemAcceptingDependenciesStartingFrom(BasicSubsystem subsystem) { // The following loop is guaranteed to end once the root subsystem has // been reached. while (!isAcceptDependencies(subsystem)) subsystem = (BasicSubsystem)subsystem.getParents().iterator().next(); return subsystem; } public static BasicSubsystem findFirstScopedAncestorWithSharingPolicy(SubsystemResource descendant) { Collection<BasicSubsystem> parents = descendant.getParents(); if (parents == null || parents.isEmpty()) { return null; } BasicSubsystem result = (BasicSubsystem) parents.iterator().next(); // The result is defined as the first scoped ancestor whose sharing // policy has already been set. This covers the case of multiple // subsystems from the same archive being installed whose regions will // form a tree of depth N. while ( // We only want scoped subsystems because they control // the region. !result.isScoped() // If the state is INSTALLING then the sharing policy // has not yet been set. This means we cannot use the // region in order to test visibility and must proceed // to the next parent. || result.getState().equals(State.INSTALLING)) { result = result.getResource().getParents().iterator().next(); } return result; } public static BasicSubsystem findScopedSubsystemInRegion(BasicSubsystem subsystem) { while (!subsystem.isScoped()) subsystem = (BasicSubsystem)subsystem.getParents().iterator().next(); return subsystem; } public static int getActiveUseCount(Resource resource) { int result = 0; for (BasicSubsystem subsystem : Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource)) { if ( // ACTIVE subsystem referencing the resource. Subsystem.State.ACTIVE.equals(subsystem.getState()) // Ensure unmanaged bundle constituents of the root subsystem are not stopped or uninstalled. || (subsystem.isRoot() && isBundle(resource))) { result++; } } return result; } public static long getId(Resource resource) { if (resource instanceof BasicSubsystem) return ((BasicSubsystem)resource).getSubsystemId(); if (resource instanceof BundleRevision) return ((BundleRevision)resource).getBundle().getBundleId(); return -1; } public static void handleTrowable(Throwable t) { if (t instanceof SubsystemException) { throw (SubsystemException)t; } if (t instanceof SecurityException) { throw (SecurityException)t; } throw new SubsystemException(t); } public static void installResource(Resource resource, BasicSubsystem subsystem) { Coordination coordination = Utils.createCoordination(subsystem); try { ResourceInstaller.newInstance(coordination, resource, subsystem).install(); } catch (Throwable t) { coordination.fail(t); } finally { try { coordination.end(); } catch (CoordinationException e) { logger.error("Resource could not be installed", e); } } } public static boolean isAcceptDependencies(BasicSubsystem subsystem) { return subsystem.getSubsystemManifest().getSubsystemTypeHeader().getProvisionPolicyDirective().isAcceptDependencies(); } public static boolean isBundle(Resource resource) { String type = ResourceHelper.getTypeAttribute(resource); return IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type); } public static boolean isFragment(Resource resource) { String type = ResourceHelper.getTypeAttribute(resource); return IdentityNamespace.TYPE_FRAGMENT.equals(type); } public static boolean isEffectiveResolve(Requirement requirement) { Map<String, String> directives = requirement.getDirectives(); String value = directives.get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE); return value == null || Namespace.EFFECTIVE_RESOLVE.equals(value); } public static boolean isMandatory(Requirement requirement) { Map<String, String> directives = requirement.getDirectives(); String value = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE); return value == null || Namespace.RESOLUTION_MANDATORY.equals(value); } /* * The Deployed-Content header in the deployment manifest is used to store * information about explicitly installed resources and provisioned * dependencies in addition to content for persistence purposes. This method * returns true only if the resource is "true" content of the subsystem and, * therefore, uses the Subsystem-Content header from the subsystem manifest. */ public static boolean isContent(BasicSubsystem subsystem, Resource resource) { SubsystemManifest subsystemManifest = subsystem.getSubsystemManifest(); if (subsystemManifest == null) return false; SubsystemContentHeader subsystemContentHeader = subsystemManifest.getSubsystemContentHeader(); if (subsystemContentHeader == null) return false; return subsystemContentHeader.contains(resource); } public static boolean isDependency(BasicSubsystem subsystem, Resource resource) { DeploymentManifest manifest = subsystem.getDeploymentManifest(); if (manifest == null) return false; ProvisionResourceHeader header = manifest.getProvisionResourceHeader(); if (header == null) return false; return header.contains(resource); } public static boolean isInstallableResource(Resource resource) { return !isSharedResource(resource); } public static boolean isRegionContextBundle(Resource resource) { return ResourceHelper.getSymbolicNameAttribute(resource).startsWith( RegionContextBundleHelper.SYMBOLICNAME_PREFIX); } public static boolean isSharedResource(Resource resource) { return resource instanceof BasicSubsystem || resource instanceof BundleRevision || resource instanceof BundleRevisionResource; } public static boolean isSubsystem(Resource resource) { String type = ResourceHelper.getTypeAttribute(resource); return SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type) || SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type) || SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type); } public static boolean isProvisionDependenciesInstall(BasicSubsystem subsystem) { return subsystem.getSubsystemManifest().getSubsystemTypeHeader().getAriesProvisionDependenciesDirective().isInstall(); } }