package crash.commands.base;
import org.crsh.cli.Argument;
import org.crsh.cli.Man;
import org.crsh.cli.Command;
import org.crsh.cli.Named;
import org.crsh.cli.Option;
import org.crsh.cli.Usage;
import org.crsh.cli.Required;
import org.crsh.command.BaseCommand;
import org.crsh.command.InvocationContext;
import org.crsh.command.Pipe;
import org.crsh.command.ScriptException;
import javax.management.AttributeNotFoundException;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.RuntimeMBeanException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** @author Julien Viet */
@Usage("Java Management Extensions")
@Man("The jmx commands interracts with the JMX registry allowing several kind JMX operations.")
public class jmx extends BaseCommand {
@Usage("query mbeans")
@Man(
"Create a stream of managed beans, by default the stream will contain all the registered managed beans:\n" +
"% jmx query\n" +
"...\n" +
"The stream can be filtered with the pattern option:\n" +
"% jmx query -p java.lang:*\n" +
"..."
)
@Command
public void query(
InvocationContext<ObjectName> context,
@Usage("the object name pattern for the query")
@Argument
String pattern) throws Exception {
//
ObjectName patternName = pattern != null ? ObjectName.getInstance(pattern) : null;
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
Set<ObjectInstance> instances = server.queryMBeans(patternName, null);
for (ObjectInstance instance : instances) {
context.provide(instance.getObjectName());
}
}
@Usage("provide the mbean info of a managed bean")
@Man(
"Provide the mbean info for a managed bean:\n" +
"% jmx info java.lang:type=ClassLoading \n" +
"sun.management.ClassLoadingImpl\n" +
"+- ClassName sun.management.ClassLoadingImpl\n" +
"| Description Information on the management interface of the MBean\n" +
"+-Descriptor\n" +
"| +-immutableInfo true\n" +
"| interfaceClassName java.lang.management.ClassLoadingMXBean\n" +
"| mxbean true\n" +
"+-Attributes\n" +
"| +-NAME TYPE DESCRIPTION\n" +
"| Verbose boolean Verbose\n" +
"| TotalLoadedClassCount long TotalLoadedClassCount\n" +
"| LoadedClassCount int LoadedClassCount\n" +
"| UnloadedClassCount long UnloadedClassCount\n" +
"| ObjectName javax.management.ObjectName ObjectName\n" +
"+-Operations\n"
)
@Command
@Named("info")
public MBeanInfo info(@Required @Argument @Usage("a managed bean object name") ObjectName mbean) {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
return server.getMBeanInfo(mbean);
}
catch (JMException e) {
throw new ScriptException("Could not retrieve mbean " + mbean + "info", e);
}
}
@Usage("get attributes of a managed bean")
@Man(
"Retrieves the attributes of a stream of managed beans, this command can be used " +
"by specifying managed bean arguments\n" +
"% jmx get java.lang:type=ClassLoading\n" +
"It also accepts a managed bean stream:\n" +
"% jmx query -p java.lang:* | jmx get\n" +
"By default all managed bean attributes will be retrieved, the attributes option allow to " +
"use a list of attributes:\n" +
"% jmx query -p java.lang:* | jmx get -a TotalSwapSpaceSize\n"
)
@Command
public Pipe<ObjectName, Map> get(
@Usage("silent mode ignores any attribute runtime failures")
@Option(names = {"s","silent"})
final Boolean silent,
@Usage("add a column with the option value with the managed bean name")
@Option(names = {"n","name"})
final String name,
@Usage("specifies a managed bean attribute name")
@Option(names = {"a","attributes"}) final List<String> attributes,
@Usage("a managed bean object name")
@Argument(name = "mbean") final List<ObjectName> mbeans
) {
//
return new Pipe<ObjectName, Map>() {
/** . */
private MBeanServer server;
/** . */
private List<ObjectName> buffer;
@Override
public void open() throws ScriptException {
this.server = ManagementFactory.getPlatformMBeanServer();
this.buffer = new ArrayList<ObjectName>();
//
if (mbeans != null) {
buffer.addAll(mbeans);
}
}
@Override
public void provide(ObjectName name) throws IOException {
buffer.add(name);
}
@Override
public void close() throws Exception, IOException {
// Determine attribute names
String[] names;
if (attributes == null) {
LinkedHashSet<String> tmp = new LinkedHashSet<String>();
for (ObjectName mbean : buffer) {
MBeanInfo mbeanInfo;
try {
mbeanInfo = server.getMBeanInfo(mbean);
}
catch (JMException e) {
throw new ScriptException(e);
}
for (MBeanAttributeInfo attributeInfo : mbeanInfo.getAttributes()) {
if (attributeInfo.isReadable()) {
tmp.add(attributeInfo.getName());
}
}
}
names = tmp.toArray(new String[tmp.size()]);
} else {
names = attributes.toArray(new String[attributes.size()]);
}
// Produce the output
for (ObjectName mbean : buffer) {
LinkedHashMap<String, Object> tuple = new LinkedHashMap<String, Object>();
if (name != null) {
tuple.put(name, mbean);
}
for (String name : names) {
Object value;
try {
value = server.getAttribute(mbean, name);
}
catch (RuntimeMBeanException runtime) {
if (Boolean.TRUE.equals(silent)) {
throw new ScriptException(runtime.getCause());
} else {
value = null;
}
}
catch (AttributeNotFoundException e) {
value = null;
}
catch (JMException e) {
throw new ScriptException(e);
}
tuple.put(name, value);
}
context.provide(tuple);
}
}
};
}
}