/* * RHQ Management Platform * Copyright (C) 2005-2014 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.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; /** * Discover domain deployments. This is analogous to {@link VersionedSubsystemDiscovery} but addresses only * domain deployments. See {@link VersionedSubsystemDiscovery} for more on controlling/overriding the version handling. * * @author Jay Shaughnessy */ public class VersionedDomainDeploymentDiscovery extends AbstractVersionedDomainDeploymentDiscovery implements ResourceUpgradeFacet { private static final Log LOG = LogFactory.getLog(VersionedDomainDeploymentDiscovery.class); private static final Pattern COMMA_PATTERN = Pattern.compile(","); @Override public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<BaseComponent<?>> context) throws Exception { // Perform the standard discovery. This can return deployments with versions in the name, // key and path. Set<DiscoveredResourceDetails> details = super.discoverResources(context); if (DISABLED || null == details || details.isEmpty()) { return details; } // Now, post-process the discovery as needed. We need to strip the versions from the // resource name and the resource key. We want to leave them in the path plugin config // property, that value reflects the actual DMR used to query EAP. // The stripped versions are then used to set the resource version string. // Work with a list because we may update the key, which is used in the DiscoveredResourceDetails.equals() ArrayList<DiscoveredResourceDetails> updatedDetails = new ArrayList<DiscoveredResourceDetails>(details); HashMap<String, Integer> keyCount = new HashMap<String, Integer>(updatedDetails.size()); details.clear(); // domain deployments are not actually deployed, they are basically just staged for deployment, so // they are fairly simple, they don't have subdeployments, etc... for (DiscoveredResourceDetails detail : updatedDetails) { MATCHER.reset(detail.getResourceName()); if (MATCHER.matches()) { // reset the resource name with the stripped value detail.setResourceName(MATCHER.group(1) + MATCHER.group(3)); detail.setResourceVersion(MATCHER.group(2)); } StringBuilder sb = new StringBuilder(); String comma = ""; for (String segment : COMMA_PATTERN.split(detail.getResourceKey())) { sb.append(comma); comma = ","; MATCHER.reset(segment); if (MATCHER.matches()) { sb.append(MATCHER.group(1)).append(MATCHER.group(3)); } else { sb.append(segment); } } detail.setResourceKey(sb.toString()); Integer count = keyCount.get(detail.getResourceKey()); keyCount.put(detail.getResourceKey(), (null == count ? 1 : ++count)); } // Now, make sure that after we've stripped the versions that we don't end up with multiple discoveries // for the same key, this is an indication that there are multiple versions of the same Deployment deployed. // In this case we remove the duplicates and issue a warning so the user can hopefully rectify the situation. for (Map.Entry<String, Integer> entry : keyCount.entrySet()) { if (entry.getValue() > 1) { LOG.warn("Discovered multiple resources with resource key [" + entry.getKey() + "]. This is not allowed and they will be removed from discovery. This is typically caused by " + "having multiple versions of the same Deployment deployed. To solve the problem either remove " + "all but one version of the problem deployment or disable versioned deployment handling by " + "setting -Drhq.as7.VersionedSubsystemDiscovery.pattern=disable for the agent."); for (Iterator<DiscoveredResourceDetails> i = updatedDetails.iterator(); i.hasNext();) { DiscoveredResourceDetails detail = i.next(); if (detail.getResourceKey().equals(entry.getKey())) { i.remove(); } } } } details.addAll(updatedDetails); return details; } // The Matching logic here is the same as above, but instead of setting the discovery details we // set new values in the upgrade report for name, version and key. Note that if multiple resources // upgrade to the same resource key it will be caught and fail downstream. @Override public ResourceUpgradeReport upgrade(ResourceUpgradeContext inventoriedResource) { ResourceUpgradeReport result = null; if (DISABLED) { return result; } MATCHER.reset(inventoriedResource.getName()); if (MATCHER.matches()) { result = new ResourceUpgradeReport(); result.setForceGenericPropertyUpgrade(true); // It is critical the name and version get upgraded // reset the resource name with the stripped value result.setNewName(MATCHER.group(1) + MATCHER.group(3)); result.setNewVersion(MATCHER.group(2)); } StringBuilder sb = new StringBuilder(); String comma = ""; boolean upgradeKey = false; for (String segment : COMMA_PATTERN.split(inventoriedResource.getResourceKey())) { sb.append(comma); comma = ","; MATCHER.reset(segment); if (MATCHER.matches()) { upgradeKey = true; sb.append(MATCHER.group(1)).append(MATCHER.group(3)); } else { sb.append(segment); } } if (upgradeKey) { if (null == result) { result = new ResourceUpgradeReport(); } result.setNewResourceKey(sb.toString()); } if (null != result && LOG.isDebugEnabled()) { LOG.debug("Requesting upgrade: " + result); } return result; } }