org.ow2.util.plan.deployer.impl.DeploymentPlanDeployer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of util-plan-deployer Show documentation
Show all versions of util-plan-deployer Show documentation
Deployer for the deployment plans and repositories data
The newest version!
/**
* OW2 Util
* Copyright (C) 2009-2012 Bull S.A.S.
* Copyright (C) 2008 SERLI
* Contact: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: DeploymentPlanDeployer.java 6240 2012-04-18 11:03:10Z sauthieg $
* --------------------------------------------------------------------------
*/
package org.ow2.util.plan.deployer.impl;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.ow2.util.archive.api.ArchiveException;
import org.ow2.util.archive.api.IArchive;
import org.ow2.util.archive.impl.ArchiveManager;
import org.ow2.util.ee.deploy.api.deployable.IDeployable;
import org.ow2.util.ee.deploy.api.deployable.OSGiDeployable;
import org.ow2.util.ee.deploy.api.deployer.DeployerException;
import org.ow2.util.ee.deploy.api.deployer.IDeployerManager;
import org.ow2.util.ee.deploy.api.deployer.UnsupportedDeployerException;
import org.ow2.util.ee.deploy.api.helper.DeployableHelperException;
import org.ow2.util.ee.deploy.impl.deployer.AbsDeployerList;
import org.ow2.util.ee.deploy.impl.helper.DeployableHelper;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
import org.ow2.util.plan.bindings.deploymentplan.Deployment;
import org.ow2.util.plan.bindings.deploymentplan.DeploymentHelper;
import org.ow2.util.plan.bindings.deploymentplan.DeploymentPlan;
import org.ow2.util.plan.bindings.deploymentplan.DeploymentPlanFragment;
import org.ow2.util.plan.bindings.exceptions.InvalidDeploymentException;
import org.ow2.util.plan.deploy.deployable.api.DeploymentPlanDeployable;
import org.ow2.util.plan.deploy.deployable.impl.DeploymentPlanDeployableImpl;
import org.ow2.util.plan.deployer.api.DeploymentPlanDeploymentException;
import org.ow2.util.plan.deployer.api.DeploymentPlanUndeploymentException;
import org.ow2.util.plan.deployer.api.FragmentDeploymentException;
import org.ow2.util.plan.deployer.api.FragmentUndeploymentException;
import org.ow2.util.plan.deployer.api.IDeploymentPlanDeployer;
import org.ow2.util.plan.deployer.api.condition.EvaluationException;
import org.ow2.util.plan.deployer.api.condition.IConditionEvaluator;
import org.ow2.util.plan.fetcher.api.IResourceFetcher;
import org.ow2.util.plan.fetcher.api.IResourceFetcherFactoryManager;
import org.ow2.util.plan.monitor.api.IResourceMonitor;
import org.ow2.util.plan.reader.plan.IPlanReader;
import org.ow2.util.url.URLUtils;
/**
* Deployer for the deployment plan deployables.
* @author Mickaël LEDUQUE
*/
//public class DeploymentPlanDeployer>
// extends AbsDeployerList implements IDeploymentPlanDeployer {
public class DeploymentPlanDeployer
extends AbsDeployerList implements IDeploymentPlanDeployer {
/**
* The DeployerManager that will be used to deploy parts of the deployment
* plans.
*/
private IDeployerManager deployerManager = null;
/**
* The Deployment -> Deployable mappings.
*/
private Map> deploymentToDeployableMap = new HashMap>();
/**
* The Deployment -> Fetcher mappings.
*/
private Map deploymentToFetcherMap = new HashMap();
/**
* The resource monitor.
*/
private IResourceMonitor resourceMonitor = null;
/**
* Logger.
*/
private static Log logger = LogFactory.getLog(DeploymentPlanDeployer.class);
/**
* The deployed deployment plans.
*/
private Collection deploymentPlans = new ArrayList();
/**
* The PlanReader that will be used to parse the deployment plan.
*/
private IPlanReader planReader;
/**
* The resource fetchers manager.
*/
private IResourceFetcherFactoryManager fetcherFactoryManager = null;
/**
* Evaluates conditional plans.
*/
private IConditionEvaluator conditionEvaluator;
/**
* {@inheritDoc}
* @throws UnsupportedDeployerException any.
*/
@Override
public void deploy(final IDeployable deployable) throws DeployerException, UnsupportedDeployerException {
if (deployable == null) {
throw new DeployerException("Null deployable");
}
if (!DeploymentPlanDeployable.class.isInstance(deployable)) {
throw new DeployerException("Bad deployable type " + deployable.getClass());
}
DeploymentPlanDeployable deploymentPlanDeployable = DeploymentPlanDeployable.class.cast(deployable);
DeploymentPlan deploymentPlan = null;
if (planReader == null) {
throw new DeployerException("Deployment aborted - The PlanReader is null");
}
URL archiveUrl = null;
try {
archiveUrl = deploymentPlanDeployable.getArchive().getURL();
} catch (ArchiveException e) {
throw new DeployerException("Error while getting URL for archive " + deploymentPlanDeployable.getArchive() + " - Deployment aborted", e);
}
try {
File archiveFile = URLUtils.urlToFile(archiveUrl);
deploymentPlan = planReader.readPlan(archiveFile);
} catch (Exception e) {
throw new DeployerException("Error while parsing archive " + archiveUrl + " - Deployment aborted", e);
}
if (deploymentPlan == null) {
// Some strange error occured
throw new DeployerException("The deployable " + deployable + " resolved in null deployment plan - Deployment aborted");
}
deploymentPlanDeployable.setAttachedData(deploymentPlan);
// Quickly exit the deployment if the plan level condition is not met
try {
if (!isActivated(deploymentPlan.getCondition())) {
return;
}
} catch (EvaluationException e) {
throw new DeployerException("Cannot evaluate condition '"
+ deploymentPlan.getCondition() + "'", e);
}
try {
deployDeploymentPlan(deploymentPlan);
} catch (DeploymentPlanDeploymentException e) {
throw new DeployerException("Deployment plan deployment failed", e);
}
logger.debug("Deployable {0} deployed", deployable);
this.deploymentPlans.add(deploymentPlanDeployable);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isDeployed(final IDeployable deployable) throws DeployerException {
return this.deploymentPlans.contains(deployable);
}
/**
* {@inheritDoc}
*/
@Override
public boolean supports(final IDeployable> deployable) {
return DeploymentPlanDeployableImpl.class.isInstance(deployable);
}
/**
* {@inheritDoc}
*/
@Override
public void undeploy(final IDeployable deployable) throws DeployerException {
if (deployable == null) {
throw new DeployerException("Null deployable");
}
if (!DeploymentPlanDeployable.class.isInstance(deployable)) {
throw new DeployerException("Bad deployable type " + deployable.getClass());
}
if (isDeployed(deployable)) {
/**
* the deployable provided by the caller in order to be undeployed
*/
DeploymentPlanDeployable deploymentPlanDeployableToUndeploy = DeploymentPlanDeployable.class.cast(deployable);
/**
* the deployable that will be undeployed is in the deploymentPlans list.
* Find it, and remove it from the deploymentPlans list.
*/
DeploymentPlanDeployable deploymentPlanDeployableToUndeployReally = null;
Iterator it = this.deploymentPlans.iterator();
while (it.hasNext()) {
DeploymentPlanDeployable deploymentPlanDeployable = it.next();
// As two Deployables with same URL are equal, we also have to compare hashCode values
if (deploymentPlanDeployable.equals(deploymentPlanDeployableToUndeploy)) {
deploymentPlanDeployableToUndeployReally = deploymentPlanDeployable;
break;
}
}
/**
* Undeploy the deployable we found.
*/
if (deploymentPlanDeployableToUndeployReally == null) {
throw new DeployerException("Didn't found deployable to undeploy" + deployable);
}
undeployRealDeployable(deploymentPlanDeployableToUndeployReally);
} else {
throw new DeployerException("Cannot undeploy deployable " + deployable + " that is not deployed");
}
}
/**
* Undeploy the same deployable which has been deployed previously.
* @param deploymentPlanDeployableToUndeployReally The given deployable
* @throws DeployerException If the undeploy operation fails.
*/
private void undeployRealDeployable(final DeploymentPlanDeployable deploymentPlanDeployableToUndeployReally) throws DeployerException {
this.deploymentPlans.remove(deploymentPlanDeployableToUndeployReally);
DeploymentPlan deploymentPlan = deploymentPlanDeployableToUndeployReally.getAttachedData();
try {
undeployDeploymentPlan(deploymentPlan);
} catch (DeploymentPlanUndeploymentException e) {
throw new DeployerException("Deployment plan undeployment failed" , e);
}
logger.debug("deployable {0} undeployed", deploymentPlanDeployableToUndeployReally);
}
/**
* {@inheritDoc}
*/
public void setPlanReader(final IPlanReader planReader) {
this.planReader = planReader;
}
/**
* {@inheritDoc}
*/
public IPlanReader getPlanReader() {
return this.planReader;
}
/**
* Deploys a deployment plan object.
* @param deploymentPlan the deployment plan.
* @throws DeploymentPlanDeploymentException
* @throws UnsupportedDeployerException
*/
private void deployDeploymentPlan(final DeploymentPlan deploymentPlan)
throws DeploymentPlanDeploymentException, UnsupportedDeployerException {
for (Deployment deployment : deploymentPlan.getDeployments()) {
DeploymentPlanFragment fragment = (DeploymentPlanFragment) deployment;
try {
deployDeployment(fragment);
fragment.setDeployed(true);
} catch (Exception deployException) {
// One deployment has failed. Is the deployment plan atomic?
if (deploymentPlan.isAtomic()) {
logger.error(
"The deployment plan {0} failed and is atomic; it must be undeployed",
deploymentPlan);
// try to undeploy everything
try {
undeployDeploymentPlan(deploymentPlan);
} catch (DeploymentPlanUndeploymentException undeployException) {
logger.error("The deployment plan was not correctly undeployed.");
}
throw new DeploymentPlanDeploymentException("Error while deploying part " + fragment + " of deployment plan " + deploymentPlan, deployException);
}
logger.error("Error while trying to deployed fragment ''{0}'' of deployment plan ''{1}''. Not atomic, so continue...", fragment, deploymentPlan, deployException);
}
}
}
private boolean isActivated(String condition) throws EvaluationException {
if (condition == null) {
// no condition => always activated
return true;
}
// Evaluate the real condition
return (conditionEvaluator.evaluate(condition));
}
private void undeployDeploymentPlan(final DeploymentPlan deploymentPlan) throws DeploymentPlanUndeploymentException {
for (Deployment deployment : deploymentPlan.getDeployments()) {
DeploymentPlanFragment fragment = (DeploymentPlanFragment) deployment;
boolean partialFail = false;
if (fragment.isDeployed()) {
try {
undeployDeployment(fragment);
fragment.setDeployed(false);
} catch (FragmentUndeploymentException e) {
logger.error("Error undeploying deployment {0} of deployment plan {1}",
fragment, deploymentPlan);
// Will continue to try undeploying other resources
partialFail = true;
}
}
// We've done as much as we could, now we can fail
// Note : we've lost the exception stack
if (partialFail == true) {
throw new DeploymentPlanUndeploymentException();
}
}
}
/**
* {@inheritDoc}
* @throws UnsupportedDeployerException
*/
public void deployDeployment(final Deployment deployment) throws FragmentDeploymentException, UnsupportedDeployerException {
if (deployment == null) {
throw new FragmentDeploymentException("Null deployment fragment.");
}
if (!(deployment instanceof DeploymentPlanFragment)) {
throw new FragmentDeploymentException("Bad deployment instance : " + deployment);
}
DeploymentPlanFragment fragment = (DeploymentPlanFragment)deployment;
// Quickly exit the deployment if the fragment level condition is not met
try {
if (!isActivated(fragment.getCondition())) {
return;
}
} catch (EvaluationException e) {
throw new FragmentDeploymentException("Cannot evaluate condition '"
+ fragment.getCondition() + "'", e);
}
Boolean reloadable = null;
try {
reloadable = DeploymentHelper.isReloadable(fragment);
} catch (InvalidDeploymentException e) {
throw new FragmentDeploymentException("Invalid deployment found : " + fragment, e);
}
File file = null;
IResourceFetcher fetcher = null;
try {
fetcher = this.fetcherFactoryManager.getResourceFetcher(fragment);
fetcher.resolve();
file = fetcher.getResource();
} catch (Exception e) {
throw new FragmentDeploymentException(e);
}
// File is a 'local' file containing the resource. We just need to deploy it the usual way.
if (file == null) {
throw new FragmentDeploymentException("Null file");
}
// Create an archive
IArchive archive = ArchiveManager.getInstance().getArchive(file);
if (archive == null) {
throw new FragmentDeploymentException("Null archive for file " + file);
}
// Create a deployable
IDeployable> deployable = null;
try {
deployable = DeployableHelper.getDeployable(archive);
} catch (DeployableHelperException e) {
throw new FragmentDeploymentException(e);
}
if (deployable == null) {
throw new FragmentDeploymentException("Null deployable for archive" + archive);
}
// Check the start property to define if the bundle must be started or not
if (OSGiDeployable.class.isInstance(deployable)) {
try {
Boolean start = DeploymentHelper.isStart(fragment);
OSGiDeployable.class.cast(deployable).setStart(start);
Boolean reference = DeploymentHelper.isReference(fragment);
OSGiDeployable.class.cast(deployable).setReference(reference);
Integer startLevel = DeploymentHelper.getStartLevel(fragment);
OSGiDeployable.class.cast(deployable).setStartLevel(startLevel);
Boolean startTransient = DeploymentHelper.isStartTransient(fragment);
OSGiDeployable.class.cast(deployable).setStartTransient(startTransient);
} catch (InvalidDeploymentException e) {
throw new FragmentDeploymentException("Invalid deployment found : " + fragment, e);
}
}
boolean isDeployed;
try {
isDeployed = this.deployerManager.isDeployed(deployable);
} catch (DeployerException e) {
throw new FragmentDeploymentException("Cannot check if deployable " + deployable + " is already deployed", e);
}
// Deploy the deployable only if it's not yet deployed
if (!isDeployed) {
try {
this.deployerManager.deploy(deployable);
} catch (DeployerException e) {
throw new FragmentDeploymentException("Exception while deploying deployable " + deployable, e);
} catch (UnsupportedDeployerException e) {
throw new UnsupportedDeployerException("No deployer found for deployable " + deployable, e);
}catch (Exception e) {
throw new FragmentDeploymentException("No deployer found for deployable " + deployable, e);
}
}
// Store the deployment->deployable
deploymentToDeployableMap.put(fragment, deployable);
if (reloadable) {
if (!deploymentToFetcherMap.containsValue(fetcher)) {
// Add this resource to the managed ones.
this.resourceMonitor.addMonitoredResource(fetcher);
}
// Store the deployment->fetcher
deploymentToFetcherMap.put(fragment, fetcher);
}
}
/**
* {@inheritDoc}
*/
/* The only cases this will be used are : 1. when undeploying a deployment plan and 2. when
redeploying a modified resource (by the monitor) */
public void undeployDeployment(final Deployment deployment) throws FragmentUndeploymentException {
if (deployment == null) {
throw new FragmentUndeploymentException("Null deployment fragment.");
}
// find the deployable and undeploy it
IDeployable> deployable = deploymentToDeployableMap.get(deployment);
if (deployable == null) {
throw new FragmentUndeploymentException("Cannot undeploy resource " + deployment.toString() + " - Trying to finish undeployment");
}
// find the fetcher and stop monitoring it
IResourceFetcher fetcher = deploymentToFetcherMap.get(deployment);
// Remove stored deployment entries from Maps
cleanDeploymentMaps(deployment, null);
if (fetcher != null) {
// Remove this resource from the monitored ones
if (!deploymentToFetcherMap.containsValue(fetcher)) {
try {
this.resourceMonitor.removeMonitoredResource(fetcher);
} catch (Exception e) {
logger.error("Cannot stop monitoring the resource ''{0}'':", deployment.toString());
}
} else {
logger.debug("Do not stop monitoring resource ''{0}'': another deployment plan makes reference to it.", deployment.toString());
}
}
// Undeploy only if no deployment plans make reference to this deployable
if (!deploymentToDeployableMap.containsValue(deployable)) {
try {
if(DeploymentPlanDeployable.class.isInstance(deployable)) {
undeployRealDeployable(DeploymentPlanDeployable.class.cast(deployable));
} else {
this.deployerManager.undeploy(deployable);
}
} catch (Exception e) {
throw new FragmentUndeploymentException("Could not undeploy resource " + deployable.getArchive() + " - Trying to finish undeployment");
}
} else {
// Remove stored sub deployments entries from Maps as the deployable has not been undeployed
cleanDeploymentMaps(deployment, deployable);
logger.debug("Do not undeploy archive ''{0}'': another deployment plan makes reference to it.", deployable.getArchive());
}
}
/**
* Remove Maps entries for a given deployment.
* In case the deployable is not null, also remove sub deployments.
* @param deployment The deployment to remove from Maps
* @param deployable The deployable to analyse (may be null)
*/
private void cleanDeploymentMaps(final Deployment deployment, final IDeployable> deployable) {
deploymentToDeployableMap.remove(deployment);
deploymentToFetcherMap.remove(deployment);
if (deployable != null && DeploymentPlanDeployable.class.isInstance(deployable)) {
DeploymentPlanDeployable deploymentPlanDeployable = DeploymentPlanDeployable.class.cast(deployable);
DeploymentPlan deploymentPlan = deploymentPlanDeployable.getAttachedData();
for (Deployment subDeployment : deploymentPlan.getDeployments()) {
cleanDeploymentMaps(subDeployment, deploymentToDeployableMap.get(subDeployment));
}
}
}
public void setFetcherFactoryManager(final IResourceFetcherFactoryManager factoryManager) {
this.fetcherFactoryManager = factoryManager;
}
/**
* {@inheritDoc}
*/
public IResourceFetcherFactoryManager getFetcherFactoryManager() {
return this.fetcherFactoryManager;
}
/**
* {@inheritDoc}
*/
public void setDeployerManager(final IDeployerManager deployerManager) {
this.deployerManager = deployerManager;
}
/**
* {@inheritDoc}
*/
public IDeployerManager getDeployerManager() {
return this.deployerManager;
}
/**
* {@inheritDoc}
*/
public Integer getDeploymentPlansCount() {
return this.deploymentPlans.size();
}
/**
* {@inheritDoc}
*/
public List getDeploymentPlansIds() {
List result = new ArrayList();
for (DeploymentPlanDeployable deploymentPlanDeployable : this.deploymentPlans) {
DeploymentPlan deploymentPlan = deploymentPlanDeployable.getAttachedData();
if (deploymentPlan.getId() == null) {
result.add("");
} else {
result.add(deploymentPlan.getId());
}
}
return result;
}
/**
* {@inheritDoc}
*/
public List getDeploymentPlansUrls() {
List result = new ArrayList();
for (DeploymentPlanDeployable deploymentPlanDeployable : this.deploymentPlans) {
URL url;
try {
url = deploymentPlanDeployable.getArchive().getURL();
result.add(URLUtils.urlToFile(url).getPath());
} catch (ArchiveException e) {
logger.error("Error in deployable archive.", e);
}
}
return result;
}
/**
* {@inheritDoc}
*/
public IResourceMonitor getResourceMonitor() {
return this.resourceMonitor;
}
/**
* {@inheritDoc}
*/
public void setResourceMonitor(final IResourceMonitor resourceMonitor) {
this.resourceMonitor = resourceMonitor;
}
/**
* {@inheritDoc}
*/
public DeploymentPlanDeployable getOwnerDeploymentPlanDeployable(final Deployment deployment) {
for (DeploymentPlanDeployable deploymentPlanDeployable : this.deploymentPlans) {
DeploymentPlan deploymentPlan = deploymentPlanDeployable.getAttachedData();
if (deploymentPlan.getDeployments().contains(deployment)) {
return deploymentPlanDeployable;
}
}
return null;
}
public void setConditionEvaluator(IConditionEvaluator conditionEvaluator) {
this.conditionEvaluator = conditionEvaluator;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy