| /******************************************************************************* |
| * Copyright (c) 2008, 2011 VMware Inc. and others |
| * 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 |
| * EclipseSource - Bug 358442 Change InstallArtifact graph from a tree to a DAG |
| *******************************************************************************/ |
| |
| package org.eclipse.virgo.kernel.model.internal.deployer; |
| |
| import org.eclipse.equinox.region.RegionDigraph; |
| import org.eclipse.equinox.region.Region; |
| import org.eclipse.virgo.nano.deployer.api.core.DeploymentException; |
| import org.eclipse.virgo.kernel.install.artifact.BundleInstallArtifact; |
| import org.eclipse.virgo.kernel.install.artifact.ConfigInstallArtifact; |
| import org.eclipse.virgo.kernel.install.artifact.InstallArtifact; |
| import org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListener; |
| import org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListenerSupport; |
| import org.eclipse.virgo.kernel.install.artifact.PlanInstallArtifact; |
| import org.eclipse.virgo.kernel.model.Artifact; |
| import org.eclipse.virgo.kernel.model.BundleArtifact; |
| import org.eclipse.virgo.kernel.model.RuntimeArtifactRepository; |
| import org.eclipse.virgo.kernel.model.internal.SpringContextAccessor; |
| import org.eclipse.virgo.nano.serviceability.NonNull; |
| import org.osgi.framework.BundleContext; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Implementation of {@link InstallArtifactLifecycleListener} that notices |
| * {@link InstallArtifactLifecycleListener#onInstalling(InstallArtifact)} and |
| * {@link InstallArtifactLifecycleListener#onUninstalled(InstallArtifact)} calls to add and remove respectively |
| * {@link Artifact}s from the {@link RuntimeArtifactRepository} |
| * <p /> |
| * An existing artifact with the same type, name, and version as the incoming artifact is not replaced except in the |
| * case of a bundle. An existing {@link BundleArtifact} is replaced by an incoming {@link DeployerBundleArtifact}. This |
| * prevents the RAM being corrupted if an attempt it made to install an artifact which belongs to an existing install |
| * tree. See {@link TreeRestrictingInstallArtifactLifecycleListener}. |
| * <p /> |
| * |
| * <strong>Concurrent Semantics</strong><br /> |
| * |
| * Threadsafe |
| * |
| */ |
| class ModelInstallArtifactLifecycleListener extends InstallArtifactLifecycleListenerSupport { |
| |
| private static final String USER_REGION_NAME = "org.eclipse.virgo.region.user"; |
| |
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); |
| |
| private final RuntimeArtifactRepository artifactRepository; |
| |
| private final BundleContext bundleContext; |
| |
| private final RegionDigraph regionDigraph; |
| |
| private final Region globalRegion; |
| |
| private final SpringContextAccessor springContextAccessor; |
| |
| public ModelInstallArtifactLifecycleListener(@NonNull BundleContext bundleContext, @NonNull RuntimeArtifactRepository artifactRepository, @NonNull RegionDigraph regionDigraph, @NonNull Region globalRegion, @NonNull SpringContextAccessor springContextAccessor) { |
| this.bundleContext = bundleContext; |
| this.artifactRepository = artifactRepository; |
| this.regionDigraph = regionDigraph; |
| this.springContextAccessor = springContextAccessor; |
| this.globalRegion = globalRegion; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void onInstalling(InstallArtifact installArtifact) throws DeploymentException { |
| logEvent("installing", installArtifact); |
| if (installArtifact instanceof PlanInstallArtifact) { |
| addPlan((PlanInstallArtifact) installArtifact); |
| } else if (installArtifact instanceof BundleInstallArtifact) { |
| addOrReplaceBundle((BundleInstallArtifact) installArtifact); |
| } else if (installArtifact instanceof ConfigInstallArtifact) { |
| addConfiguration((ConfigInstallArtifact) installArtifact); |
| }else { |
| addArtifact(installArtifact); |
| } |
| } |
| |
| private void addConfiguration(ConfigInstallArtifact configInstallArtifact) { |
| this.artifactRepository.add(new DeployerConfigArtifact(this.bundleContext, configInstallArtifact, this.globalRegion)); |
| } |
| |
| private void addPlan(PlanInstallArtifact planInstallArtifact) { |
| this.artifactRepository.add(new DeployerCompositeArtifact(this.bundleContext, planInstallArtifact, this.globalRegion)); |
| } |
| |
| private void addOrReplaceBundle(BundleInstallArtifact bundleInstallArtifact) { |
| Artifact existingBundleArtifact = this.artifactRepository.getArtifact(bundleInstallArtifact.getType(), bundleInstallArtifact.getName(), bundleInstallArtifact.getVersion(), getRegion(USER_REGION_NAME)); |
| if (!(existingBundleArtifact instanceof DeployerBundleArtifact)) { |
| remove(bundleInstallArtifact); |
| this.artifactRepository.add(new DeployerBundleArtifact(this.bundleContext, bundleInstallArtifact, getRegion(USER_REGION_NAME), this.springContextAccessor)); |
| } |
| } |
| |
| private void addArtifact(InstallArtifact installArtifact) { |
| this.artifactRepository.add(new DeployerArtifact(this.bundleContext, installArtifact, this.globalRegion)); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void onInstallFailed(InstallArtifact installArtifact) throws DeploymentException { |
| logEvent("install failed", installArtifact); |
| remove(installArtifact); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void onUninstalled(InstallArtifact installArtifact) throws DeploymentException { |
| logEvent("uninstalled", installArtifact); |
| remove(installArtifact); |
| } |
| |
| private void logEvent(String event, InstallArtifact installArtifact) { |
| this.logger.info("Processing " + event + " event for {} '{}' version '{}'", |
| installArtifact.getType(), installArtifact.getName(), installArtifact.getVersion().toString()); |
| } |
| |
| private void remove(InstallArtifact installArtifact) { |
| if(installArtifact instanceof BundleInstallArtifact){ |
| this.artifactRepository.remove(installArtifact.getType(), installArtifact.getName(), installArtifact.getVersion(), getRegion(USER_REGION_NAME)); |
| } else { |
| this.artifactRepository.remove(installArtifact.getType(), installArtifact.getName(), installArtifact.getVersion(), this.globalRegion); |
| } |
| } |
| |
| private Region getRegion(String name){ |
| return this.regionDigraph.getRegion(name); |
| } |
| |
| } |