FileDocCategorySizeDatePackage
CLISupportTester.javaAPI DocGlassfish v2 API16476Fri May 04 22:24:54 BST 2007com.sun.cli.jmx.test

CLISupportTester.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
 
/*
 * $Header: /cvs/glassfish/admin-cli/cli-api/src/java/com/sun/cli/jmx/test/CLISupportTester.java,v 1.4 2007/05/05 05:24:53 tcfujii Exp $
 * $Revision: 1.4 $
 * $Date: 2007/05/05 05:24:53 $
 */
 
package com.sun.cli.jmx.test;

// java imports
//
import java.lang.reflect.Array;

// RI imports
//
import javax.management.*;
import javax.management.remote.JMXServiceURL;

import com.sun.jmx.trace.Trace;

import com.sun.cli.util.stringifier.*;
import com.sun.cli.util.ClassUtil;

import com.sun.cli.jmx.support.CLISupportStrings;
import com.sun.cli.jmx.support.StandardAliases;
import com.sun.cli.jmx.support.CLISupportMBeanProxy;
import com.sun.cli.jmx.support.InspectRequest;
import com.sun.cli.jmx.support.InspectResult;
import com.sun.cli.jmx.support.InvokeResult;
import com.sun.cli.jmx.support.ResultsForGetSet;
import com.sun.cli.jmx.support.InspectResultStringifier;
import com.sun.cli.jmx.support.ResultsForGetSetStringifier;
import com.sun.cli.jmx.support.InvokeResultStringifier;


public final class CLISupportTester
{
	final MBeanServerConnection	mServer;
	final CLISupportMBeanProxy	mProxy;
	final TestLog				mLog;
	
	final static private String		ALIAS_BASE	= "test-alias-";
	private final static String		CLI_TEST_ALIAS_NAME	= ALIAS_BASE + "generic-test";

		public
	CLISupportTester( MBeanServerConnection conn, CLISupportMBeanProxy proxy )
		throws Exception
	{
		this( conn, proxy, new StdOutTestLog() );
	}
	
		public
	CLISupportTester( MBeanServerConnection conn, CLISupportMBeanProxy proxy, TestLog logger)
		throws Exception
	{
		mServer	= conn;
		mLog	= logger;
		
		mProxy	= proxy;
	}

		private void
	p( Object arg )
	{
		mLog.println( arg );
	}
	
		private void
	p( Object arg, boolean newline)
	{
		if ( newline )
		{
			p( arg );
		}
		else
		{
			mLog.print( arg );
		}
	}
	
		private void
	begin( String msg )
	{
		p( msg + "...", false);
	}
	
		private static String
	quote( Object str )
	{
		return( "\"" + str.toString() + "\"" );
	}
	

		private void
	TestMBeanList( CLISupportMBeanProxy test ) throws Exception
	{
		final String []	testStrings	= new String [] { StandardAliases.ALL_ALIAS };
		
		final ObjectName []	results	= test.mbeanFind( testStrings );
		final int			numObjects	= Array.getLength( results );
		
		final ArrayStringifier	testStringsStringifier	= new ArrayStringifier( "," );
		
		p( "\nmbean-list results: " + numObjects +
			" mbeans for expr " + testStringsStringifier.stringify( testStrings ) );
		
		final String	str	= ArrayStringifier.stringify( results, "\n", ObjectStringifier.DEFAULT);
		p ( str );
		
		p( "TestMBeanList...DONE: listed " + numObjects + " for " + testStrings[ 0 ] );
	}
	
		private void
	TestMBeanInspect( CLISupportMBeanProxy test, String [] patterns ) throws Exception
	{
		begin( "TestMBeanInspect" );
		
		final InspectRequest	request	= new InspectRequest();
		
		final InspectResult []	results	= test.mbeanInspect( request, patterns );
		final int			numResults	= Array.getLength( results );
		
		final String	summary	= "" + numResults +
				" mbeans for expr " + ArrayStringifier.stringify( patterns, ",");
				
		final String	str	= ArrayStringifier.stringify( results, "\n\n", new InspectResultStringifier());
		
		p( "DONE: inspected " + summary);
	}
	
		private void
	TestMBeanGet( CLISupportMBeanProxy test, String [] targets ) throws Exception
	{
		begin( "TestMBeanGet" );
		
		final ResultsForGetSet []	results	= test.mbeanGet( "*", targets );
		final int					numResults	= Array.getLength( results );
		
		final String	summary	= "" + numResults +
				" mbeans for expr " + ArrayStringifier.stringify( targets, ",");
				
		final ResultsForGetSetStringifier resultStringifier =
			new ResultsForGetSetStringifier(  );
			
		final String str	= ArrayStringifier.stringify( results, "\n\n", resultStringifier);
		
		p ( str );
		
		p( "DONE: inspected " + summary);
	}
	
	
		private String
	InvokeResultsToString( InvokeResult []	results)
	{
		return( ArrayStringifier.stringify( results, "\n", new InvokeResultStringifier() ) );
	}
	
	
		private void
	testInvoke( String operationName, String args, String [] targets )
		throws Exception
	{
		InvokeResult []	results = null;
		
		results = mProxy.mbeanInvoke( operationName, args, targets );
		
		p( InvokeResultsToString( results ) + "\n" );
	}
	
		private void
	TestNamedInvoke( CLISupportMBeanProxy test, String [] targets ) throws Exception
	{
		begin( "TestNamedInvoke" );
		
		testInvoke( "testNamed", "p1=hello", targets );
		
		testInvoke( "testNamed", "p1=hello,p2=there", targets );
		
		testInvoke( "testNamed", "p1=hello,p2=there,p3=!!!", targets );
		
		testInvoke( "testNamed", "p1=hello,p2=there,p3=!!!,p4=foobar", targets );
		
		p( "DONE ");
	}


		private void
	TestMBeanInvoke( CLISupportMBeanProxy test, String [] targets ) throws Exception
	{
		TestNamedInvoke( test, targets );
	}

	
	
		private void
	deleteTestAliases() throws Exception
	{
		final String []	aliases	= mProxy.listAliases( false );
		
		for( int i = 0; i < aliases.length; ++i )
		{
			final String	name	= aliases[ i ];
			
			if ( name.startsWith( ALIAS_BASE ) )
			{
				p( "deleteTestAliases: deleting: " + name );
				mProxy.deleteAlias( name );
			}
		}
	}
	
		private void
	TestAliases(  ) throws Exception
	{
		begin( "TestAliases" );
		
		deleteTestAliases();
		
		int	failureCount	= 0;
		
		// create an alias for each MBean
		final ObjectName []	names	= mProxy.mbeanFind( new String [] { StandardAliases.ALL_ALIAS } );
		final int			numNames	= Array.getLength( names );
		
		// create  test alias for each existing MBean
		for( int i = 0; i < numNames; ++i )
		{
			final String	aliasName	= ALIAS_BASE + (i+1);
			mProxy.createAlias( aliasName, names[ i ].toString() );
		}
		
		// now verify that each of them resolves correctly
		for( int i = 0; i < numNames; ++i )
		{
			final String	aliasName	= ALIAS_BASE + (i+1);
			
			final String	aliasValue	= mProxy.resolveAlias( aliasName );
			if ( aliasValue == null || ! names[ i ].toString().equals( aliasValue ))
			{
				++failureCount;
				p( "FAILURE: alias " + aliasName + ": " +
					quote( aliasValue ) + " != " + quote( names[ i ].toString() ) );
			}
		}
		
		// create an alias consisting of all aliases
		final String	ALL_ALIASES_NAME	= ALIAS_BASE + "all";
		final String []	aliases	= mProxy.listAliases( false );
		final String	allAliases	= ArrayStringifier.stringify( aliases, " " );
		mProxy.createAlias( ALL_ALIASES_NAME, allAliases );
		
		// create a recursive alias
		String	allAliasesName	= ALL_ALIASES_NAME;
		for( int i = 0; i < 5; ++i )
		{
			mProxy.createAlias( allAliasesName + i, allAliasesName );
			allAliasesName	= allAliasesName + i;
		}
		
		// verify that the alias to all of them produces the same set of names as we started with
		final ObjectName []	resolvedNames	= mProxy.resolveTargets( new String [] { allAliasesName } );
		//p( "all aliases = " + ArrayStringifier.stringify( resolvedNames, "\n" ) );
		if ( Array.getLength( resolvedNames ) !=  numNames )
		{
			++failureCount;
		}
		
		deleteTestAliases();
		
		if ( failureCount == 0 )
		{
			p( "DONE" );
		}
		else
		{
			p( "FAILURES = " + failureCount );
		}
	}
	
	/*
		Convert the parameters to String suitable for consumption by the CLISupportMBean
	 */
		private String
	MakeArgList( final String [] args )
	{
		final int			numArgs	= Array.getLength( args );
		String				result	= null;
		
		if ( numArgs != 0 )
		{
			final StringBuffer	buf	= new StringBuffer();
		
			for( int i = 0; i < numArgs; ++i )
			{
				buf.append( args[ i ] );
				buf.append( "," );
			}
			// strip trailing ","
			buf.setLength( buf.length() - 1 );
			
			result	= new String( buf ) ;
		}
		
		return( result );
	}
	
	
		private String
	getCastType( String type )
		throws ClassNotFoundException
	{
		String	result	= type;
		
		if ( ClassUtil.classnameIsArray( result ) )
		{
			final Class	theClass	= ClassUtil.getClassFromName(result);
			
			final Class elementClass	= ClassUtil.getInnerArrayElementClass( theClass );
			
			result	= elementClass.getName();
		}
		
		return( result );
	}
	
	
	
		private InvokeResult.ResultType
	TestOperationGenerically(
		final CLISupportMBeanProxy	test,
		final boolean				namedArgs,
		final ObjectName			targetName,
		final MBeanOperationInfo	operationInfo )
		throws Exception
	{
		final MBeanParameterInfo []	paramInfos	= operationInfo.getSignature();
		final int					numParams	= Array.getLength( paramInfos );
		
		final String []	strings	= new String [ numParams ];
		final String	operationName	= operationInfo.getName();
		
		// create an object of the correct type for each parameter.
		// The actual value is not important.
		for( int i = 0; i < numParams; ++i )
		{
			final MBeanParameterInfo	paramInfo	= paramInfos[ i ];
			final String				paramType	= paramInfos[ i ].getType();
			final Class					theClass	= ClassUtil.getClassFromName( paramType );
			
			final Object paramObject	= ClassUtil.InstantiateDefault( theClass );
			final String paramString	= SmartStringifier.toString( paramObject );
			final String castString		= "(" + getCastType( paramType ) + ")";
			
			final String paramName		= namedArgs ? (paramInfo.getName() + '=') : "";
			
			strings[ i ]	= paramName + castString + paramString;
		}
		
		// convert the arguments to strings
		final String	argString	= MakeArgList( strings );
		
		final String []	args	= new String [] { targetName.toString() };
		
		final InvokeResult []	results	= (InvokeResult [])test.mbeanInvoke( operationName, argString, args );
		final InvokeResult	result	= results[ 0 ];
		
		if ( result.getResultType() == InvokeResult.SUCCESS )
		{
			// p( "SUCCESS: " + operationName + "(" + SmartStringifier.toString( paramInfos ) + ")");
		}
		else
		{
			final String paramInfosString	= SmartStringifier.toString( paramInfos );
			
			p( "FAILURE: " + operationName + "(" + paramInfosString + ")" +
				" with " + argString );
			result.mThrowable.printStackTrace();
		}
		
		return( result.getResultType() );
	}
	
	static private final Class []	GENERICALLY_TESTABLE_CLASSES	= 
	{
		boolean.class,
		char.class,
		byte.class, short.class, int.class, long.class,
		float.class, double.class,
		Boolean.class,
		Character.class,
		Byte.class, Short.class, Integer.class, Long.class,
		Float.class,
		Double.class,
		Number.class,
		String.class,
		Object.class,
		java.math.BigDecimal.class,
		java.math.BigInteger.class,
		java.net.URL.class,
		java.net.URI.class

	};
		private boolean
	IsGenericallyTestableClass( final Class theClass )
		throws ClassNotFoundException
	{
		boolean	isTestable	= false;
		
		Class	testClass	= theClass;
		if ( ClassUtil.classIsArray( theClass ) )
		{
			// we can test all arrays of supported types
			testClass	= ClassUtil.getInnerArrayElementClass( theClass );
		}
		
		final Class []	classes	= GENERICALLY_TESTABLE_CLASSES;
		final int	numClasses	= Array.getLength( classes );
		for( int i = 0; i < numClasses; ++i )
		{
			if ( testClass == classes[ i ] )
			{
				isTestable	= true;
				break;
			}
		}
		
		if ( ! isTestable  )
		{
			assert( testClass == java.util.Properties.class );
		}
		
		return( isTestable );
	}
	
		private boolean
	IsGenericallyTestable( final MBeanOperationInfo operationInfo )
		throws ClassNotFoundException
	{
		boolean	isTestable	= true;
		
		final MBeanParameterInfo []	paramInfos	= operationInfo.getSignature();
		final int					numParams	= Array.getLength( paramInfos );
		for( int i = 0; i < numParams; ++i )
		{
			final Class	theClass	= ClassUtil.getClassFromName( paramInfos[i].getType() );
			
			if ( ! IsGenericallyTestableClass( theClass ) )
			{
				isTestable	= false;
				break;
			}
		}
		
		return( isTestable );
	}
	
	
		private void
	TestGeneric( CLISupportMBeanProxy test, boolean namedTest, ObjectName objectName ) throws Exception
	{
		final MBeanInfo				info	= mServer.getMBeanInfo( objectName );
		final MBeanOperationInfo []	opInfo	= info.getOperations();
		
		begin( "TestGeneric" );
		
		int	successCount	= 0;
		int	failureCount	= 0;
		int	notTestedCount	= 0;
		for( int i = 0; i < Array.getLength( opInfo ); ++i )
		{
			try
			{
				if ( IsGenericallyTestable( opInfo[ i ] ) )
				{
					final InvokeResult.ResultType resultType	= TestOperationGenerically( test,namedTest, objectName, opInfo[ i ] );
					if ( resultType == InvokeResult.SUCCESS )
					{
						++successCount;
					}
					else
					{
						++failureCount;
					}
				}
				else
				{
					++notTestedCount;
				}
			}
			catch( Exception e )
			{
				p( "FAILURE: " + SmartStringifier.toString( opInfo[ i ] ) );
			}
		}
		
		p( "DONE " + (namedTest ? "NAMED":"ORDERED") +
			": SUCCESSES = " + successCount +
			", FAILURES = " + failureCount +
			", NOT TESTABLE = " + notTestedCount );
	}
	
		private void
	TestGeneric( CLISupportMBeanProxy test, String [] targets ) throws Exception
	{
		final ObjectName []	allObjects	= test.mbeanFind( targets );
		
		assert( allObjects.length >= 1 );
		
		for( int i = 0; i < allObjects.length; ++i )
		{
			TestGeneric( test, false, allObjects[ i ] );
		}
		
		for( int i = 0; i < allObjects.length; ++i )
		{
			TestGeneric( test, true, allObjects[ i ] );
		}
	}
	
		private void
	VerifySetup( CLISupportMBeanProxy proxy ) throws Exception
	{
		// must be at least one MBean
		final ObjectName []	all	= proxy.resolveTargets( new String [] { "*" } );
		assert( all.length != 0 );
		
		// verify that the AliasMgr and CLI are available.
		final String []	aliases	= proxy.listAliases( false );
		assert( aliases.length != 0 );
		
		// verify that required aliases are in place
		assert( proxy.resolveAlias( StandardAliases.ALL_ALIAS ) != null );
		assert( proxy.resolveAlias( StandardAliases.CLI_ALIAS ) != null );
		assert( proxy.resolveAlias( StandardAliases.ALIAS_MGR_ALIAS ) != null );
		
	}
	
	
		public void
	Run() throws Exception
	{
		final CLISupportMBeanProxy	proxy	= mProxy;
		
		try
		{
			// ensure certain aliases are present, as we use them
			final String []	all			= new String [] { StandardAliases.ALL_ALIAS };
		
			VerifySetup( proxy );
			
			TestAliases(  );
			
			TestMBeanList( proxy );
			
			TestMBeanGet( proxy, all );
			
			TestMBeanInspect( proxy, all );
			
			proxy.deleteAlias( CLI_TEST_ALIAS_NAME );
			proxy.createAlias( CLI_TEST_ALIAS_NAME, CLISupportStrings.CLI_SUPPORT_TESTEE_TARGET );
			final String []	testMBean	= new String [] { CLI_TEST_ALIAS_NAME };
			
			TestMBeanInvoke( proxy, testMBean );
			
			TestGeneric( proxy, testMBean);
			
			
			p( "DONE" );
			
				
		}
		catch( Exception e )
		{
			e.printStackTrace();
		}
	}


};