/* * JBoss, Home of Professional Open Source * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.jboss.arquillian.impl.client.container; import java.util.List; import java.util.concurrent.Callable; import org.jboss.arquillian.impl.client.container.event.DeployDeployment; import org.jboss.arquillian.impl.client.container.event.DeployManagedDeployments; import org.jboss.arquillian.impl.client.container.event.DeploymentEvent; import org.jboss.arquillian.impl.client.container.event.UnDeployDeployment; import org.jboss.arquillian.impl.client.container.event.UnDeployManagedDeployments; import org.jboss.arquillian.impl.domain.Container; import org.jboss.arquillian.impl.domain.ContainerRegistry; import org.jboss.arquillian.spi.client.container.DeployableContainer; import org.jboss.arquillian.spi.client.deployment.DeploymentDescription; import org.jboss.arquillian.spi.client.deployment.DeploymentScenario; import org.jboss.arquillian.spi.client.protocol.metadata.ProtocolMetaData; import org.jboss.arquillian.spi.client.test.TargetDescription; import org.jboss.arquillian.spi.core.Event; import org.jboss.arquillian.spi.core.Injector; import org.jboss.arquillian.spi.core.Instance; import org.jboss.arquillian.spi.core.InstanceProducer; import org.jboss.arquillian.spi.core.annotation.DeploymentScoped; import org.jboss.arquillian.spi.core.annotation.Inject; import org.jboss.arquillian.spi.core.annotation.Observes; import org.jboss.arquillian.spi.event.container.AfterDeploy; import org.jboss.arquillian.spi.event.container.AfterUnDeploy; import org.jboss.arquillian.spi.event.container.BeforeDeploy; import org.jboss.arquillian.spi.event.container.BeforeUnDeploy; import org.jboss.arquillian.spi.event.container.DeployerEvent; /** * Controller for handling all Deployment related operations. <br/> * <br/> * * Fires DeployDeployment events for each deployment that should be deployed during startup. This so the Cores exception handling * will be triggered if Deployment fails inside the context of the deployment and container. This lets extensions listen for Exceptions types * and handle them inside the same context. * * @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a> * @version $Revision: $ */ public class ContainerDeployController { @Inject private Instance<ContainerRegistry> containerRegistry; @Inject private Instance<DeploymentScenario> deploymentScenario; @Inject private Instance<Injector> injector; /** * Deploy all deployments marked as startup = true. * * @param event * @throws Exception */ public void deployManaged(@Observes DeployManagedDeployments event) throws Exception { forEachManagedDeployment(new Operation<Container, DeploymentDescription>() { @Inject private Event<DeploymentEvent> event; @Override public void perform(Container container, DeploymentDescription deployment) throws Exception { event.fire(new DeployDeployment(container, deployment)); } }); } /** * Undeploy all deployments marked as startup = true. * * @param event * @throws Exception */ public void undeployManaged(@Observes UnDeployManagedDeployments event) throws Exception { forEachManagedDeployment(new Operation<Container, DeploymentDescription>() { @Inject private Event<DeploymentEvent> event; @Override public void perform(Container container, DeploymentDescription deployment) throws Exception { event.fire(new UnDeployDeployment(container, deployment)); } }); } public void deploy(@Observes final DeployDeployment event) throws Exception { executeOperation(new Callable<Void>() { @Inject private Event<DeployerEvent> deployEvent; @Inject @DeploymentScoped private InstanceProducer<DeploymentDescription> deploymentDescription; @Inject @DeploymentScoped private InstanceProducer<ProtocolMetaData> protocolMetadata; @Override public Void call() throws Exception { DeployableContainer<?> deployableContainer = event.getDeployableContainer(); DeploymentDescription deployment = event.getDeployment(); /* * TODO: should the DeploymentDescription producer some how be automatically registered ? * Or should we just 'know' who is the first one to create the context */ deploymentDescription.set(deployment); deployEvent.fire(new BeforeDeploy(deployableContainer, deployment)); if(deployment.isArchiveDeployment()) { protocolMetadata.set(deployableContainer.deploy( deployment.getTestableArchive() != null ? deployment.getTestableArchive():deployment.getArchive())); } else { deployableContainer.deploy(deployment.getDescriptor()); } deployEvent.fire(new AfterDeploy(deployableContainer, deployment)); return null; } }); } public void undeploy(@Observes final UnDeployDeployment event) throws Exception { executeOperation(new Callable<Void>() { @Inject private Event<DeployerEvent> deployEvent; @Override public Void call() throws Exception { DeployableContainer<?> deployableContainer = event.getDeployableContainer(); DeploymentDescription deployment = event.getDeployment(); deployEvent.fire(new BeforeUnDeploy(deployableContainer, deployment)); if(deployment.isArchiveDeployment()) { try { deployableContainer.undeploy( deployment.getTestableArchive() != null ? deployment.getTestableArchive():deployment.getArchive()); } catch (Exception e) { // TODO: Evaluate, should this be moved to DeploymentExceptionHandler? // silently ignore UnDeploy exceptions if a expected exception during deploy(it is probably not deployed) if(deployment.getExpectedException() == null) { throw e; } } } else { deployableContainer.undeploy(deployment.getDescriptor()); } deployEvent.fire(new AfterUnDeploy(deployableContainer, deployment)); return null; } }); } private void forEachManagedDeployment(Operation<Container, DeploymentDescription> operation) throws Exception { injector.get().inject(operation); ContainerRegistry containerRegistry = this.containerRegistry.get(); DeploymentScenario deploymentScenario = this.deploymentScenario.get(); for(TargetDescription target : deploymentScenario.getTargets()) { List<DeploymentDescription> startUpDeployments = deploymentScenario.getStartupDeploymentsFor(target); if(startUpDeployments.size() == 0) { continue; // nothing to do, move on } // Container should exists, handled by up front validation Container container = containerRegistry.getContainer(target); for(DeploymentDescription deployment : startUpDeployments) { operation.perform(container, deployment); } } } private void executeOperation(Callable<Void> operation) throws Exception { injector.get().inject(operation); operation.call(); } public interface Operation<T, X> { void perform(T container, X deployment) throws Exception; } }