/*
* JBoss, Home of Professional Open Source
* Copyright 2007, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.managed.factory.test;

import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;

import junit.framework.Test;

import org.jboss.managed.api.ManagedObject;
import org.jboss.managed.api.ManagedOperation;
import org.jboss.managed.api.ManagedProperty;
import org.jboss.managed.api.annotation.ManagementComponent;
import org.jboss.managed.api.factory.ManagedObjectFactory;
import org.jboss.managed.plugins.ManagedOperationMatcher;
import org.jboss.managed.plugins.jmx.CompositeDataMetaValueBuilder;
import org.jboss.managed.plugins.jmx.ManagementFactoryUtils;
import org.jboss.metatype.api.types.SimpleMetaType;
import org.jboss.metatype.api.values.CompositeValue;
import org.jboss.metatype.api.values.MetaValue;
import org.jboss.metatype.api.values.MetaValueFactory;
import org.jboss.metatype.api.values.SimpleValue;
import org.jboss.metatype.api.values.SimpleValueSupport;
import org.jboss.test.managed.factory.AbstractManagedObjectFactoryTest;

/**
 * Tests of creating ManagedObjects for the jvm platform mbeans
 * 
 * @author Scott.Stark@jboss.org
 * @version $Revision: 1.1 $
 */
public class PlatformMBeanUnitTestCase extends AbstractManagedObjectFactoryTest
{
   /**
    * Create a testsuite for this test
    * 
    * @return the testsuite
    */
   public static Test suite()
   {
      return suite(PlatformMBeanUnitTestCase.class);
   }

   /**
    * Create a new ManagementObjectUnitTestCase.
    * 
    * @param name the test name
    */
   public PlatformMBeanUnitTestCase(String name)
   {
      super(name);
   }

   /**
    * Test the transformer value of the annotation
    */
   public void testClassLoadingMXBean()
   {
      super.enableTrace("org.jboss.managed.plugins.factory");
      ManagedObjectFactory mof = getMOF();
      ManagedObject mo = ManagementFactoryUtils.getClassLoadingMO(mof);
      assertNotNull(mo);
      assertEquals(ManagementFactory.CLASS_LOADING_MXBEAN_NAME, mo.getName());
      validateComponentType(mo);
      assertEquals(ManagementFactory.CLASS_LOADING_MXBEAN_NAME, mo.getComponentName());

      Map<String, ManagedProperty> props = mo.getProperties();
      assertNotNull(props);
      // totalLoadedClassCount
      ManagedProperty totalLoadedClassCount = props.get("totalLoadedClassCount");
      assertNotNull(totalLoadedClassCount);
      assertEquals(SimpleMetaType.LONG_PRIMITIVE, totalLoadedClassCount.getMetaType());
      assertEquals("the total number of classes loaded.", totalLoadedClassCount.getDescription());
      SimpleValue totalLoadedClassCountSV = SimpleValue.class.cast(totalLoadedClassCount.getValue());
      assertNotNull(totalLoadedClassCountSV);
      getLog().debug("totalLoadedClassCountSV"+totalLoadedClassCountSV);
      SimpleValue sv1 = SimpleValueSupport.wrap(new Long(100));
      assertTrue("> 100 classes loaded", sv1.compareTo(totalLoadedClassCountSV) < 0);
      // loadedClassCount
      ManagedProperty loadedClassCount = props.get("loadedClassCount");
      assertNotNull(loadedClassCount);
      assertEquals(SimpleMetaType.INTEGER_PRIMITIVE, loadedClassCount.getMetaType());
      assertEquals("the number of currently loaded classes.", loadedClassCount.getDescription());
      SimpleValue loadedClassCountSV = SimpleValue.class.cast(loadedClassCount.getValue());
      assertNotNull(loadedClassCountSV);
      getLog().debug("loadedClassCountSV"+loadedClassCountSV);
      assertTrue("> 100 classes loaded", sv1.compareTo(loadedClassCountSV) < 0);
      // unloadedClassCount
      ManagedProperty unloadedClassCount = props.get("unloadedClassCount");
      assertNotNull(unloadedClassCount);
      assertEquals(SimpleMetaType.LONG_PRIMITIVE, unloadedClassCount.getMetaType());
      assertEquals("the total number of unloaded classes.", unloadedClassCount.getDescription());
      SimpleValue unloadedClassCountSV = SimpleValue.class.cast(unloadedClassCount.getValue());
      assertNotNull(unloadedClassCountSV);
      getLog().debug("unloadedClassCountSV"+unloadedClassCountSV);
      // verbose
      ManagedProperty verbose = props.get("verbose");
      assertNotNull(verbose);
      assertEquals(SimpleMetaType.BOOLEAN_PRIMITIVE, verbose.getMetaType());
      assertEquals("the verbose output flag for the class loading system.", verbose.getDescription());
      SimpleValue verboseSV = SimpleValue.class.cast(verbose.getValue());
      assertNotNull(verboseSV);
      getLog().debug("verboseSV"+verboseSV);
      
   }

   public void testMemoryMXBean()
   {
      ManagedObjectFactory mof = getMOF();
      ManagedObject mo = ManagementFactoryUtils.getMemoryMXBean(mof);
      assertNotNull(mo);
      assertEquals(ManagementFactory.MEMORY_MXBEAN_NAME, mo.getName());
      validateComponentType(mo);

      Map<String, ManagedProperty> props = mo.getProperties();
      assertNotNull(props);

      // heapMemoryUsage
      ManagedProperty heapMemoryUsage = props.get("heapMemoryUsage");
      assertNotNull(heapMemoryUsage);
      assertEquals("object representing the heap memory usage.", heapMemoryUsage.getDescription());
      CompositeValue heapMemoryUsageMV = CompositeValue.class.cast(heapMemoryUsage.getValue());
      assertNotNull(heapMemoryUsageMV);
      getLog().debug("heapMemoryUsageMV; "+heapMemoryUsageMV);
      MemoryUsage heapMemoryUsageMU = ManagementFactoryUtils.unwrapMemoryUsage(heapMemoryUsageMV);
      assertTrue(heapMemoryUsageMU.getInit() >= 0);
      assertTrue(heapMemoryUsageMU.getUsed() >= 1000);
      assertTrue(heapMemoryUsageMU.getMax() >= heapMemoryUsageMU.getCommitted());
      assertTrue(heapMemoryUsageMU.getCommitted() >=  heapMemoryUsageMU.getUsed());

      // nonHeapMemoryUsage
      ManagedProperty nonHeapMemoryUsage = props.get("nonHeapMemoryUsage");
      assertNotNull(nonHeapMemoryUsage);
      assertEquals("object representing the non-heap memory usage.", nonHeapMemoryUsage.getDescription());
      CompositeValue nonHeapMemoryUsageMV = CompositeValue.class.cast(nonHeapMemoryUsage.getValue());
      assertNotNull(nonHeapMemoryUsageMV);
      getLog().debug("nonHeapMemoryUsageMV; "+nonHeapMemoryUsageMV);
      MemoryUsage nonHeapMemoryUsageMU = ManagementFactoryUtils.unwrapMemoryUsage(nonHeapMemoryUsageMV);
      assertTrue(nonHeapMemoryUsageMU.getInit() >= 0);
      assertTrue(nonHeapMemoryUsageMU.getUsed() >= 1000);
      assertTrue(nonHeapMemoryUsageMU.getMax() >= nonHeapMemoryUsageMU.getCommitted());
      assertTrue(nonHeapMemoryUsageMU.getCommitted() >=  nonHeapMemoryUsageMU.getUsed());
      // objectPendingFinalizationCount
      ManagedProperty objectPendingFinalizationCount = props.get("objectPendingFinalizationCount");
      assertNotNull(objectPendingFinalizationCount);
      assertEquals("the approximate number objects for which finalization is pending.", objectPendingFinalizationCount.getDescription());
      MetaValue objectPendingFinalizationCountMV = objectPendingFinalizationCount.getValue();
      assertNotNull(objectPendingFinalizationCountMV);
      getLog().debug("objectPendingFinalizationCountMV; "+objectPendingFinalizationCountMV);

      // verbose
      ManagedProperty verbose = props.get("verbose");
      assertNotNull(verbose);
      assertEquals(SimpleMetaType.BOOLEAN_PRIMITIVE, verbose.getMetaType());
      assertEquals("the verbose output flag for the memory system.", verbose.getDescription());
      SimpleValue verboseSV = SimpleValue.class.cast(verbose.getValue());
      assertNotNull(verboseSV);
      getLog().debug("verboseSV; "+verboseSV);

      // The gc op
      Set<ManagedOperation> ops = mo.getOperations();
      assertNotNull(ops);
      assertEquals("There is 1 op", 1, ops.size());
      ManagedOperation gc = ops.iterator().next();
      assertEquals("gc", gc.getName());
      assertEquals("Runs the garbage collector", gc.getDescription());
      gc.invoke();
   }

   public void testThreadMXBean()
      throws Exception
   {
      ManagedObjectFactory mof = getMOF();
      ManagedObject mo = ManagementFactoryUtils.getThreadMXBean(mof);
      assertNotNull(mo);
      assertEquals(ManagementFactory.THREAD_MXBEAN_NAME, mo.getName());
      validateComponentType(mo);
      
      ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
      long threadID = Thread.currentThread().getId();
      ThreadInfo threadInfo = mbean.getThreadInfo(threadID, 3);

      // Test ThreadInfo MetaValue wrap/unwrap
      MetaValueFactory metaValueFactory = MetaValueFactory.getInstance();
      CompositeDataMetaValueBuilder builder = new CompositeDataMetaValueBuilder();
      builder.setMetaValueFactory(metaValueFactory);
      metaValueFactory.setBuilder(CompositeData.class, builder);
      metaValueFactory.setBuilder(CompositeDataSupport.class, builder);

      MetaValue threadInfoMV = metaValueFactory.create(threadInfo);
      log.debug("ThreadInfo.MV: "+threadInfoMV);
      assertTrue(threadInfoMV instanceof CompositeValue);
      CompositeValue tiCV = CompositeValue.class.cast(threadInfoMV);
      ThreadInfo threadInfo2 = ManagementFactoryUtils.unwrapThreadInfo(tiCV);
      assertEquals(threadInfo.getLockOwnerName(), threadInfo2.getLockOwnerName());
      assertEquals(threadInfo.getThreadName(), threadInfo2.getThreadName());
      assertEquals(threadInfo.isInNative(), threadInfo2.isInNative());
      assertEquals(threadInfo.getBlockedCount(), threadInfo2.getBlockedCount());
      assertEquals(threadInfo.getBlockedTime(), threadInfo2.getBlockedTime());
      assertEquals(threadInfo.getLockOwnerId(), threadInfo2.getLockOwnerId());
      assertEquals(threadInfo.getThreadId(), threadInfo2.getThreadId());
      assertEquals(threadInfo.getThreadState(), threadInfo2.getThreadState());
      assertEquals(threadInfo.getWaitedCount(), threadInfo2.getWaitedCount());
      assertEquals(threadInfo.getWaitedTime(), threadInfo2.getWaitedTime());
      StackTraceElement[] st = threadInfo.getStackTrace();
      StackTraceElement[] st2 = threadInfo2.getStackTrace();
      for(int n = 0; n < st.length; n ++)
      {
         assertEquals(st[n], st2[n]);
      }

      // Properties
      ManagedProperty allThreadIds = mo.getProperty("allThreadIds");
      assertNotNull(allThreadIds);
      ManagedProperty currentThreadCpuTime = mo.getProperty("currentThreadCpuTime");
      assertNotNull(currentThreadCpuTime);
      long x = (Long) metaValueFactory.unwrap(currentThreadCpuTime.getValue());
      assertTrue(x > 1000);
      ManagedProperty currentThreadUserTime = mo.getProperty("currentThreadUserTime");
      assertNotNull(currentThreadUserTime);
      ManagedProperty daemonThreadCount = mo.getProperty("daemonThreadCount");
      assertNotNull(daemonThreadCount);
      x = (Integer) metaValueFactory.unwrap(daemonThreadCount.getValue());
      assertEquals(mbean.getDaemonThreadCount(), x);
      ManagedProperty peakThreadCount = mo.getProperty("peakThreadCount");
      assertNotNull(peakThreadCount);
      x = (Integer) metaValueFactory.unwrap(peakThreadCount.getValue());
      assertEquals(mbean.getPeakThreadCount(), x);
      ManagedProperty threadCount = mo.getProperty("threadCount");
      assertNotNull(threadCount);
      x = (Integer) metaValueFactory.unwrap(threadCount.getValue());
      assertEquals(mbean.getThreadCount(), x);
      ManagedProperty totalStartedThreadCount = mo.getProperty("totalStartedThreadCount");
      assertNotNull(totalStartedThreadCount);
      x = (Long) metaValueFactory.unwrap(totalStartedThreadCount.getValue());
      assertEquals(mbean.getTotalStartedThreadCount(), x);
      ManagedProperty currentThreadCpuTimeSupported = mo.getProperty("currentThreadCpuTimeSupported");
      assertNotNull(currentThreadCpuTimeSupported);
      boolean flag = (Boolean) metaValueFactory.unwrap(currentThreadCpuTimeSupported.getValue());
      assertEquals(mbean.isCurrentThreadCpuTimeSupported(), flag);
      ManagedProperty threadContentionMonitoringEnabled = mo.getProperty("threadContentionMonitoringEnabled");
      assertNotNull(threadContentionMonitoringEnabled);
      flag = (Boolean) metaValueFactory.unwrap(threadContentionMonitoringEnabled.getValue());
      assertEquals(mbean.isThreadContentionMonitoringEnabled(), flag);
      ManagedProperty threadContentionMonitoringSupported = mo.getProperty("threadContentionMonitoringSupported");
      assertNotNull(threadContentionMonitoringSupported);
      flag = (Boolean) metaValueFactory.unwrap(threadContentionMonitoringSupported.getValue());
      assertEquals(mbean.isThreadContentionMonitoringSupported(), flag);
      ManagedProperty threadCpuTimeEnabled = mo.getProperty("threadCpuTimeEnabled");
      assertNotNull(threadCpuTimeEnabled);
      flag = (Boolean) metaValueFactory.unwrap(threadCpuTimeEnabled.getValue());
      assertEquals(mbean.isThreadCpuTimeEnabled(), flag);
      ManagedProperty threadCpuTimeSupported = mo.getProperty("threadCpuTimeSupported");
      assertNotNull(threadCpuTimeSupported);
      flag = (Boolean) metaValueFactory.unwrap(threadCpuTimeSupported.getValue());
      assertEquals(mbean.isThreadCpuTimeSupported(), flag);

      // Ops
      Set<ManagedOperation> ops = mo.getOperations();
      log.debug(ops);

      assertEquals("Ops count is 8", 8, ops.size());
      ManagedOperation getThreadInfo = ManagedOperationMatcher.findOperation(ops,
            "getThreadInfo", SimpleMetaType.LONG_PRIMITIVE, SimpleMetaType.INTEGER_PRIMITIVE);
      assertNotNull("getThreadInfo", getThreadInfo);
      log.debug(getThreadInfo);
      String[] getThreadInfoSig = getThreadInfo.getReflectionSignature();
      String[] getThreadInfoSigExpected = {"long", "int"};
      assertEquals(Arrays.asList(getThreadInfoSigExpected), Arrays.asList(getThreadInfoSig));
      ManagedOperation resetPeakThreadCount = ManagedOperationMatcher.findOperation(ops,
            "resetPeakThreadCount");
      assertNotNull("resetPeakThreadCount", resetPeakThreadCount);
      assertEquals(0, resetPeakThreadCount.getReflectionSignature().length);

      MBeanServer server = ManagementFactory.getPlatformMBeanServer();
      ObjectName tname = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
      MBeanInfo tinfo = server.getMBeanInfo(tname);
      MBeanOperationInfo[] tops = tinfo.getOperations();
      String javaSpecVersion = System.getProperty("java.specification.version");
      if (javaSpecVersion.equals("1.5") || javaSpecVersion.equals("5.0"))
         assertEquals(8, tops.length);
      else if (javaSpecVersion.equals("1.6") || javaSpecVersion.equals("6.0"))
         assertEquals(11, tops.length);
      for(MBeanOperationInfo op : tops)
      {
         MBeanParameterInfo[] params = op.getSignature();
         String sig = "";
         if(params != null)
         {
            for(MBeanParameterInfo param : params)
            {
               if(sig.length() > 0)
                  sig += ",";
               sig += param.getType();
            }
         }
         log.debug(op.getName()+"("+sig+")");
      }
      Object[] params = {threadID};
      String[] signature = {"long"};
      Object result = server.invoke(tname, "getThreadInfo", params, signature);
      threadInfo = mbean.getThreadInfo(threadID);
      log.debug("getThreadInfo()-OpenType: "+result);
      assertTrue(result instanceof CompositeDataSupport);
      MetaValue resultMV = metaValueFactory.create(result);
      assertTrue(resultMV instanceof CompositeValue);
      CompositeValue resultCV = (CompositeValue) resultMV;
      log.debug("getThreadInfo()-MetaType: "+resultCV);
      
      ThreadInfo resultTI = ManagementFactoryUtils.unwrapThreadInfo(resultCV);
      threadInfo2 = resultTI;
      assertEquals(threadInfo.getLockOwnerName(), threadInfo2.getLockOwnerName());
      assertEquals(threadInfo.getThreadName(), threadInfo2.getThreadName());
      assertEquals(threadInfo.isInNative(), threadInfo2.isInNative());
      assertEquals(threadInfo.getBlockedCount(), threadInfo2.getBlockedCount());
      assertEquals(threadInfo.getBlockedTime(), threadInfo2.getBlockedTime());
      assertEquals(threadInfo.getLockOwnerId(), threadInfo2.getLockOwnerId());
      assertEquals(threadInfo.getThreadId(), threadInfo2.getThreadId());
      assertEquals(threadInfo.getThreadState(), threadInfo2.getThreadState());
      assertEquals(threadInfo.getWaitedCount(), threadInfo2.getWaitedCount());
      assertEquals(threadInfo.getWaitedTime(), threadInfo2.getWaitedTime());
      st = threadInfo.getStackTrace();
      st2 = threadInfo2.getStackTrace();
      for(int n = 0; n < st.length; n ++)
      {
         assertEquals(st[n], st2[n]);
      }

   }

   public void testRuntimeMXBean()
   {
      ManagedObjectFactory mof = getMOF();
      ManagedObject mo = ManagementFactoryUtils.getRuntimeMXBean(mof);
      assertNotNull(mo);
      assertEquals(ManagementFactory.RUNTIME_MXBEAN_NAME, mo.getName());
      validateComponentType(mo);

      RuntimeMXBean mbean = ManagementFactory.getRuntimeMXBean();
      MetaValueFactory metaValueFactory = MetaValueFactory.getInstance();
      
      ManagedProperty bootClassPath = mo.getProperty("bootClassPath");
      String x = (String) metaValueFactory.unwrap(bootClassPath.getValue());
      assertEquals(mbean.getBootClassPath(), x);
      ManagedProperty classPath = mo.getProperty("classPath");
      x = (String) metaValueFactory.unwrap(classPath.getValue());
      assertEquals(mbean.getClassPath(), x);
      ManagedProperty libraryPath = mo.getProperty("libraryPath");
      x = (String) metaValueFactory.unwrap(libraryPath.getValue());
      assertEquals(mbean.getLibraryPath(), x);      
      ManagedProperty managementSpecVersion = mo.getProperty("managementSpecVersion");
      x = (String) metaValueFactory.unwrap(managementSpecVersion.getValue());
      assertEquals(mbean.getManagementSpecVersion(), x);      
      ManagedProperty specName = mo.getProperty("specName");
      x = (String) metaValueFactory.unwrap(specName.getValue());
      assertEquals(mbean.getSpecName(), x);      
      ManagedProperty specVendor = mo.getProperty("specVendor");
      x = (String) metaValueFactory.unwrap(specVendor.getValue());
      assertEquals(mbean.getSpecVendor(), x);      
      ManagedProperty specVersion = mo.getProperty("specVersion");
      x = (String) metaValueFactory.unwrap(specVersion.getValue());
      assertEquals(mbean.getSpecVersion(), x);      
      ManagedProperty vmName = mo.getProperty("vmName");
      x = (String) metaValueFactory.unwrap(vmName.getValue());
      assertEquals(mbean.getVmName(), x);      
      ManagedProperty vmVendor = mo.getProperty("vmVendor");
      x = (String) metaValueFactory.unwrap(vmVendor.getValue());
      assertEquals(mbean.getVmVendor(), x);      
      ManagedProperty vmVersion = mo.getProperty("vmVersion");
      x = (String) metaValueFactory.unwrap(vmVersion.getValue());
      assertEquals(mbean.getVmVersion(), x);
      ManagedProperty startTime = mo.getProperty("startTime");
      long time = (Long) metaValueFactory.unwrap(startTime.getValue());
      assertEquals(mbean.getStartTime(), time);
      ManagedProperty uptime = mo.getProperty("uptime");
      time = (Long) metaValueFactory.unwrap(uptime.getValue());
      ManagedProperty inputArguments = mo.getProperty("inputArguments");
      List<String> ls = (List<String>) metaValueFactory.unwrap(inputArguments.getValue());
      List<String> args = mbean.getInputArguments();
      assertEquals(args, ls);
      ManagedProperty systemProperties = mo.getProperty("systemProperties");
      Map<String, String> map = (Map<String, String>) metaValueFactory.unwrap(systemProperties.getValue());
      log.info("sun.io.unicode.encoding: "+map.get("sun.io.unicode.encoding"));
      Map<String, String> sysProps = mbean.getSystemProperties();
      for(String key : sysProps.keySet())
      {
         String p1 = sysProps.get(key);
         String p2 = map.get(key);
         // TODO: some properties are missing?
         // assertEquals(key, p1, p2);
      }
   }
   public void testOperatingSystemMXBean()
   {
      ManagedObjectFactory mof = getMOF();
      ManagedObject mo = ManagementFactoryUtils.getOperatingSystemMXBean(mof);
      assertNotNull(mo);
      assertEquals(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, mo.getName());
      validateComponentType(mo);

      ManagedProperty arch = mo.getProperty("arch");
      assertNotNull(arch);
      ManagedProperty availableProcessors = mo.getProperty("availableProcessors");
      assertNotNull(availableProcessors);
      SimpleValue procsSV = (SimpleValue) availableProcessors.getValue();
      Integer procs = (Integer) procsSV.getValue();
      assertTrue(procs.intValue() >= 1);
      ManagedProperty version = mo.getProperty("version");
      assertNotNull(version);
      log.debug(version.getValue());
   }
   public void testMemoryManagerMXBeans()
   {
      ManagedObjectFactory mof = getMOF();
      List<ManagedObject> mos = ManagementFactoryUtils.getMemoryManagerMXBeans(mof);
      assertTrue(mos.size() > 0);
      for(ManagedObject mo : mos)
      {
         ManagedProperty nameMP = mo.getProperty("name");
         SimpleValue nameSV = SimpleValue.class.cast(nameMP.getValue());
         String nameString = nameSV.getValue().toString();
         String name = ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + nameString;
         assertEquals(name, mo.getName());
         validateComponentType(mo);
      }
   }
   public void testMemoryPoolMXBeans()
   {
      ManagedObjectFactory mof = getMOF();
      List<ManagedObject> mos = ManagementFactoryUtils.getMemoryPoolMXBeans(mof);
      assertTrue(mos.size() > 0);
      for(ManagedObject mo : mos)
      {
         ManagedProperty nameMP = mo.getProperty("name");
         SimpleValue nameSV = SimpleValue.class.cast(nameMP.getValue());
         String nameString = nameSV.getValue().toString();
         String name = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + nameString;
         assertEquals(name, mo.getName());
         validateComponentType(mo);
      }
   }
   public void testGarbageCollectorMXBeans()
   {
      ManagedObjectFactory mof = getMOF();
      List<ManagedObject> mos = ManagementFactoryUtils.getGarbageCollectorMXBeans(mof);
      assertTrue(mos.size() > 0);
      for(ManagedObject mo : mos)
      {
         log.debug("GC.MO.props: "+mo.getPropertyNames());
         ManagedProperty nameMP = mo.getProperty("name");
         SimpleValue nameSV = SimpleValue.class.cast(nameMP.getValue());
         String nameString = nameSV.getValue().toString();
         String name = ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + nameString;
         assertEquals(name, mo.getName());
         validateComponentType(mo);
      }
   }

   protected void validateComponentType(ManagedObject mo)
   {
      Map<String, Annotation> moAnns = mo.getAnnotations();
      assertNotNull(moAnns);
      ManagementComponent mc = (ManagementComponent) moAnns.get(ManagementComponent.class.getName());
      assertNotNull(mc);
      assertEquals("MBean", mc.type());
      assertEquals("Platform", mc.subtype());      
   }

   static class X
   {
      public int m0(int i)
      {
         return 0;
      }
      public Integer m1(Integer i)
      {
         return 0;
      }
   }

}
