/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.core.clientapi.agent.metadata.test; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.bind.util.ValidationEventCollector; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager; import org.rhq.core.clientapi.descriptor.DescriptorPackages; import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.ConfigurationTemplate; import org.rhq.core.domain.configuration.definition.PropertyDefinitionList; import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple; import org.rhq.core.domain.configuration.definition.PropertySimpleType; import org.rhq.core.domain.configuration.definition.constraint.RegexConstraint; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceType; /** * Test the management and loading of Agent plugin metadata. * * @author Greg Hinkle */ public class MetadataManagerTest { private static final String DESCRIPTOR_FILENAME_TEST1 = "metadata-manager-test-1.xml"; private static final String DESCRIPTOR_FILENAME_TEST2 = "metadata-manager-test-2.xml"; private static final String DESCRIPTOR_FILENAME_TEST3 = "metadata-manager-test-3.xml"; private PluginMetadataManager metadataManager; @BeforeClass public void beforeClass() { try { this.metadataManager = new PluginMetadataManager(); } catch (Throwable t) { // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)! t.printStackTrace(); throw new RuntimeException(t); } } @Test public void loadPluginDescriptorTest1() throws Exception { PluginDescriptor pluginDescriptor; URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST1); System.out.println("Loading plugin descriptor at: " + descriptorUrl); JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ValidationEventCollector vec = new ValidationEventCollector(); unmarshaller.setEventHandler(vec); pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream()); this.metadataManager.loadPlugin(pluginDescriptor); System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 1"); outputTypes(); } @Test(dependsOnMethods = "loadPluginDescriptorTest1") public void testDefinitionParsing1() { ResourceType serverAType = this.metadataManager.getType("Server A", "Test1"); assert serverAType.getName().equals("Server A"); assert serverAType.getPlugin().equals("Test1"); assertServerTypeIsOK(serverAType); } @Test(dependsOnMethods = "loadPluginDescriptorTest1") public void loadPluginDescriptorTest2() throws Exception { PluginDescriptor pluginDescriptor; URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST2); System.out.println("Loading plugin descriptor at: " + descriptorUrl); JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ValidationEventCollector vec = new ValidationEventCollector(); unmarshaller.setEventHandler(vec); pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream()); this.metadataManager.loadPlugin(pluginDescriptor); System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 2"); outputTypes(); } @Test(dependsOnMethods = "loadPluginDescriptorTest2") public void testDefinitionParsing2() { ResourceType serverBType = this.metadataManager.getType("Extension Server B", "Test2"); assert serverBType.getName().equals("Extension Server B"); assert serverBType.getPlugin().equals("Test2"); assertServerTypeIsOK(serverBType); } @Test(dependsOnMethods = "loadPluginDescriptorTest2") public void loadPluginDescriptorTest3() throws Exception { PluginDescriptor pluginDescriptor; URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST3); System.out.println("Loading plugin descriptor at: " + descriptorUrl); JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ValidationEventCollector vec = new ValidationEventCollector(); unmarshaller.setEventHandler(vec); pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream()); this.metadataManager.loadPlugin(pluginDescriptor); System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 3"); outputTypes(); ResourceType parentA = getResourceType(new ResourceType("Server A", "Test1", ResourceCategory.SERVER, null)); ResourceType parentB = getResourceType(new ResourceType("Extension Server B", "Test2", ResourceCategory.SERVER, null)); assert parentA != null; assert parentB != null; ResourceType testC = getResourceType(new ResourceType("Injection C To Server A", "Test3", ResourceCategory.SERVER, null)); assert testC != null; assert parentA.getChildResourceTypes().contains(testC); assert parentB.getChildResourceTypes().contains(testC); // shows that a type can have more than one parent ResourceType testD = getResourceType(new ResourceType("Injection D To Server A", "Test3", ResourceCategory.SERVICE, null)); assert testD != null; assert parentA.getChildResourceTypes().contains(testD); assert !parentB.getChildResourceTypes().contains(testD); // now check the many-to-many relationship - child can have more than one parent assert testC.getParentResourceTypes().contains(parentA); assert testC.getParentResourceTypes().contains(parentB); assert testD.getParentResourceTypes().contains(parentA); assert !testD.getParentResourceTypes().contains(parentB); // ensure the bundle metadata is correct assert testD.getBundleType() != null : "missing the bundle for 'Injection D To Server A'"; assert testD.getBundleType().getName().equals("test-bundle-name"); assert testD.getBundleType().getResourceType().equals(testD); } @Test(dependsOnMethods = "loadPluginDescriptorTest3") public void testDiscoveryCallbackDefinitions() { ResourceType serverAType = this.metadataManager.getType("Server A", "Test1"); ResourceType serverBType = this.metadataManager.getType("Extension Server B", "Test2"); assert serverAType != null : "Where's Server A?"; assert serverBType != null : "Where's Extension Server B?"; Map<String, List<String>> serverACallbacks = this.metadataManager.getDiscoveryCallbacks(serverAType); assert serverACallbacks.size() == 1 : serverACallbacks; assert serverACallbacks.get("Test3").size() == 2 : serverACallbacks; assert serverACallbacks.get("Test3").get(0).equals("org.rhq.plugins.test3.DiscoveryCallback1") : serverACallbacks; assert serverACallbacks.get("Test3").get(1).equals("org.rhq.plugins.test3.DiscoveryCallbackAnother1") : serverACallbacks; Map<String, List<String>> serverBCallbacks = this.metadataManager.getDiscoveryCallbacks(serverBType); assert serverBCallbacks.size() == 2 : serverBCallbacks; assert serverBCallbacks.get("Test3").size() == 1 : serverBCallbacks; assert serverBCallbacks.get("Test2").size() == 1 : serverBCallbacks; assert serverBCallbacks.get("Test3").get(0).equals("org.rhq.plugins.test3.DiscoveryCallback2") : serverBCallbacks; assert serverBCallbacks.get("Test2").get(0).equals("org.rhq.plugins.test2.DiscoveryCallbackTest2") : serverBCallbacks; } private ResourceType getResourceType(ResourceType typeToGet) { for (ResourceType type : metadataManager.getAllTypes()) { if (type.equals(typeToGet)) { return type; } } return null; } /** * @param serverType */ private void assertServerTypeIsOK(ResourceType serverType) { assert serverType != null : "Expected type not found"; ConfigurationDefinition def = serverType.getPluginConfigurationDefinition(); PropertyDefinitionSimple alpha = def.getPropertyDefinitionSimple("alpha"); assert alpha.getType() == PropertySimpleType.STRING; assert alpha.isRequired(); assert alpha.getConstraints().size() == 1; RegexConstraint regexConstraint = (RegexConstraint) alpha.getConstraints().iterator().next(); assert regexConstraint.getDetails().equals("^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$"); PropertyDefinitionSimple bravo = def.getPropertyDefinitionSimple("bravo"); assert bravo.getType() == PropertySimpleType.STRING; assert bravo.getEnumeratedValues().size() == 4; assert bravo.getEnumeratedValues().get(0).getName().equals("First Option Name"); assert bravo.getEnumeratedValues().get(0).getValue().equals("FirstOptionValue"); assert bravo.getEnumeratedValues().get(0).getValue().equals( def.getDefaultTemplate().getConfiguration().getSimpleValue("bravo", null)); assert def.getPropertyDefinitionSimple("charlie").getType() == PropertySimpleType.BOOLEAN; assert def.getPropertyDefinitionSimple("delta").getType() == PropertySimpleType.INTEGER; assert def.getPropertyDefinitionSimple("deltalong").getType() == PropertySimpleType.LONG; assert def.getPropertyDefinitionSimple("echo").getType() == PropertySimpleType.PASSWORD; assert def.getPropertyDefinitionSimple("foxtrot").getType() == PropertySimpleType.FLOAT; assert def.getPropertyDefinitionSimple("foxtrotdouble").getType() == PropertySimpleType.DOUBLE; assert def.getPropertyDefinitionSimple("golf").getType() == PropertySimpleType.DIRECTORY; assert def.getPropertyDefinitionSimple("hotel").getType() == PropertySimpleType.FILE; assert def.getPropertyDefinitionSimple("india").getType() == PropertySimpleType.LONG_STRING; PropertyDefinitionList juliet = def.getPropertyDefinitionList("juliet"); assert juliet.getMin() == 3; assert juliet.getMax() == 4; PropertyDefinitionSimple foo = (PropertyDefinitionSimple) juliet.getMemberDefinition(); assert foo != null; assert foo.getName().equals("foo"); assert foo.getType() == PropertySimpleType.STRING; // This is an arbitrary entry map assert def.getPropertyDefinitionMap("kilo").getMap().size() == 0; assert def.getPropertyDefinitionMap("kilo").getName().equals("kilo"); PropertyDefinitionSimple mapEmbeddedSimpleDef = (PropertyDefinitionSimple) def.getPropertyDefinitionMap("lima") .getMap().get("file"); assert mapEmbeddedSimpleDef != null; assert mapEmbeddedSimpleDef.getType() == PropertySimpleType.FILE; assert def.getPropertyDefinitionList("mike").getMin() == 0; assert def.getPropertyDefinitionList("mike").getMax() == Integer.MAX_VALUE; Map<String, ConfigurationTemplate> templates = def.getTemplates(); ConfigurationTemplate t = templates.get("First Template"); assert !t.isDefault(); assert t.getConfiguration().getSimple("alpha").getStringValue().equals("template1:alpha value"); assert t.getConfiguration().getSimple("charlie").getBooleanValue(); assert t.getConfiguration().getSimple("delta").getIntegerValue() == 42; assert serverType.getBundleType() == null : "bundle should not be defined for type: " + serverType; // ensure the bundle target metadata is correct ResourceTypeBundleConfiguration bundleTargetConfig = serverType.getResourceTypeBundleConfiguration(); assert bundleTargetConfig != null; Set<ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory> set = bundleTargetConfig .getBundleDestinationBaseDirectories(); assert set.size() == 2; for (BundleDestinationBaseDirectory bdbd : set) { if (bdbd.getName().equals("basedir1")) { assert bdbd.getValueContext() == Context.pluginConfiguration : bdbd; assert bdbd.getValueName().equals("alpha") : bdbd; } else if (bdbd.getName().equals("basedir2")) { assert bdbd.getValueContext() == Context.resourceConfiguration : bdbd; assert bdbd.getValueName().equals("resourceAlpha") : bdbd; } else { assert false : "Bad bundle target name: " + bdbd; } } } private void outputTypes() { Set<ResourceType> allTypes = metadataManager.getRootTypes(); for (ResourceType type : allTypes) { outputType(type, 0); } System.out.flush(); } private void outputType(ResourceType type, int depth) { StringBuilder line = new StringBuilder(); for (int i = 0; i < depth; i++) { line.append(" "); } line.append("+ "); line.append(type.toString()); System.out.println(line.toString()); for (ResourceType child : type.getChildResourceTypes()) { outputType(child, depth + 1); } } }