/*
* 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, 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.plugins.jbossas5;
import static org.rhq.plugins.jbossas5.AbstractManagedDeploymentComponent.DEPLOYMENT_KEY_PROPERTY;
import static org.rhq.plugins.jbossas5.AbstractManagedDeploymentComponent.DEPLOYMENT_NAME_PROPERTY;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.deployers.spi.management.KnownDeploymentTypes;
import org.jboss.deployers.spi.management.ManagementView;
import org.jboss.managed.api.ManagedDeployment;
import org.jboss.profileservice.spi.NoSuchDeploymentException;
import org.jboss.profileservice.spi.ProfileKey;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.ResourceUpgradeReport;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext;
import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet;
import org.rhq.plugins.jbossas5.connection.ProfileServiceConnection;
import org.rhq.plugins.jbossas5.util.ConversionUtils;
/**
* Discovery component for discovering JBAS 5.x/6.x deployments (EARs, WARs, EJB-JARs, etc.).
*
* @author Mark Spritzler
* @author Ian Springer
*/
public abstract class AbstractManagedDeploymentDiscoveryComponent implements
ResourceDiscoveryComponent<ProfileServiceComponent<?>>, ResourceUpgradeFacet<ProfileServiceComponent<?>> {
private static final Log LOG = LogFactory.getLog(AbstractManagedDeploymentDiscoveryComponent.class);
@Override
public Set<DiscoveredResourceDetails> discoverResources(
ResourceDiscoveryContext<ProfileServiceComponent<?>> discoveryContext) {
ResourceType resourceType = discoveryContext.getResourceType();
if (LOG.isTraceEnabled()) {
LOG.trace("Discovering " + resourceType.getName() + " Resources...");
}
ProfileServiceComponent<?> parentResourceComponent = discoveryContext.getParentResourceComponent();
ManagementView managementView = getManagementView(parentResourceComponent.getConnection());
if (managementView == null) {
return Collections.emptySet();
}
Set<String> deploymentNames = getDeploymentNamesForType(managementView, resourceType);
if (deploymentNames.isEmpty()) {
return Collections.emptySet();
}
Set<DiscoveredResourceDetails> discoveredResources = new HashSet<DiscoveredResourceDetails>(
deploymentNames.size());
// Create a resource details for each managed deployment found.
for (String deploymentName : deploymentNames) {
// example of deploymentName: vfszip:/C:/opt/jboss-6.0.0.Final/server/default/deploy/http-invoker.sar/invoker.war/
try {
ManagedDeployment managedDeployment = managementView.getDeployment(deploymentName);
if (!accept(managedDeployment)) {
continue;
}
String resourceName = managedDeployment.getSimpleName();
if (resourceName.equals("%Generated%")) {
resourceName = deploymentName.substring(deploymentName.lastIndexOf("/") + 1);
}
// example of a resource key: {default}http-invoker.sar/invoker.war
String resourceKey = buildResourceKey(managedDeployment);
DiscoveredResourceDetails resource = new DiscoveredResourceDetails(resourceType, resourceKey,
resourceName, null, resourceType.getDescription(),
discoveryContext.getDefaultPluginConfiguration(), null);
String deploymentKey = URI.create(deploymentName).getPath();
resource.getPluginConfiguration().put(new PropertySimple(DEPLOYMENT_KEY_PROPERTY, deploymentKey));
discoveredResources.add(resource);
} catch (NoSuchDeploymentException e) {
// This is a bug in the profile service that occurs often, so don't log the stack trace.
LOG.error("ManagementView.getDeploymentNamesForType() returned [" + deploymentName
+ "] as a deployment name, but calling getDeployment() with that name failed.");
} catch (Exception e) {
LOG.error("An error occurred while discovering " + resourceType + " resources.", e);
}
}
if (LOG.isTraceEnabled()) {
LOG.trace("Discovered " + discoveredResources.size() + " " + resourceType.getName() + " resource(s).");
}
return discoveredResources;
}
protected abstract boolean accept(ManagedDeployment managedDeployment);
@Override
public ResourceUpgradeReport upgrade(ResourceUpgradeContext<ProfileServiceComponent<?>> upgradeContext) {
// check if the inventoried resource already has the new resource key format.
// the new format is "{default}http-invoker.sar/invoker.war", while the old format
// was "vfszip:/C:/opt/jboss-6.0.0.Final/server/default/deploy/http-invoker.sar/invoker.war/".
String newResourceKey = null;
String existingResourceKey = upgradeContext.getResourceKey();
if (!existingResourceKey.startsWith("{")) {
newResourceKey = getNewResourceKey(upgradeContext, existingResourceKey);
}
Configuration newPluginConfiguration = null;
Configuration existingPluginConfig = upgradeContext.getPluginConfiguration();
if (existingPluginConfig.getSimpleValue(DEPLOYMENT_NAME_PROPERTY) != null) {
newPluginConfiguration = getNewPluginConfig(upgradeContext);
}
if (newResourceKey != null || newPluginConfiguration != null) {
ResourceUpgradeReport upgradeReport = new ResourceUpgradeReport();
upgradeReport.setNewResourceKey(newResourceKey);
upgradeReport.setNewPluginConfiguration(newPluginConfiguration);
return upgradeReport;
}
return null;
}
private String getNewResourceKey(ResourceUpgradeContext<ProfileServiceComponent<?>> upgradeContext,
String existingResourceKey) {
String newResourceKey;
ProfileServiceConnection connection = upgradeContext.getParentResourceComponent().getConnection();
if (connection == null) {
LOG.warn(getClass().getName() + ": could not upgrade resource, no profile service connection available");
return null;
}
ManagementView managementView = connection.getManagementView();
ManagedDeployment deployment;
try {
deployment = managementView.getDeployment(existingResourceKey);
} catch (NoSuchDeploymentException e) {
throw new IllegalStateException(e);
}
newResourceKey = buildResourceKey(deployment);
return newResourceKey;
}
private Configuration getNewPluginConfig(ResourceUpgradeContext<ProfileServiceComponent<?>> upgradeContext) {
Configuration newPluginConfiguration = upgradeContext.getPluginConfiguration().deepCopy(false);
String deploymentName = newPluginConfiguration.getSimpleValue(DEPLOYMENT_NAME_PROPERTY);
newPluginConfiguration.remove(DEPLOYMENT_NAME_PROPERTY);
String deploymentKey = URI.create(deploymentName).getPath();
newPluginConfiguration.put(new PropertySimple(DEPLOYMENT_KEY_PROPERTY, deploymentKey));
return newPluginConfiguration;
}
private static String buildResourceKey(ManagedDeployment deployment) {
StringBuilder resourceKey = new StringBuilder();
resourceKey.append('{').append(ProfileKey.DEFAULT).append("}");
List<String> ancestryNames = new ArrayList<String>();
ManagedDeployment parentDeployment = deployment;
do {
ancestryNames.add(0, parentDeployment.getSimpleName());
} while ((parentDeployment = parentDeployment.getParent()) != null);
for (int i = 0, ancestryNamesSize = ancestryNames.size(); i < ancestryNamesSize; i++) {
String deploymentSimpleName = ancestryNames.get(i);
resourceKey.append(deploymentSimpleName);
if (i != (ancestryNamesSize - 1)) {
resourceKey.append("/");
}
}
return resourceKey.toString();
}
static ManagementView getManagementView(ProfileServiceConnection connection) {
if (connection == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("No profile service connection available");
}
return null;
}
ManagementView managementView = connection.getManagementView();
managementView.load();
return managementView;
}
static Set<String> getDeploymentNamesForType(ManagementView managementView, ResourceType resourceType) {
KnownDeploymentTypes deploymentType = ConversionUtils.getDeploymentType(resourceType);
String deploymentTypeString = deploymentType.getType();
Set<String> deploymentNames;
try {
deploymentNames = managementView.getDeploymentNamesForType(deploymentTypeString);
} catch (Exception e) {
LOG.error("Unable to get deployment names for type " + deploymentTypeString, e);
deploymentNames = Collections.emptySet();
}
return deploymentNames;
}
}