/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. 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.deployment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jboss.arquillian.impl.ThreadContext;
import org.jboss.arquillian.impl.client.deployment.event.GenerateDeployment;
import org.jboss.arquillian.impl.domain.Container;
import org.jboss.arquillian.impl.domain.ContainerRegistry;
import org.jboss.arquillian.impl.domain.ProtocolDefinition;
import org.jboss.arquillian.impl.domain.ProtocolRegistry;
import org.jboss.arquillian.spi.ServiceLoader;
import org.jboss.arquillian.spi.TestClass;
import org.jboss.arquillian.spi.TestDeployment;
import org.jboss.arquillian.spi.client.deployment.ApplicationArchiveProcessor;
import org.jboss.arquillian.spi.client.deployment.AuxiliaryArchiveAppender;
import org.jboss.arquillian.spi.client.deployment.AuxiliaryArchiveProcessor;
import org.jboss.arquillian.spi.client.deployment.DeploymentDescription;
import org.jboss.arquillian.spi.client.deployment.DeploymentPackager;
import org.jboss.arquillian.spi.client.deployment.DeploymentScenario;
import org.jboss.arquillian.spi.client.deployment.DeploymentScenarioGenerator;
import org.jboss.arquillian.spi.client.deployment.ProtocolArchiveProcessor;
import org.jboss.arquillian.spi.client.protocol.Protocol;
import org.jboss.arquillian.spi.client.protocol.ProtocolDescription;
import org.jboss.arquillian.spi.client.test.TargetDescription;
import org.jboss.arquillian.spi.core.Instance;
import org.jboss.arquillian.spi.core.InstanceProducer;
import org.jboss.arquillian.spi.core.annotation.ClassScoped;
import org.jboss.arquillian.spi.core.annotation.Inject;
import org.jboss.arquillian.spi.core.annotation.Observes;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.container.ClassContainer;
/**
* DeploymentGenerator
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
public class DeploymentGenerator
{
@Inject
private Instance<ServiceLoader> serviceLoader;
@Inject @ClassScoped
private InstanceProducer<DeploymentScenario> deployment;
@Inject
private Instance<ContainerRegistry> containerRegistry;
@Inject
private Instance<ProtocolRegistry> protocolRegistry;
public void generateDeployment(@Observes GenerateDeployment event)
{
DeploymentScenarioGenerator generator = serviceLoader.get().onlyOne(
DeploymentScenarioGenerator.class, AnnotationDeploymentScenarioGenerator.class);
DeploymentScenario scenario = generator.generate(event.getTestClass());
validate(scenario);
createTestableDeployments(scenario, event.getTestClass());
deployment.set(scenario);
}
//-------------------------------------------------------------------------------------||
// Validate DeploymentScenario --------------------------------------------------------||
//-------------------------------------------------------------------------------------||
protected void validate(DeploymentScenario scenario)
{
ContainerRegistry conReg = containerRegistry.get();
for(TargetDescription target : scenario.getTargets())
{
Container container = conReg.getContainer(target);
if(container == null)
{
throw new ValidationException(
DeploymentScenario.class.getSimpleName() + " contains targets not maching any defined Container in the registry. " + target.getName());
}
}
ProtocolRegistry proReg = protocolRegistry.get();
for(ProtocolDescription proDesc : scenario.getProtocols())
{
if(ProtocolDescription.DEFAULT.equals(proDesc))
{
continue;
}
ProtocolDefinition protocol = proReg.getProtocol(proDesc);
if(protocol == null)
{
throw new ValidationException(
DeploymentScenario.class.getSimpleName() + " contains protcols not maching any defined Protocol in the registry. " + proDesc.getName());
}
}
}
//-------------------------------------------------------------------------------------||
// Enrich with Protocol Packaging -----------------------------------------------------||
//-------------------------------------------------------------------------------------||
/**
* @param scenario
*/
private void createTestableDeployments(DeploymentScenario scenario, TestClass testCase)
{
ProtocolRegistry protoReg = protocolRegistry.get();
buildTestableDeployments(scenario, testCase, protoReg);
}
private void buildTestableDeployments(DeploymentScenario scenario, TestClass testCase, ProtocolRegistry protoReg)
{
for(DeploymentDescription deployment : scenario.getDeployments())
{
if(!deployment.testable() || !deployment.isArchiveDeployment())
{
continue;
}
// TODO: could be optimalized to only be loaded pr Container
List<Archive<?>> auxiliaryArchives = loadAuxiliaryArchives(deployment);
ProtocolDefinition protocolDefinition = protoReg.getProtocol(deployment.getProtocol());
if(protocolDefinition == null)
{
protocolDefinition = protoReg.getProtocol(
containerRegistry.get().getContainer(deployment.getTarget()).getDeployableContainer().getDefaultProtocol());
}
Protocol<?> protocol = protocolDefinition.getProtocol();
DeploymentPackager packager = protocol.getPackager();
Archive<?> applicationArchive = deployment.getArchive();
applyApplicationProcessors(deployment.getArchive(), testCase);
applyAuxiliaryProcessors(auxiliaryArchives);
try
{
// this should be made more reliable, does not work with e.g. a EnterpriseArchive
if(ClassContainer.class.isInstance(applicationArchive))
{
ClassContainer<?> classContainer = ClassContainer.class.cast(applicationArchive);
classContainer.addClass(testCase.getJavaClass());
}
}
catch (UnsupportedOperationException e)
{
/*
* Quick Fix: https://jira.jboss.org/jira/browse/ARQ-118
* Keep in mind when rewriting for https://jira.jboss.org/jira/browse/ARQ-94
* that a ShrinkWrap archive might not support a Container if even tho the
* ContianerBase implements it. Check the Archive Interface..
*/
}
ClassLoader classLoader = containerRegistry.get().getContainer(deployment.getTarget()).getClassLoader();
deployment.setTestableArchive(
packager.generateDeployment(
new TestDeployment(applicationArchive, auxiliaryArchives),
serviceLoader.get().all(classLoader, ProtocolArchiveProcessor.class)));
}
}
private List<Archive<?>> loadAuxiliaryArchives(DeploymentDescription deployment)
{
List<Archive<?>> archives = new ArrayList<Archive<?>>();
ClassLoader classLoader = containerRegistry.get().getContainer(deployment.getTarget()).getClassLoader();
// load based on the Containers ClassLoader
Collection<AuxiliaryArchiveAppender> archiveAppenders = serviceLoader.get().all(
classLoader, AuxiliaryArchiveAppender.class);
try
{
ThreadContext.set(classLoader);
for(AuxiliaryArchiveAppender archiveAppender : archiveAppenders)
{
archives.add(archiveAppender.createAuxiliaryArchive());
}
}
finally
{
ThreadContext.reset();
}
return archives;
}
private void applyApplicationProcessors(Archive<?> applicationArchive, TestClass testClass)
{
Collection<ApplicationArchiveProcessor> processors = serviceLoader.get().all(ApplicationArchiveProcessor.class);
for(ApplicationArchiveProcessor processor : processors)
{
processor.process(applicationArchive, testClass);
}
}
private void applyAuxiliaryProcessors(List<Archive<?>> auxiliaryArchives)
{
Collection<AuxiliaryArchiveProcessor> processors = serviceLoader.get().all(AuxiliaryArchiveProcessor.class);
for(AuxiliaryArchiveProcessor processor : processors)
{
for(Archive<?> auxiliaryArchive : auxiliaryArchives)
{
processor.process(auxiliaryArchive);
}
}
}
}