/* * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.core.pc; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicInteger; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.clientapi.agent.metadata.PluginDependencyGraph; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.pc.inventory.InventoryManager; import org.rhq.core.pc.inventory.ResourceContainer; import org.rhq.core.pc.plugin.CanonicalResourceKey; import org.rhq.core.pc.plugin.ClassLoaderManager; import org.rhq.core.pluginapi.operation.OperationResult; /** * The management interface implementation for the {@link PluginContainer} itself. * * @author John Mazzitelli */ public class PluginContainerMBeanImpl implements PluginContainerMBeanImplMBean { private static final Log log = LogFactory.getLog(PluginContainerMBeanImpl.class); private final PluginContainer pluginContainer; public PluginContainerMBeanImpl(PluginContainer pc) { this.pluginContainer = pc; } public void register() { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); try { server.registerMBean(this, new ObjectName(OBJECT_NAME)); } catch (Exception e) { log.error("Unable to register PluginContainerMBean", e); } } public void unregister() { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); try { server.unregisterMBean(new ObjectName(OBJECT_NAME)); } catch (Exception e) { log.warn("Unable to unregister PluginContainerMBean", e); } } public String executeDiscovery(Boolean detailedDiscovery) { StringBuilder results = new StringBuilder(); InventoryReport report = this.pluginContainer.getInventoryManager().executeServerScanImmediately(); results.append(generateInventoryReportString(report)); if (detailedDiscovery != null && detailedDiscovery.booleanValue()) { report = this.pluginContainer.getInventoryManager().executeServiceScanImmediately(); results.append('\n'); results.append(generateInventoryReportString(report)); } return results.toString(); } public OperationResult retrievePluginDependencyGraph() { Map<String, List<String>> dependencies = new HashMap<String, List<String>>(); List<String> deploymentOrder; ClassLoader originalCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); ClassLoaderManager clm = this.pluginContainer.getPluginManager().getClassLoaderManager(); PluginDependencyGraph graph = clm.getPluginDependencyGraph(); deploymentOrder = graph.getDeploymentOrder(); for (String pluginName : deploymentOrder) { List<String> deps = graph.getPluginDependencies(pluginName); if (deps == null || deps.size() == 0) { deps = new ArrayList<String>(Arrays.asList("<none>")); } dependencies.put(pluginName, deps); } } finally { Thread.currentThread().setContextClassLoader(originalCL); } OperationResult info = new OperationResult(); PropertyList list = new PropertyList("plugins"); info.getComplexResults().put(list); for (String plugin : deploymentOrder) { PropertyMap map = new PropertyMap("plugin"); map.put(new PropertySimple("name", plugin)); map.put(new PropertySimple("dependencies", dependencies.get(plugin))); list.add(map); } return info; } public OperationResult retrievePluginClassLoaderInformation() { Map<String, ClassLoader> classloaders; ClassLoader originalCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); ClassLoaderManager clm = this.pluginContainer.getPluginManager().getClassLoaderManager(); classloaders = clm.getPluginClassLoaders(); } finally { Thread.currentThread().setContextClassLoader(originalCL); } OperationResult info = new OperationResult(); PropertySimple numClassLoaders = new PropertySimple("numberOfClassLoaders", String.valueOf(classloaders.size())); PropertyList list = new PropertyList("classloaders"); info.getComplexResults().put(numClassLoaders); info.getComplexResults().put(list); for (Map.Entry<String, ClassLoader> entry : classloaders.entrySet()) { String pluginName = entry.getKey(); ClassLoader classloader = entry.getValue(); PropertyMap map = new PropertyMap("classloader"); map.put(new PropertySimple("pluginName", pluginName)); map.put(new PropertySimple("classloaderInfo", classloader)); list.add(map); } return info; } public OperationResult retrieveDiscoveryClassLoaderInformation() { Map<String, ClassLoader> classloaders; ClassLoader originalCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); ClassLoaderManager clm = this.pluginContainer.getPluginManager().getClassLoaderManager(); classloaders = clm.getDiscoveryClassLoaders(); } finally { Thread.currentThread().setContextClassLoader(originalCL); } OperationResult info = new OperationResult(); PropertySimple numClassLoaders = new PropertySimple("numberOfClassLoaders", String.valueOf(classloaders.size())); PropertyList list = new PropertyList("classloaders"); info.getComplexResults().put(numClassLoaders); info.getComplexResults().put(list); for (Map.Entry<String, ClassLoader> entry : classloaders.entrySet()) { String id = entry.getKey(); ClassLoader classloader = entry.getValue(); PropertyMap map = new PropertyMap("classloader"); map.put(new PropertySimple("id", id)); map.put(new PropertySimple("classloaderInfo", classloader)); list.add(map); } return info; } public OperationResult retrieveAllResourceClassLoaderInformation() { Map<CanonicalResourceKey, ClassLoader> classloaders; Map<CanonicalResourceKey, String[]> canonicalIdMap = new HashMap<CanonicalResourceKey, String[]>(); // [0]=name, [1]=id, [2]=uuid ClassLoader originalCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); ClassLoaderManager clm = this.pluginContainer.getPluginManager().getClassLoaderManager(); InventoryManager im = this.pluginContainer.getInventoryManager(); classloaders = clm.getResourceClassLoaders(); for (CanonicalResourceKey canonicalId : classloaders.keySet()) { ResourceContainer container = im.getResourceContainer(canonicalId); String[] nameId = new String[3]; if (container != null) { nameId[0] = container.getResource().getName(); nameId[1] = Integer.toString(container.getResource().getId()); nameId[2] = container.getResource().getUuid(); } else { nameId[0] = "<unknown>"; nameId[1] = "<unknown>"; nameId[2] = "<unknown>"; } canonicalIdMap.put(canonicalId, nameId); } } finally { Thread.currentThread().setContextClassLoader(originalCL); } OperationResult info = new OperationResult(); PropertySimple numClassLoaders = new PropertySimple("numberOfResources", String.valueOf(classloaders.size())); PropertyList list = new PropertyList("classloaders"); info.getComplexResults().put(numClassLoaders); info.getComplexResults().put(list); for (Entry<CanonicalResourceKey, ClassLoader> entry : classloaders.entrySet()) { CanonicalResourceKey canonicalId = entry.getKey(); ClassLoader classloader = entry.getValue(); String[] data = canonicalIdMap.get(canonicalId); PropertyMap map = new PropertyMap("classloader"); map.put(new PropertySimple("resourceName", data[0])); map.put(new PropertySimple("resourceId", data[1])); map.put(new PropertySimple("resourceUuid", data[2])); map.put(new PropertySimple("canonicalId", canonicalId.toString())); map.put(new PropertySimple("classloaderInfo", classloader)); list.add(map); } classloaders.clear(); // don't need this shallow copy anymore, help the GC clean up return info; } public OperationResult retrieveUniqueResourceClassLoaderInformation() { // keyed on resource classloader with the value being the number of resources assigned the classloader Map<ClassLoader, AtomicInteger> classloaderCounts = new HashMap<ClassLoader, AtomicInteger>(); ClassLoader originalCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); ClassLoaderManager clm = this.pluginContainer.getPluginManager().getClassLoaderManager(); Map<CanonicalResourceKey, ClassLoader> classloaders = clm.getResourceClassLoaders(); for (Entry<CanonicalResourceKey, ClassLoader> entry : classloaders.entrySet()) { AtomicInteger count = classloaderCounts.get(entry.getValue()); if (count == null) { count = new AtomicInteger(1); classloaderCounts.put(entry.getValue(), count); } else { count.incrementAndGet(); } } classloaders.clear(); // don't need this shallow copy anymore, help the GC clean up } finally { Thread.currentThread().setContextClassLoader(originalCL); } OperationResult info = new OperationResult(); PropertySimple numClassLoaders = new PropertySimple("numberOfClassLoaders", String.valueOf(classloaderCounts .size())); PropertyList list = new PropertyList("classloaders"); info.getComplexResults().put(numClassLoaders); info.getComplexResults().put(list); for (Map.Entry<ClassLoader, AtomicInteger> entry : classloaderCounts.entrySet()) { ClassLoader classloader = entry.getKey(); AtomicInteger count = entry.getValue(); PropertyMap map = new PropertyMap("classloader"); map.put(new PropertySimple("classloaderInfo", classloader)); map.put(new PropertySimple("resourceCount", count.get())); list.add(map); } return info; } public int getNumberOfPluginClassLoaders() { return this.pluginContainer.getPluginManager().getClassLoaderManager().getNumberOfPluginClassLoaders(); } public int getNumberOfDiscoveryClassLoaders() { return this.pluginContainer.getPluginManager().getClassLoaderManager().getNumberOfDiscoveryClassLoaders(); } public int getNumberOfResourceClassLoaders() { return this.pluginContainer.getPluginManager().getClassLoaderManager().getNumberOfResourceClassLoaders(); } private String generateInventoryReportString(InventoryReport report) { StringBuilder reportStr = new StringBuilder(); if (report != null) { reportStr.append((report.isRuntimeReport() ? "*Service Scan" : "*Server Scan")); reportStr.append(" Inventory Report*\n"); reportStr.append("Start Time: ").append(new Date(report.getStartTime())).append('\n'); reportStr.append("Finish Time: ").append(new Date(report.getEndTime())).append('\n'); reportStr.append("Resource Count: ").append(report.getResourceCount()).append('\n'); reportStr.append("Error Count: ").append(report.getErrors().size()); } else { reportStr.append("No inventory report available!"); } return reportStr.toString(); } }