package org.clamshellcli.jmx; import org.clamshellcli.api.Command; import org.clamshellcli.api.Context; import org.clamshellcli.api.IOConsole; import org.clamshellcli.core.ShellException; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.MBeanServerConnection; import javax.management.ObjectInstance; import javax.management.ObjectName; /* * Copyright 2012 ClamShell-Cli. * * 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. */ /** * This Command describes an MBean instance using MBean Info. * Format: * <pre> * desc * bean:<ObectName>|<BeanLabel> * [attribs:*|<attributeList>] * [ops:*|<OperationList>] * </pre> * @author vvivien */ public class DescribeCommand implements Command{ public static final String CMD_NAME = "desc"; public static final String NAMESPACE = "jmx"; public static final String KEY_ARGS_BEAN = "bean"; public static final String KEY_ARGS_ATTRIBS = "attribs"; public static final String KEY_ARGS_OPS = "ops"; private Command.Descriptor descriptor = null; public Descriptor getDescriptor() { return (descriptor != null ) ? descriptor : ( descriptor = new Command.Descriptor() { public String getNamespace() { return NAMESPACE; } public String getName() { return CMD_NAME; } public String getDescription() { return "Prints description for specified mbean."; } public String getUsage() { return "desc bean:<MBeanObjectName or MBeanLabel> [attribs:<attributes> ops:<operations>] ('help desc' for detail)."; } Map<String,String> args = null; public Map<String, String> getArguments() { if(args != null) return args; args = new LinkedHashMap<String,String>(); args.put(KEY_ARGS_BEAN + ":<NamePattern>", "The MBean object name pattern to describe"); args.put(KEY_ARGS_BEAN + ":<MBeanLabel>","A bean label that refers to an MBean"); args.put(KEY_ARGS_ATTRIBS + ":*", "Describes all attributes"); args.put(KEY_ARGS_ATTRIBS + ":<attribName>", "Name of a single attribute to describe"); args.put(KEY_ARGS_ATTRIBS + ":[attribList]", "A list of one or more attributes to describe"); args.put(KEY_ARGS_OPS + ":*", "Describes all operations"); args.put(KEY_ARGS_OPS + ":<operationName>", "Name of a single operation to describe"); args.put(KEY_ARGS_OPS + ":[operationList]", "A list of one or more operations to describe"); return args; } } ); } public Object execute(Context ctx) { IOConsole c = ctx.getIoConsole(); Map<String,Object> argsMap = (Map<String,Object>) ctx.getValue(Context.KEY_COMMAND_LINE_ARGS); Map<String,ObjectInstance[]> mbeanMap = (Map<String,ObjectInstance[]>)ctx.getValue(Management.KEY_MBEANS_MAP); // validate connection Management.verifyServerConnection(ctx); MBeanServerConnection server = (MBeanServerConnection)ctx.getValue(Management.KEY_JMX_MBEANSERVER); String mbeanParam = (argsMap != null) ? (String)argsMap.get(KEY_ARGS_BEAN) : null; Object attribsParam = (argsMap != null) ? argsMap.get(KEY_ARGS_ATTRIBS) : null; Object opsParam = (argsMap != null) ? argsMap.get(KEY_ARGS_OPS) : null; ObjectInstance[] objs = Management.findObjectInstances(ctx, mbeanParam); if(objs == null || objs.length == 0){ throw new ShellException(String.format("No MBeans found %s.",mbeanParam)); } try{ for(ObjectInstance obj : objs){ MBeanInfo beanInfo = server.getMBeanInfo(obj.getObjectName()); printObjectInstanceInfo(ctx, obj); // print attribs c.writeOutput(String.format("%n%nAttributes:")); if(attribsParam == null){ printObjectInstanceAttribs(ctx, obj); }else{ if(attribsParam instanceof String){ String val = (String) attribsParam; if(val.equals("*")){ printObjectInstanceAttribs(ctx, obj); }else{ MBeanAttributeInfo attrib = retrieveAttribInfoByName(beanInfo, val); c.writeOutput(String.format("%n%s",getAttribDesc(attrib))); } } if(attribsParam instanceof List){ List<String> attribNames = (List<String>)attribsParam; for(String name : attribNames){ if(name != null){ MBeanAttributeInfo attrib = retrieveAttribInfoByName(beanInfo,name); c.writeOutput(String.format("%n%s",getAttribDesc(attrib))); } } } } // print ops c.writeOutput(String.format("%n%nOperations:")); if(opsParam == null){ printObjectInstanceOps(ctx,obj); }else{ if(opsParam instanceof String){ String val = (String)opsParam; if(val.equals("*")){ printObjectInstanceOps(ctx,obj); }else{ MBeanOperationInfo op = retrieveOpInfoByName(beanInfo, val); c.writeOutput(String.format("%n%s",getOperationDesc(op))); } } if(opsParam instanceof List){ List<String> opNames = (List<String>)opsParam; for(String name : opNames){ MBeanOperationInfo op = retrieveOpInfoByName(beanInfo, name); c.writeOutput(String.format("%n%s",getOperationDesc(op))); } } } c.writeOutput(String.format("%n%n")); } }catch(Exception ex){ throw new ShellException(ex); } c.writeOutput(String.format("%n%n")); return null; } public void plug(Context plug) { //throw new UnsupportedOperationException("Not supported yet."); } private void printObjectInstanceInfo(Context ctx, ObjectInstance obj) throws Exception{ IOConsole c = ctx.getIoConsole(); MBeanServerConnection server = (MBeanServerConnection)ctx.getValue(Management.KEY_JMX_MBEANSERVER); ObjectName name = obj.getObjectName(); c.writeOutput(String.format("%nMBean: %s (%s)", name.getCanonicalName(), obj.getClassName())); MBeanInfo info = server.getMBeanInfo(name); c.writeOutput(String.format("%n%s", info.getDescription())); } private void printObjectInstanceAttribs(Context ctx, ObjectInstance obj) throws Exception { IOConsole c = ctx.getIoConsole(); MBeanServerConnection server = (MBeanServerConnection)ctx.getValue(Management.KEY_JMX_MBEANSERVER); MBeanInfo info = server.getMBeanInfo(obj.getObjectName()); MBeanAttributeInfo[] attribs = info.getAttributes(); for(MBeanAttributeInfo attrib : attribs){ c.writeOutput(String.format("%n%s",getAttribDesc(attrib))); } } private String getAttribDesc(MBeanAttributeInfo attrib){ StringBuilder result = new StringBuilder(); result.append(String.format("%5s%s : %s ", " ", attrib.getName(), attrib.getType())); result.append("("); if (attrib.isReadable()) { result.append("r"); } if (attrib.isWritable()) { result.append("w"); } result.append(")"); result.append(" - ").append(attrib.getDescription()); return result.toString(); } private MBeanAttributeInfo retrieveAttribInfoByName(MBeanInfo mbeanInfo, String attribName){ MBeanAttributeInfo[] attribs = mbeanInfo.getAttributes(); for(MBeanAttributeInfo attrib : attribs){ if(attrib.getName().equalsIgnoreCase(attribName)){ return attrib; } } return null; } private void printObjectInstanceOps(Context ctx, ObjectInstance obj) throws Exception{ IOConsole c = ctx.getIoConsole(); MBeanServerConnection server = (MBeanServerConnection)ctx.getValue(Management.KEY_JMX_MBEANSERVER); MBeanInfo info = server.getMBeanInfo(obj.getObjectName()); MBeanOperationInfo[] ops = info.getOperations(); for(MBeanOperationInfo op : ops){ c.writeOutput(String.format("%n%s",getOperationDesc(op))); } } private String getOperationDesc(MBeanOperationInfo op){ StringBuilder result = new StringBuilder(); result.append(String.format("%5s%s"," ",op.getName())); result.append("("); MBeanParameterInfo[] params = op.getSignature(); for(int j = 0; j < params.length; j++){ result.append(params[j].getType()); if(j < params.length-1){ result.append(","); } } result.append(")"); result.append(":").append(op.getReturnType()); return result.toString(); } private MBeanOperationInfo retrieveOpInfoByName(MBeanInfo mbeanInfo, String opName){ MBeanOperationInfo[] ops = mbeanInfo.getOperations(); for(MBeanOperationInfo op : ops){ if(op.getName().equalsIgnoreCase(opName)){ return op; } } return null; } }