package org.arquillian.cube.impl.client.container; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import java.util.regex.Pattern; import org.arquillian.cube.impl.util.ContainerUtil; import org.arquillian.cube.spi.Cube; import org.arquillian.cube.spi.CubeRegistry; import org.arquillian.cube.spi.metadata.HasPortBindings; import org.arquillian.cube.spi.metadata.HasPortBindings.PortAddress; import org.jboss.arquillian.config.descriptor.api.ContainerDef; import org.jboss.arquillian.container.spi.Container; import org.jboss.arquillian.container.spi.ContainerRegistry; import org.jboss.arquillian.container.spi.event.container.BeforeSetup; import org.jboss.arquillian.core.api.annotation.Observes; public class ContainerConfigurationController { private static final Pattern portPattern = Pattern.compile("(?i:.*port.*)"); //private static final Pattern hostPattern = Pattern.compile("(?i:.*host.*)"); private static final Pattern addressPattern = Pattern.compile("(?i:.*address.*)"); private PortAddress mappingForPort = null; //private static final Pattern jmxPattern = Pattern.compile("(?i:.*jmx.*)"); public void remapContainer(@Observes BeforeSetup event, CubeRegistry cubeRegistry, ContainerRegistry containerRegistry) throws InstantiationException, IllegalAccessException { Container container = ContainerUtil.getContainerByDeployableContainer(containerRegistry, event.getDeployableContainer()); if (container == null) { return; } Cube<?> cube = cubeRegistry.getCube(ContainerUtil.getCubeIDForContainer(container)); if (cube == null) { return; // No Cube found matching Container name, not managed by Cube } HasPortBindings bindings = cube.getMetadata(HasPortBindings.class); if (bindings == null) { return; } ContainerDef containerConfiguration = container.getContainerConfiguration(); //Get the port property List<String> portPropertiesFromArquillianConfigurationFile = filterArquillianConfigurationPropertiesByPortAttribute(containerConfiguration); //Get the AddressProperty property List<String> addressPropertiesFromArquillianConfigurationFile = filterArquillianConfigurationPropertiesByAddressAttribute(containerConfiguration); Class<?> configurationClass = container.getDeployableContainer().getConfigurationClass(); //Get the port property List<PropertyDescriptor> configurationClassPortFields = filterConfigurationClassPropertiesByPortAttribute(configurationClass); //Get the Address property List<PropertyDescriptor> configurationClassAddressFields = filterConfigurationClassPropertiesByAddressAttribute(configurationClass); Object newConfigurationInstance = configurationClass.newInstance(); for (PropertyDescriptor configurationClassPortField : configurationClassPortFields) { int containerPort = getDefaultPortFromConfigurationInstance(newConfigurationInstance, configurationClass, configurationClassPortField); mappingForPort = bindings.getMappedAddress(containerPort); if (!portPropertiesFromArquillianConfigurationFile.contains(configurationClassPortField.getName()) && ( configurationClassPortField.getPropertyType().equals(Integer.class) || configurationClassPortField.getPropertyType().equals(int.class))) { // This means that port has not configured in arquillian.xml and it will use default value. // In this case is when remapping should be activated to adequate the situation according to // Arquillian Cube exposed ports. if (mappingForPort != null) { containerConfiguration.overrideProperty(configurationClassPortField.getName(), Integer.toString(mappingForPort.getPort())); } } } for (PropertyDescriptor configurationClassAddressField : configurationClassAddressFields) { if (!addressPropertiesFromArquillianConfigurationFile.contains(configurationClassAddressField.getName()) && ( configurationClassAddressField.getPropertyType().equals(String.class) || configurationClassAddressField.getPropertyType().equals(String.class))) { // If a property called portForwardBindAddress on openshift qualifier on arquillian.xml exists it will overrides the // arquillian default|defined managementAddress with the IP address given on this property. if (mappingForPort != null) { containerConfiguration.overrideProperty(configurationClassAddressField.getName(), mappingForPort.getIP()); } } } } private int getDefaultPortFromConfigurationInstance(Object configurationInstance, Class<?> configurationClass, PropertyDescriptor fieldName) { try { Method method = fieldName.getReadMethod(); return (int) method.invoke(configurationInstance); } catch (SecurityException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e); } catch (InvocationTargetException e) { throw new IllegalArgumentException(e); } } private List<String> filterArquillianConfigurationPropertiesByPortAttribute(ContainerDef containerDef) { List<String> fields = new ArrayList<String>(); for (Entry<String, String> entry : containerDef.getContainerProperties().entrySet()) { if (portPattern.matcher(entry.getKey()).matches()) { fields.add(entry.getKey()); } } return fields; } private List<String> filterArquillianConfigurationPropertiesByAddressAttribute(ContainerDef containerDef) { List<String> fields = new ArrayList<String>(); for (Entry<String, String> entry : containerDef.getContainerProperties().entrySet()) { if (addressPattern.matcher(entry.getKey()).matches()) { fields.add(entry.getKey()); } } return fields; } private List<PropertyDescriptor> filterConfigurationClassPropertiesByPortAttribute(Class<?> configurationClass) { List<PropertyDescriptor> fields = new ArrayList<PropertyDescriptor>(); try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(configurationClass, Object.class) .getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String propertyName = propertyDescriptor.getName(); if (portPattern.matcher(propertyName).matches()) { if (int.class.equals(propertyDescriptor.getPropertyType()) || Integer.class.equals( propertyDescriptor.getPropertyType())) { fields.add(propertyDescriptor); } } } } catch (IntrospectionException e) { throw new IllegalArgumentException(e); } return fields; } private List<PropertyDescriptor> filterConfigurationClassPropertiesByAddressAttribute(Class<?> configurationClass) { List<PropertyDescriptor> fields = new ArrayList<PropertyDescriptor>(); try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(configurationClass, Object.class) .getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String propertyName = propertyDescriptor.getName(); if (addressPattern.matcher(propertyName).matches()) { fields.add(propertyDescriptor); } } } catch (IntrospectionException e) { throw new IllegalArgumentException(e); } return fields; } }