Created
September 27, 2011 19:28
-
-
Save PiotrNowicki/1245983 to your computer and use it in GitHub Desktop.
Arquillian - multiple deployments for different containers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////////////////// | |
// DeploymentScenarioGenerator extension | |
///////////////////////////////////////////////////////////////////////////////////////// | |
/** | |
* Registers the {@link FlexibleRegisterDeployment} which allows to choose the | |
* {@link Deployment} annotated method from the test class which will be used | |
* for particular target container. | |
* | |
* @author PedroKowalski | |
* | |
*/ | |
public class DeploymentRegisterer implements LoadableExtension { | |
@Override | |
public void register(ExtensionBuilder builder) { | |
builder.service(DeploymentScenarioGenerator.class, | |
FlexibleRegisterDeployment.class); | |
} | |
/** | |
* Chooses the appropriate {@link Deployment} annotated method basing on the | |
* chosen target container. The target container is defined using | |
* {@link UseInContainer} annotation. | |
* | |
* If there is only one {@link Deployment} annotated method, it will be | |
* chosen by default. It's assumed that no container-specific deployment | |
* means that no special steps are need to be taken for different | |
* containers. | |
* | |
* @see DeploymentRegisterer | |
* @see TargetContainerName | |
* @see UseInContainer | |
* | |
* @author PedroKowalski | |
* | |
*/ | |
public static class FlexibleRegisterDeployment implements | |
DeploymentScenarioGenerator { | |
/** | |
* We need to know what container are we actually using. | |
*/ | |
@Inject | |
Instance<ContainerRegistry> container; | |
private static final Logger log = Logger | |
.getLogger(FlexibleRegisterDeployment.class.getName()); | |
@Override | |
public List<DeploymentDescription> generate(TestClass testClass) { | |
Method m = getMethodForDeployment(testClass, getTargetContainer()); | |
WebArchive deployment; | |
try { | |
deployment = (WebArchive) m.invoke(testClass); | |
} catch (Exception e) { | |
throw new IllegalStateException(e); | |
} | |
return Arrays.asList(new DeploymentDescription( | |
"On-the-fly deployment", deployment)); | |
} | |
/** | |
* Gets the deployment method for particular target container. | |
* | |
* @param clazz | |
* test class which contains {@link Deployment} annotated | |
* method(s). | |
* @param targetContainer | |
* target container adapter which is active in classpath. | |
* @return deployment method to be invoked for specified target | |
* container. | |
*/ | |
private Method getMethodForDeployment(TestClass clazz, | |
TargetContainerName targetContainer) { | |
Method[] methods = clazz.getMethods(Deployment.class); | |
if (methods.length == 0) { | |
throw new IllegalStateException( | |
"At least one @Deployment method is required"); | |
} else { | |
for (Method method : methods) { | |
if (method.getAnnotation(UseInContainer.class).value() | |
.equals(targetContainer)) { | |
return method; | |
} | |
} | |
MessageFormat msg = new MessageFormat( | |
"Deployment method cannot be found. Are you sure you have an appropriate @UseInContainer annotation on one of your @Deployment methods in {1}?"); | |
throw new IllegalStateException(msg.format(new Object[] { | |
targetContainer, clazz.getName() })); | |
} | |
} | |
/** | |
* Gets the target container which is in user's classpath and is used in | |
* the test run. | |
* | |
* If no value is specified, the default container ( | |
* {@link TargetContainerName#GLASSFISH}) will be chosen. | |
* | |
* @return name of the target container to be used. | |
*/ | |
private TargetContainerName getTargetContainer() { | |
DeployableContainer<?> dc = container.get().getContainers().get(0) | |
.getDeployableContainer(); | |
TargetContainerName result = TargetContainerName.get(dc.getClass()); | |
log.info("Using '" + result + "' as a target container."); | |
return result; | |
} | |
} | |
} | |
///////////////////////////////////////////////////////////////////////////////////////// | |
// Possible target containers | |
///////////////////////////////////////////////////////////////////////////////////////// | |
/** | |
* Represents possible target container which deployment can be explicitly set | |
* in test class. | |
* | |
* @author PedroKowalski | |
* | |
*/ | |
public enum TargetContainerName { | |
/** | |
* Glassfish 3.1 container. | |
*/ | |
GLASSFISH("container.glassfish"), | |
/** | |
* JBoss AS7 container. | |
*/ | |
JBOSSAS7("org.jboss.as.arquillian.container"); | |
/** | |
* Holds the unique part of the container adapter package name. | |
*/ | |
private String packageName; | |
private static final Logger log = Logger | |
.getLogger(TargetContainerName.class.getName()); | |
private TargetContainerName(String packageName) { | |
this.packageName = packageName; | |
} | |
public String getPackageName() { | |
return packageName; | |
} | |
/** | |
* Gets the {@link TargetContainerName} basing on the runtime deployment | |
* class passed as an argument. | |
* | |
* @param clazz | |
* deployment class for which the target container should be | |
* returned | |
* @return target container name | |
*/ | |
public static TargetContainerName get(Class<?> clazz) { | |
for (TargetContainerName tcn : values()) { | |
String packageName = clazz.getPackage().getName().toLowerCase(); | |
if (packageName.contains(tcn.getPackageName())) { | |
return tcn; | |
} | |
} | |
// No matches found - go with the default. | |
log.warning("No matching container for '" + clazz.getName() | |
+ "' found. Falling back to default."); | |
return GLASSFISH; | |
} | |
} | |
///////////////////////////////////////////////////////////////////////////////////////// | |
// Exemplary usage in test class | |
///////////////////////////////////////////////////////////////////////////////////////// | |
@Deployment | |
@UseInContainer(TargetContainerName.GLASSFISH) | |
public static WebArchive createGlassFishDeployment() {} | |
@Deployment | |
@UseInContainer(TargetContainerName.JBOSSAS7) {} | |
///////////////////////////////////////////////////////////////////////////////////////// | |
// UseInContainer annotation | |
///////////////////////////////////////////////////////////////////////////////////////// | |
/** | |
* Defines that the Deployment should be used only when particular container | |
* adapter is active. | |
* | |
* @author PedroKowalski | |
* | |
*/ | |
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.METHOD) | |
public @interface UseInContainer { | |
/** | |
* Name of the container for which the deployment should be used. | |
*/ | |
TargetContainerName value(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment