org.cyclopsgroup.jmxterm.cmd.RunCommand Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmxterm Show documentation
Show all versions of jmxterm Show documentation
Command line based interactive JMX client
package org.cyclopsgroup.jmxterm.cmd;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.commons.lang.Validate;
import org.cyclopsgroup.jcli.annotation.Argument;
import org.cyclopsgroup.jcli.annotation.Cli;
import org.cyclopsgroup.jcli.annotation.MultiValue;
import org.cyclopsgroup.jcli.annotation.Option;
import org.cyclopsgroup.jmxterm.Command;
import org.cyclopsgroup.jmxterm.Session;
import org.cyclopsgroup.jmxterm.SyntaxUtils;
import org.cyclopsgroup.jmxterm.io.ValueOutputFormat;
import org.cyclopsgroup.jmxterm.utils.ValueFormat;
/**
* Command to run an MBean operation
*
* @author Jiaqi Guo
*/
@Cli( name = "run", description = "Invoke an MBean operation", note = "Syntax is \n run [parameter1] [parameter2]" )
public class RunCommand
extends Command
{
private String bean;
private String domain;
private boolean measure;
private List parameters = Collections.emptyList();
private boolean showQuotationMarks;
private String types;
/**
* @inheritDoc
*/
@Override
public List doSuggestArgument()
throws IOException, JMException
{
Session session = getSession();
if ( getSession().getBean() != null )
{
MBeanInfo info =
session.getConnection().getServerConnection().getMBeanInfo( new ObjectName(
session.getBean() ) );
MBeanOperationInfo[] operationInfos = info.getOperations();
List ops = new ArrayList( operationInfos.length );
for ( MBeanOperationInfo op : operationInfos )
{
ops.add( op.getName() );
}
return ops;
}
return null;
}
/**
* @inheritDoc
*/
@Override
public void execute()
throws MalformedObjectNameException, IOException, JMException
{
Session session = getSession();
String beanName = BeanCommand.getBeanName( bean, domain, session );
if ( beanName == null )
{
throw new IllegalArgumentException(
"Please specify MBean to invoke either using -b option or bean command" );
}
Validate.isTrue( parameters.size() > 0,
"At least one parameter is needed" );
String[] paramTypes = null;
if ( types != null )
{
paramTypes = types.split( "," );
Validate.isTrue( paramTypes.length == parameters.size() - 1,
"Signature does not match parameter count" );
}
String operationName = parameters.get( 0 );
ObjectName name = new ObjectName( beanName );
MBeanServerConnection con =
session.getConnection().getServerConnection();
MBeanInfo beanInfo = con.getMBeanInfo( name );
// Looking for operation to invoke
MBeanOperationInfo operationInfo = null;
for ( MBeanOperationInfo info : beanInfo.getOperations() )
{
if ( operationName.equals( info.getName() )
&& info.getSignature().length == parameters.size() - 1 )
{
// If operation name and number of parameters matches, optionally check parameter types
if ( paramTypes == null )
{
operationInfo = info;
break;
}
// If paramTypes parameter is set, narrow down operation with parameter matching
boolean match = true;
MBeanParameterInfo[] paramInfos = info.getSignature();
for ( int i = 0; i < paramTypes.length && i < paramInfos.length; i++ )
{
// String type is treated specially
// type "string" implies type "java.lang.String"
if ( paramInfos[i].getType().equals( String.class.getName() )
&& paramTypes[i].equals( "string" ) )
{
continue;
}
if ( !paramTypes[i].equals( paramInfos[i].getType() ) )
{
match = false;
break;
}
}
if ( match )
{
operationInfo = info;
break;
}
}
}
// If no matching operation is found, throw an exception
if ( operationInfo == null )
{
throw new IllegalArgumentException( "Operation " + operationName
+ " with " + ( parameters.size() - 1 )
+ " parameters doesn't exist in bean " + beanName );
}
// Now set parameters to invoke with
Object[] params = new Object[parameters.size() - 1];
MBeanParameterInfo[] paramInfos = operationInfo.getSignature();
Validate.isTrue( params.length == paramInfos.length,
String.format( "%d parameters are expected but %d are provided",
paramInfos.length, params.length ) );
String[] signatures = new String[paramInfos.length];
for ( int i = 0; i < paramInfos.length; i++ )
{
MBeanParameterInfo paramInfo = paramInfos[i];
String expression = parameters.get( i + 1 );
if ( expression != null )
{
expression = ValueFormat.parseValue( expression );
}
Object paramValue =
SyntaxUtils.parse( expression, paramInfo.getType() );
params[i] = paramValue;
signatures[i] = paramInfo.getType();
}
session.output.printMessage( String.format( "calling operation %s of mbean %s with params %s",
operationName, beanName, Arrays.toString(params) ) );
// Invoke operation, record execution time if measure flag is on
Object result;
if ( measure )
{
long start = System.currentTimeMillis();
try
{
result = con.invoke( name, operationName, params, signatures );
}
finally
{
long latency = System.currentTimeMillis() - start;
session.output.printMessage( latency
+ "ms is taken by invocation" );
}
}
else
{
result = con.invoke( name, operationName, params, signatures );
}
session.output.printMessage( "operation returns: " );
new ValueOutputFormat( 2, false, showQuotationMarks ).printValue( session.output,
result );
// Finish with an empty line
session.output.println( "" );
}
/**
* @param bean Bean under which the operation is
*/
@Option( name = "b", longName = "bean", description = "MBean to invoke" )
public final void setBean( String bean )
{
this.bean = bean;
}
/**
* @param domain Domain under which is bean is
*/
@Option( name = "d", longName = "domain", description = "Domain of MBean to invoke" )
public final void setDomain( String domain )
{
this.domain = domain;
}
/**
* @param measure True if you want to display latency
*/
@Option( name = "m", longName = "measure", description = "Measure the time spent on the invocation of operation" )
public final void setMeasure( boolean measure )
{
this.measure = measure;
}
/**
* @param types
*/
@Option( name = "t", longName = "types", description = "Require parameters to have specific types (comma separated)" )
public final void setTypes( String types )
{
this.types = types;
}
/**
* @param parameters List of parameters. The first parameter is operation name
*/
@MultiValue( listType = ArrayList.class, minValues = 1 )
@Argument( description = "The first parameter is operation name, which is followed by list of arguments" )
public final void setParameters( List parameters )
{
Validate.notNull( parameters, "Parameters can't be NULL" );
this.parameters = parameters;
}
/**
* @param showQuotationMarks True if output is surrounded by quotation marks
*/
@Option( name = "q", longName = "quots", description = "Flag for quotation marks" )
public final void setShowQuotationMarks( boolean showQuotationMarks )
{
this.showQuotationMarks = showQuotationMarks;
}
}