/******************************************************************************* * Copyright (c) 2008, 2010 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VMware Inc. - initial contribution *******************************************************************************/ package org.eclipse.virgo.kernel.install.artifact.internal; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.osgi.framework.Version; import org.eclipse.virgo.kernel.artifact.fs.ArtifactFS; import org.eclipse.virgo.nano.deployer.api.core.DeployerLogEvents; import org.eclipse.virgo.nano.deployer.api.core.DeploymentException; import org.eclipse.virgo.nano.deployer.api.core.FatalDeploymentException; import org.eclipse.virgo.kernel.install.artifact.BundleInstallArtifact; import org.eclipse.virgo.kernel.install.artifact.InstallArtifact; import org.eclipse.virgo.kernel.install.artifact.ScopeServiceRepository; import org.eclipse.virgo.kernel.install.artifact.internal.scoping.Scoper; import org.eclipse.virgo.kernel.install.artifact.internal.scoping.Scoper.DuplicateBundleSymbolicNameException; import org.eclipse.virgo.kernel.install.artifact.internal.scoping.Scoper.DuplicateExportException; import org.eclipse.virgo.kernel.install.artifact.internal.scoping.Scoper.UnsupportedBundleManifestVersionException; import org.eclipse.virgo.medic.eventlog.EventLogger; import org.eclipse.virgo.util.osgi.manifest.BundleManifest; /** * {@link ApplicationScoper} provides scoping of bundle manifests and Spring services for {@link MultiBundleApplication} * s. * <p /> * * <strong>Concurrent Semantics</strong><br /> * * This class is not thread safe. * */ final class PlanScoper { private static final String SCOPE_SEPARATOR = "-"; private List<InstallArtifact> scopeMembers; private final EventLogger eventLogger; private final Scoper scoper; private final ServiceScoper serviceScoper; private final String scopeName; private final Version scopeVersion; /** * Create a new {@link PlanScoper}. * * @param scopeMembers the items to be scoped * @param name the scope name * @param version the scope version * @param scopeServiceRepository the {@link StandardScopeServiceRepository} * @param eventLogger an {@link EventLogger} * @throws DeploymentException */ public PlanScoper(List<InstallArtifact> scopeMembers, String name, Version version, ScopeServiceRepository scopeServiceRepository, EventLogger eventLogger) throws DeploymentException { this.scopeMembers = scopeMembers; this.scopeName = createScopeName(name, version); this.scopeVersion = version; this.scoper = new Scoper(getBundleManifests(), this.scopeName); this.serviceScoper = new ServiceScoper(this.scopeName, scopeServiceRepository, eventLogger); this.eventLogger = eventLogger; } /** * Get the application scope name. * * @return the application scope name */ String getScopeName() { return this.scopeName; } private String createScopeName(String name, Version version) { String scopeName = name + SCOPE_SEPARATOR + versionToShortString(version); return scopeName; } private List<BundleManifest> getBundleManifests() throws DeploymentException { List<BundleManifest> bundleManifests = new ArrayList<BundleManifest>(); for (InstallArtifact scopeMember : this.scopeMembers) { if (scopeMember instanceof BundleInstallArtifact) { BundleInstallArtifact bundleInstallArtifact = (BundleInstallArtifact) scopeMember; try { bundleManifests.add(bundleInstallArtifact.getBundleManifest()); } catch (IOException e) { throw new DeploymentException("Cannot access bundle manifest for scoping", e); } } } return bundleManifests; } /** * Scope the application. * * @throws DeploymentException */ void scope() throws DeploymentException { try { // Transform the modules' bundle manifests to scope the OSGi // application. this.scoper.scope(); } catch (UnsupportedBundleManifestVersionException ubmve) { // This represents a failure to upgrade the manifest. throw new FatalDeploymentException("Cannot scope a bundle which does not specify a bundle manifest version of at least " + ubmve.getLowestSupportedVersion()); } catch (DuplicateBundleSymbolicNameException dbsne) { this.eventLogger.log(DeployerLogEvents.DUPLICATE_BSN_IN_SCOPE, dbsne, this.scopeName, this.scopeVersion, dbsne.getBundleSymbolicName()); throw new DeploymentException("More than one bundle in scope '" + this.scopeName + "' version '" + this.scopeVersion + "' has bundle symbolic name '" + dbsne.getBundleSymbolicName() + "'"); } catch (DuplicateExportException dee) { String packageName = dee.getPackageName(); String exporters = dee.getExporters(); this.eventLogger.log(DeployerLogEvents.DUPLICATE_PACKAGE_DURING_SCOPING, dee, this.scopeName, this.scopeVersion, packageName, exporters); throw new DeploymentException("Package '" + packageName + "' exported by more than one bundle [" + exporters + "] in scope '" + this.scopeName + "' version '" + this.scopeVersion + "'"); } this.serviceScoper.scope(getBundleArtifacts()); } private Set<ArtifactFS> getBundleArtifacts() { Set<ArtifactFS> bundleArtifacts = new HashSet<ArtifactFS>(); for (InstallArtifact scopeMember : this.scopeMembers) { if (scopeMember instanceof BundleInstallArtifact) { ArtifactFS artifactFS = scopeMember.getArtifactFS(); bundleArtifacts.add(artifactFS); } } return bundleArtifacts; } private static String versionToShortString(Version version) { String result = version.toString(); while (result.endsWith(".0")) { result = result.substring(0, result.length() - 2); } return result; } }