

package gov.va.med.cds.client.functional.mbean;


import gov.va.med.cds.client.functional.AbstractFunctionalTest;
import gov.va.med.cds.junit.runners.AfterTestsOnce;
import gov.va.med.cds.junit.runners.BeforeTestsOnce;
import gov.va.med.cds.junit.runners.AfterTestsOnce;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.junit.runners.Suite;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.HashMap;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;


/**
 * Tests the filter memory cache ManagedBean operations using JMX Connectors
 * 
 * @author DNS   THUMMP
 * 
 */

@RunWith( SuiteAwareRunner.class )
public class FilterMemoryCacheResizeMBeanTest
    extends
        AbstractFunctionalTest
{
    private static Log logger;
    private static final String NL = System.getProperty( "line.separator" );
    private static final String MBEAN_SERVER_IP = "localhost";
    private static final String MBEAN_SERVER_PORT = "5555";
    private static final String ADMIN_USER_ENV_PROPERTY_NAME = "USER";
    private static final String ADMIN_PASSWORD_ENV_PROPERTY_NAME = "PASSWORD";
    private static final String FILTER_MANAGER_MBEAN_DOMAIN = "gov.va.med.cds.filter";
    private static final String FILTER_MANAGER_MBEAN_NAME = ":name=cds-filter-manager";

    private static JMXConnector jmxc;
    private static ObjectName stdMBeanName;
    private static MBeanServerConnection mbsc;


    public static final void usage( )
    {
        System.err.println( "The FilterManager JMX client:" + NL + "Options:" + NL + " -ip - IP Address to FilterManager." + NL
                        + " -port - Listening port." + NL + " -user - (optional) Specify the username for authentication." + NL
                        + " -password - (optional) Specify the password for authentication." + NL );

        System.exit( 1 );
    }


    @Test
    @Suite( groups = "prototypetest" )
    public void testVerifyFilterCacheResize( )
        throws Exception
    {
        // increasing filterMemoryCacheMap capacity to 15
        mbsc.invoke( stdMBeanName, "resizeFilterMemoryCache", new Object[] { 15 }, new String[] { "int" } );
        System.out.println( "=====After INCREASING FilterCache Threshold from 10 (default) to 15======" );
        // get the current size of filterMemoryCache
        System.out.println( "Number of FilterSchemas loaded into FilterCache : "
                        + mbsc.invoke( stdMBeanName, "getNumberOfFilterSchemasLoadedIntoFilterCache", null, null ) );
        Assert.assertEquals( ( ( Integer )mbsc.invoke( stdMBeanName, "getFilterCacheThreshold", null, null ) ).intValue(), 15 );

        // decreasing filterMemoryCacheMap capacity to 6
        mbsc.invoke( stdMBeanName, "resizeFilterMemoryCache", new Object[] { 6 }, new String[] { "int" } );
        System.out.println( "\n=====After DECREASING FilterCache Threshold from 15 to 6======" );
        // get the current size of filterMemoryCache
        System.out.println( "Number of FilterSchemas loaded into FilterCache : "
                        + mbsc.invoke( stdMBeanName, "getNumberOfFilterSchemasLoadedIntoFilterCache", null, null ) );
        Assert.assertEquals( ( ( Integer )mbsc.invoke( stdMBeanName, "getFilterCacheThreshold", null, null ) ).intValue(), 6 );

        // increasing filterMemoryCacheMap capacity to 10
        mbsc.invoke( stdMBeanName, "resizeFilterMemoryCache", new Object[] { 10 }, new String[] { "int" } );
        System.out.println( "\n=====After INCREASING FilterCache Threshold from 6 to 10======" );
        // get the current size of filterMemoryCache
        System.out.println( "Number of FilterSchemas loaded into FilterCache : "
                        + mbsc.invoke( stdMBeanName, "getNumberOfFilterSchemasLoadedIntoFilterCache", null, null ) );
        Assert.assertEquals( ( ( Integer )mbsc.invoke( stdMBeanName, "getFilterCacheThreshold", null, null ) ).intValue(), 10 );
    }


    @BeforeTestsOnce
    @Suite( groups = "prototypetest" )
    public void beforeFilterMemoryCacheResizeMBeanTestClassSetUp( )
        throws Exception
    {
        logger = LogFactory.getLog( FilterMemoryCacheResizeMBeanTest.class );

        // instantiate response validator MBean
        setupFilterManagerMBean( new String[] { "-ip", MBEAN_SERVER_IP, "-port", MBEAN_SERVER_PORT } );
    }


    @AfterTestsOnce
    @Suite( groups = "prototypetest" )
    public static void afterFilterMemoryCacheResizeMBeanTestClassTearDown( )
        throws Exception
    {
        // Close MBeanServer connection
        if ( jmxc != null ) {
            jmxc.close();
        }
    }


    private static void setupFilterManagerMBean( String[] args )
    {
        try
        {
            GetArgs opts = new GetArgs( FilterMemoryCacheResizeMBeanTest.class, args, "ip:port:user:password:shutdownNow", "ip:port", false );

            String ip = opts.getArg( "ip" );
            String port = opts.getArg( "port" );
            String user = opts.getArg( "user" );
            String password = opts.getArg( "password" );

            // Create an RMI connector client and connect it to the RMI connector server
            JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi" );

            // Need to test password against remote server
            Map<String, String> env = new HashMap<String, String>();
            String pkgs = "com.sun.enterprise.admin.jmx.remote.protocol";
            env.put( JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, pkgs );
            env.put( ADMIN_USER_ENV_PROPERTY_NAME, user );
            env.put( ADMIN_PASSWORD_ENV_PROPERTY_NAME, password );

            // Creates a connector client for the connector server at the given address. The resultant client is not
            // connected until its connect method is called.
            jmxc = JMXConnectorFactory.newJMXConnector( url, env );
            jmxc.connect();

            // Get an MBeanServerConnection
            mbsc = jmxc.getMBeanServerConnection();

            // Create FitlerManager MBean
            stdMBeanName = new ObjectName( FILTER_MANAGER_MBEAN_DOMAIN + FILTER_MANAGER_MBEAN_NAME );
            mbsc.getObjectInstance( stdMBeanName );
        }
        catch ( Exception e )
        {
            if ( e.getMessage().startsWith( "Failed to retrieve RMIServer stub" ) )
            {
                if ( logger.isErrorEnabled() )
                {
                    logger.error( "\nFailed to retrieve RMIServer stub.  Filter Manager not running at the specified location." );
                }
            }
            else
            {
                e.printStackTrace();
            }
        }
    }
}
