org.jboss.as.arquillian.container.ContainerResourceTestEnricher Maven / Gradle / Ivy
/*
* Copyright 2015 Red Hat, Inc.
*
* 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.as.arquillian.container;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ContainerRegistry;
import org.jboss.arquillian.container.spi.context.ContainerContext;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestEnricher;
import org.jboss.as.arquillian.api.ContainerResource;
/**
* Test enricher that allows for injection of remote JNDI context into @RunAsClient test cases.
*
* @author Stuart Douglas
*/
public class ContainerResourceTestEnricher implements TestEnricher {
@Inject
private Instance containerRegistry;
@Inject
private Instance containerContext;
@Inject
private Instance managementClient;
/* (non-Javadoc)
* @see org.jboss.arquillian.spi.TestEnricher#enrich(java.lang.Object)
*/
public void enrich(Object testCase) {
for (Field field : SecurityActions.getFieldsWithAnnotation(testCase.getClass(), ContainerResource.class)) {
Object value = null;
try {
Annotation[] qualifiers = filterAnnotations(field.getAnnotations());
// null value will throw exception in lookup
value = lookup(field.getType(), field.getAnnotation(ContainerResource.class), qualifiers);
} catch (Exception e) {
throw new RuntimeException("Could not lookup value for field " + field, e);
}
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(testCase, value);
} catch (Exception e) {
throw new RuntimeException("Could not set value on field " + field + " using " + value);
}
}
}
/* (non-Javadoc)
* @see org.jboss.arquillian.spi.TestEnricher#resolve(java.lang.reflect.Method)
*/
public Object[] resolve(Method method) {
Object[] values = new Object[method.getParameterTypes().length];
Class>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ContainerResource resource = getResourceAnnotation(method.getParameterAnnotations()[i]);
if (resource != null) {
Annotation[] qualifiers = filterAnnotations(method.getParameterAnnotations()[i]);
values[i] = lookup(method.getParameterTypes()[i], resource, qualifiers);
}
}
return values;
}
/**
* @param type
* @param resource
* @return
* @throws IllegalArgumentException If no ResourceProvider found for Type
* @throws RuntimeException If ResourceProvider return null
*/
private Object lookup(Class> type, ContainerResource resource, Annotation... qualifiers) {
final Container container;
final List containers = containerRegistry.get().getContainers();
if (resource.value().isEmpty()) {
if (containers.size() > 1) {
throw new RuntimeException("@ContainerResource did not specify a server and more than one server exists in the deployment");
}
container = containers.get(0);
} else {
container = containerRegistry.get().getContainer(resource.value());
if (container == null) {
throw new RuntimeException("@ContainerResource specified non existent server " + resource.value());
}
}
try {
containerContext.get().activate(container.getName());
if (Context.class.isAssignableFrom(type)) {
return lookupContext(type, resource, qualifiers);
} else if (ManagementClient.class.isAssignableFrom(type)) {
return managementClient.get();
} else {
throw new RuntimeException("@ContainerResource an unknown type " + resource.value());
}
} finally {
containerContext.get().deactivate();
}
}
/**
* @param type
* @param resource
* @return
* @throws IllegalArgumentException If no ResourceProvider found for Type
* @throws RuntimeException If ResourceProvider return null
*/
private Object lookupContext(Class> type, ContainerResource resource, Annotation... qualifiers) {
try {
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, managementClient.get().getRemoteEjbURL().toString());
env.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
env.put("jboss.naming.client.security.callback.handler.class", Authentication.CallbackHandler.class.getName());
return new InitialContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
private ContainerResource getResourceAnnotation(Annotation[] annotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType() == ContainerResource.class) {
return (ContainerResource) annotation;
}
}
return null;
}
/**
* @param annotations
* @return
*/
private Annotation[] filterAnnotations(Annotation[] annotations) {
if (annotations == null) {
return new Annotation[0];
}
List filtered = new ArrayList();
for (Annotation annotation : annotations) {
if (annotation.annotationType() != ContainerResource.class) {
filtered.add(annotation);
}
}
return filtered.toArray(new Annotation[0]);
}
private interface ContainerResourceProvider {
Object lookup(Class> type, ContainerResource resource, Annotation... qualifiers);
}
}