/* * RHQ Management Platform * Copyright (C) 2005-2013 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 as published by * the Free Software Foundation version 2 of the License. * * 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 for more details. * * You should have received a copy of the GNU 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.modules.plugins.jbossas7; import java.util.HashMap; import java.util.Map; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinition; import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.modules.plugins.jbossas7.json.Operation; import org.rhq.modules.plugins.jbossas7.json.ReadResource; import org.rhq.modules.plugins.jbossas7.json.Result; /** * @author Stefan Negrea * @author Simeon Pinder * */ public class TemplatedComponent extends BaseComponent<ResourceComponent<?>> { private final static String TYPE_CONFIGURATION = "__type"; private final static String NAME_CONFIGURATION = "__name"; @Override public Configuration loadResourceConfiguration() throws Exception { ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition(); if (configDef.getDefaultTemplate().getConfiguration().get(TYPE_CONFIGURATION) != null) { //__type is a fake property, do not attempt to load it from the managed server configDef.getPropertyDefinitions().remove(TYPE_CONFIGURATION); ConfigurationLoadDelegate delegate = new ConfigurationLoadDelegate(configDef, getASConnection(), address); Configuration configuration = delegate.loadResourceConfiguration(); //manually load type based on the resource path PropertySimple pathProperty = (PropertySimple) context.getPluginConfiguration().get("path"); String type = pathProperty.getStringValue(); type = type.substring(type.lastIndexOf(',') + 1, type.lastIndexOf('=')); configuration.put(new PropertySimple(TYPE_CONFIGURATION, type)); return configuration; } else if (configDef.getDefaultTemplate().getConfiguration().get(NAME_CONFIGURATION) != null) { //__name is a fake property, do not attempt to load it from the managed server configDef.getPropertyDefinitions().remove(NAME_CONFIGURATION); ConfigurationLoadDelegate delegate = new ConfigurationLoadDelegate(configDef, getASConnection(), address); Configuration configuration = delegate.loadResourceConfiguration(); //manually load name based on the resource path PropertySimple pathProperty = (PropertySimple) context.getPluginConfiguration().get("path"); String name = pathProperty.getStringValue(); name = name.substring(name.lastIndexOf('=') + 1); configuration.put(new PropertySimple(NAME_CONFIGURATION, name)); return configuration; } return super.loadResourceConfiguration(); } @Override public void updateResourceConfiguration(ConfigurationUpdateReport report) { ConfigurationDefinition configDefCopy = context.getResourceType().getResourceConfigurationDefinition().copy(); Map<String, PropertyDefinition> propDefs = configDefCopy.getPropertyDefinitions(); boolean templatedComponentUpdate = false; if (configDefCopy.getDefaultTemplate().getConfiguration().get(TYPE_CONFIGURATION) != null) { //__type is a fake property, do not attempt to save it. propDefs.remove(TYPE_CONFIGURATION); report.getConfiguration().remove(TYPE_CONFIGURATION); templatedComponentUpdate = true; } else if (configDefCopy.getDefaultTemplate().getConfiguration().get(NAME_CONFIGURATION) != null) { //__name is a fake property, do not attempt to save it. propDefs.remove(NAME_CONFIGURATION); report.getConfiguration().remove(NAME_CONFIGURATION); templatedComponentUpdate = true; } if (templatedComponentUpdate) { //For templated resources we need to parse only the specific subset of attributes //supported by this component Map<String, Object> currentAttributeList = null; Operation currentAttributesOp = new ReadResource(address); Map<String, Object> additionalProperties = new HashMap<String, Object>(); //includes operation request attributes applicable to 6.0 & 6.1 additionalProperties.put("proxies", "true"); additionalProperties.put("include-runtime", "true"); additionalProperties.put("include-defaults", "true"); additionalProperties.put("attributes-only", "true"); currentAttributesOp.setAdditionalProperties(additionalProperties); Result currentAttributes = getASConnection().execute(currentAttributesOp); if (currentAttributes.isSuccess()) { currentAttributeList = (Map<String, Object>) currentAttributes.getResult(); } for (PropertyDefinition propDef : configDefCopy.getNonGroupedProperties()) { //with templated resources we should only parse the properties being used by this specific resource. if (currentAttributeList != null) { //take care to strip off as7 plugin specific identifiers here when comparing attributes. String name = removeAttributeMarkup(propDef.getName()); if (!currentAttributeList.containsKey(name)) { propDefs.remove(propDef.getName()); report.getConfiguration().remove(propDef.getName()); } else { // BZ 1033404, because EAP sometimes has issues setting an attribute undefined (i.e. null), // don't reset to null if it's already undefined. Object current = currentAttributeList.get(name); Property update = report.getConfiguration().getAllProperties().get(propDef.getName()); if ((null == current && isUndefined(update))) { propDefs.remove(propDef.getName()); report.getConfiguration().remove(propDef.getName()); } } } } } ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDefCopy, getASConnection(), address); delegate.updateResourceConfiguration(report); } // use to optimize config update by omitting props where new and current are both "undefined" private boolean isUndefined(Property property) { if (null == property) { return true; } if (property instanceof PropertySimple) { return ((PropertySimple) property).getStringValue() == null; } else if (property instanceof PropertyMap) { for (Property p : ((PropertyMap) property).getMap().values()) { if (!isUndefined(p)) { return false; } } return true; } // not sure what to do about lists, just return them, this whole thing is a "best-effort" optimization return false; } /** Method removes attribute metadata mark up so that the attributes can be * compared directly to results from stock as7/eap resources. * Ex. queue-length:expr -> queue-length. * * @param name : string to scrub metadata from. * @return String minus known metadata markup. */ private String removeAttributeMarkup(String name) { int index = -1; //Ex. Markup :pname,:key,:name,:expr,:collapsed,:nullable,:# .. where # represent [0-9] if ((index = name.indexOf(":")) > -1) { name = name.substring(0, index); } return name; } }