package org.rhq.test.arquillian.impl; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Set; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.test.spi.annotation.TestScoped; import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager; import org.rhq.core.clientapi.agent.metadata.ResourceTypeNotEnabledException; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.inventory.InventoryManager; import org.rhq.core.pc.inventory.ResourceContainer; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.test.arquillian.DiscoveredResources; import org.rhq.test.arquillian.ResourceComponentInstances; import org.rhq.test.arquillian.ResourceContainers; import org.rhq.test.arquillian.spi.PostPrepareEnricher; public class DiscoveryResultsTestEnricher implements PostPrepareEnricher { @Inject @TestScoped private Instance<PluginContainer> pluginContainer; @Override public void enrich(Object testCase) { Set<Field> discoveredResourceFields = new HashSet<Field>(); Set<Field> resourceComponentFields = new HashSet<Field>(); Set<Field> resourceContainerFields = new HashSet<Field>(); for (Field f : testCase.getClass().getDeclaredFields()) { collectDiscoveredResourceFields(f, discoveredResourceFields); collectResourceComponentFields(f, resourceComponentFields); collectResourceContainerFields(f, resourceContainerFields); } for(Field f : discoveredResourceFields) { assignDiscoveredResourceField(testCase, f); } for(Field f : resourceComponentFields) { assignResourceComponentField(testCase, f); } for(Field f : resourceContainerFields) { assignResourceContainerField(testCase, f); } } private PluginContainer getPluginContainer() { return pluginContainer.get(); } private void collectDiscoveredResourceFields(Field f, Set<Field> fields) { DiscoveredResources a = f.getAnnotation(DiscoveredResources.class); if (a != null && hasType(f, Set.class, Resource.class)) { fields.add(f); } } private void collectResourceComponentFields(Field f, Set<Field> fields) { ResourceComponentInstances a = f.getAnnotation(ResourceComponentInstances.class); if (a != null) { ResourceType rt = getResourceType(a.plugin(), a.resourceType()); Class<?> resourceComponentClass = getResourceComponentClass(rt); if (hasType(f, Set.class, resourceComponentClass)) { fields.add(f); } } } private void collectResourceContainerFields(Field f, Set<Field> fields) { ResourceContainers a = f.getAnnotation(ResourceContainers.class); if (a != null && hasType(f, Set.class, ResourceContainer.class)) { fields.add(f); } } private void assignDiscoveredResourceField(Object testCase, Field f) { DiscoveredResources config = f.getAnnotation(DiscoveredResources.class); String pluginName = config.plugin(); String resourceTypeName = config.resourceType(); ResourceType resourceType = getPluginContainer().getPluginManager().getMetadataManager().getType(resourceTypeName, pluginName); if (resourceType == null) { return; } Set<Resource> resources = getPluginContainer().getInventoryManager().getResourcesWithType(resourceType); f.setAccessible(true); try { f.set(testCase, resources); } catch (IllegalArgumentException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } catch (IllegalAccessException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } } private void assignResourceComponentField(Object testCase, Field f) { ResourceComponentInstances config = f.getAnnotation(ResourceComponentInstances.class); String pluginName = config.plugin(); String resourceTypeName = config.resourceType(); ResourceType resourceType = getResourceType(pluginName, resourceTypeName); Class<?> componentClass = getResourceComponentClass(resourceType); if (hasType(f, Set.class, componentClass)) { InventoryManager im = getPluginContainer().getInventoryManager(); Set<Resource> resources = im.getResourcesWithType(resourceType); Set<ResourceComponent<?>> components = new HashSet<ResourceComponent<?>>(resources.size()); for(Resource r : resources) { components.add(im.getResourceComponent(r)); } f.setAccessible(true); try { f.set(testCase, components); } catch (IllegalArgumentException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } catch (IllegalAccessException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } } } private void assignResourceContainerField(Object testCase, Field f) { ResourceContainers config = f.getAnnotation(ResourceContainers.class); String pluginName = config.plugin(); String resourceTypeName = config.resourceType(); ResourceType resourceType = getPluginContainer().getPluginManager().getMetadataManager().getType(resourceTypeName, pluginName); if (resourceType == null) { return; } Set<Resource> resources = getPluginContainer().getInventoryManager().getResourcesWithType(resourceType); Set<ResourceContainer> containers = new HashSet<ResourceContainer>(); for(Resource r : resources) { containers.add(getPluginContainer().getInventoryManager().getResourceContainer(r)); } f.setAccessible(true); try { f.set(testCase, containers); } catch (IllegalArgumentException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } catch (IllegalAccessException e) { throw new IllegalStateException( "Could not enrich the test class with the discovered resources on field " + f, e); } } private ResourceType getResourceType(String pluginName, String resourceTypeName) { PluginMetadataManager pmm = getPluginContainer().getPluginManager().getMetadataManager(); ResourceType resourceType = pmm.getType(resourceTypeName, pluginName); if (resourceType == null) { throw new IllegalArgumentException("No resource type called '" + resourceTypeName + "' found in plugin '" + pluginName + "'."); } return resourceType; } private Class<?> getResourceComponentClass(ResourceType resourceType) { PluginMetadataManager pmm = getPluginContainer().getPluginManager().getMetadataManager(); String componentClassName; try { componentClassName = pmm.getComponentClass(resourceType); } catch (ResourceTypeNotEnabledException rtne) { throw new RuntimeException(rtne); } try { return Class.forName(componentClassName); } catch (ClassNotFoundException e) { throw new IllegalStateException("Could not find the component class " + componentClassName, e); } } private static boolean hasType(Field f, Class<?> type, Class<?>... typeParams) { Type fieldType = f.getGenericType(); if (typeParams.length == 0) { return type.equals(fieldType); } if (!(fieldType instanceof ParameterizedType)) { return false; } ParameterizedType ptype = (ParameterizedType) fieldType; Type rawType = ptype.getRawType(); Type[] params = ptype.getActualTypeArguments(); if (!rawType.equals(type)) { return false; } if (params.length != typeParams.length) { return false; } for(int i = 0; i < params.length; ++i) { Type fieldTypeParam = params[i]; Class<?> expectedTypeParam = typeParams[i]; if (!fieldTypeParam.equals(expectedTypeParam)) { return false; } else if (fieldTypeParam instanceof Class) { if (!((Class<?>)fieldTypeParam).isAssignableFrom(expectedTypeParam)) { return false; } } } return true; } }