net.bull.javamelody.internal.model.MBeans Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javamelody-core Show documentation
Show all versions of javamelody-core Show documentation
Monitoring of JavaEE applications
/*
* Copyright 2008-2019 by Emeric Vernat
*
* This file is part of Java Melody.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bull.javamelody.internal.model;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.management.Attribute;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import net.bull.javamelody.internal.common.I18N;
import net.bull.javamelody.internal.common.LOG;
import net.bull.javamelody.internal.model.MBeanNode.MBeanAttribute;
/**
* Objet récupérant une instance de {@link MBeanServer} lors de sa construction
* et permettant de récupérer différentes données sur les MBeans.
* @author Emeric Vernat
*/
public final class MBeans {
/**
* Separator between mbeans attributes in the External API.
*/
public static final char ATTRIBUTES_SEPARATOR = '|';
private static final String JAVA_LANG_MBEAN_DESCRIPTION = "Information on the management interface of the MBean";
private static final Comparator NODE_COMPARATOR = new Comparator() {
@Override
public int compare(MBeanNode o1, MBeanNode o2) {
return o1.getName() != null ? o1.getName().compareTo(o2.getName()) : 0;
}
};
private static final Comparator ATTRIBUTE_COMPARATOR = new Comparator() {
@Override
public int compare(MBeanAttribute o1, MBeanAttribute o2) {
return o1.getName().compareTo(o2.getName());
}
};
private final MBeanServer mbeanServer;
MBeans() {
this(getPlatformMBeanServer());
}
private MBeans(MBeanServer mbeanServer) {
super();
this.mbeanServer = mbeanServer;
}
Object getAttribute(ObjectName name, String attribute) throws JMException {
return mbeanServer.getAttribute(name, attribute);
}
public static List getAllMBeanNodes() throws JMException {
initJRockitMBeansIfNeeded();
final List result = new ArrayList<>();
final MBeanServer platformMBeanServer = getPlatformMBeanServer();
final MBeanNode platformNode = new MBeanNode("");
// MBeans pour la plateforme
final MBeans platformMBeans = new MBeans();
platformNode.getChildren().addAll(platformMBeans.getMBeanNodes());
result.add(platformNode);
// pour JBoss 5.0.x, les MBeans de JBoss sont dans un autre MBeanServer
for (final MBeanServer mbeanServer : getMBeanServers()) {
if (!mbeanServer.equals(platformMBeanServer)) {
final MBeanNode node = new MBeanNode(mbeanServer.getDefaultDomain());
final MBeans mbeans = new MBeans(mbeanServer);
node.getChildren().addAll(mbeans.getMBeanNodes());
result.add(node);
}
}
return result;
}
private static void initJRockitMBeansIfNeeded() {
// si jrockit, on initialise les MBeans spécifiques jrockit lors de la première demande
if (System.getProperty("java.vendor").contains("BEA")) {
try {
// initialisation des MBeans jrockit comme indiqué dans http://blogs.oracle.com/hirt/jrockit/
try {
getPlatformMBeanServer().getMBeanInfo(
new ObjectName("bea.jrockit.management:type=JRockitConsole"));
} catch (final InstanceNotFoundException e1) {
getPlatformMBeanServer().createMBean("bea.jrockit.management.JRockitConsole",
null);
LOG.debug("JRockit MBeans initialized");
}
} catch (final JMException e) {
throw new IllegalStateException(e);
}
}
}
private List getMBeanNodes() throws JMException {
final List result = new ArrayList<>();
final Set names = mbeanServer.queryNames(null, null);
for (final ObjectName name : names) {
final String domain = name.getDomain();
if ("jboss.deployment".equals(domain)) {
// la partie "jboss.deployment" dans JBoss (5.0.x) est plutôt inutile et trop lourde
continue;
}
MBeanNode domainNode = getMBeanNodeFromList(result, domain);
if (domainNode == null) {
domainNode = new MBeanNode(domain);
result.add(domainNode);
}
final String keyPropertyListString = name.getKeyPropertyListString();
final String firstPropertyValue;
final int indexOf = keyPropertyListString.indexOf('=');
if (indexOf == -1) {
// n'arrive probablement pas, mais au cas où
firstPropertyValue = null;
} else {
firstPropertyValue = name
.getKeyProperty(keyPropertyListString.substring(0, indexOf));
}
MBeanNode firstPropertyNode = getMBeanNodeFromList(domainNode.getChildren(),
firstPropertyValue);
if (firstPropertyNode == null) {
firstPropertyNode = new MBeanNode(firstPropertyValue);
domainNode.getChildren().add(firstPropertyNode);
}
try {
final MBeanNode mbean = getMBeanNode(name);
firstPropertyNode.getChildren().add(mbean);
} catch (final IllegalStateException e) {
// for JBoss EAP 6 (#757)
continue;
}
}
sortMBeanNodes(result);
return result;
}
private void sortMBeanNodes(List nodes) {
if (nodes.size() > 1) {
Collections.sort(nodes, NODE_COMPARATOR);
}
for (final MBeanNode node : nodes) {
final List children = node.getChildren();
if (children != null) {
sortMBeanNodes(children);
}
final List attributes = node.getAttributes();
if (attributes != null && attributes.size() > 1) {
Collections.sort(attributes, ATTRIBUTE_COMPARATOR);
}
}
}
private static MBeanNode getMBeanNodeFromList(List list, String name) {
for (final MBeanNode node : list) {
if (node.getName().equals(name)) {
return node;
}
}
return null;
}
private MBeanNode getMBeanNode(ObjectName name) throws JMException {
final String mbeanName = name.toString();
final MBeanInfo mbeanInfo = mbeanServer.getMBeanInfo(name);
final String description = formatDescription(mbeanInfo.getDescription());
final MBeanAttributeInfo[] attributeInfos = mbeanInfo.getAttributes();
final List attributes = getAttributes(name, attributeInfos);
// les attributs seront triés par ordre alphabétique dans getMBeanNodes
return new MBeanNode(mbeanName, description, attributes);
}
private List getAttributes(ObjectName name,
MBeanAttributeInfo[] attributeInfos) {
final List attributeNames = new ArrayList<>(attributeInfos.length);
for (final MBeanAttributeInfo attribute : attributeInfos) {
// on ne veut pas afficher l'attribut password, jamais
// (notamment, dans users tomcat ou dans datasources tomcat)
// et on ne veut pas afficher l'attribut configurationAsProperties d'infinispan (issue 1180)
if (attribute.isReadable() && !"password".equalsIgnoreCase(attribute.getName())
&& !"configurationAsProperties".equalsIgnoreCase(attribute.getName())) {
attributeNames.add(attribute.getName());
}
}
final String[] attributeNamesArray = attributeNames.toArray(new String[0]);
final List result = new ArrayList<>();
try {
// issue 116: asList sur mbeanServer.getAttributes(name, attributeNamesArray) n'existe qu'en java 1.6
final List