1: 
  37: 
  38: package ;
  39: 
  40: import ;
  41: 
  42: import ;
  43: import ;
  44: import ;
  45: import ;
  46: import ;
  47: import ;
  48: import ;
  49: import ;
  50: import ;
  51: 
  52: import ;
  53: 
  54: import ;
  55: import ;
  56: import ;
  57: 
  58: import ;
  59: import ;
  60: import ;
  61: import ;
  62: import ;
  63: 
  64: import ;
  65: 
  66: import ;
  67: import ;
  68: import ;
  69: import ;
  70: import ;
  71: import ;
  72: import ;
  73: import ;
  74: import ;
  75: import ;
  76: import ;
  77: import ;
  78: 
  79: import ;
  80: import ;
  81: 
  82: 
 147: public class ManagementFactory
 148: {
 149: 
 150:   
 153:   public static final String CLASS_LOADING_MXBEAN_NAME =
 154:     "java.lang:type=ClassLoading";
 155: 
 156:   
 159:   public static final String COMPILATION_MXBEAN_NAME =
 160:     "java.lang:type=Compilation";
 161: 
 162:   
 165:   public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE =
 166:     "java.lang:type=GarbageCollector";
 167: 
 168:   
 171:   public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE =
 172:     "java.lang:type=MemoryManager";
 173: 
 174:   
 177:   public static final String MEMORY_MXBEAN_NAME =
 178:     "java.lang:type=Memory";
 179: 
 180:   
 183:   public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE =
 184:     "java.lang:type=MemoryPool";
 185: 
 186:   
 189:   public static final String OPERATING_SYSTEM_MXBEAN_NAME =
 190:     "java.lang:type=OperatingSystem";
 191: 
 192:   
 195:   public static final String RUNTIME_MXBEAN_NAME =
 196:     "java.lang:type=Runtime";
 197: 
 198:   
 201:   public static final String THREAD_MXBEAN_NAME =
 202:     "java.lang:type=Threading";
 203: 
 204:   
 207:   private static OperatingSystemMXBean osBean;
 208: 
 209:   
 212:   private static RuntimeMXBean runtimeBean;
 213: 
 214:   
 217:   private static ClassLoadingMXBean classLoadingBean;
 218: 
 219:   
 222:   private static ThreadMXBean threadBean;
 223: 
 224:   
 227:   private static MemoryMXBean memoryBean;
 228: 
 229:   
 232:   private static CompilationMXBean compilationBean;
 233: 
 234:   
 237:   private static MBeanServer platformServer;
 238: 
 239:   
 242:   private ManagementFactory() {}
 243: 
 244:   
 251:   public static OperatingSystemMXBean getOperatingSystemMXBean()
 252:   {
 253:     if (osBean == null)
 254:       try 
 255:     {
 256:       osBean = new OperatingSystemMXBeanImpl();
 257:     }
 258:       catch (NotCompliantMBeanException e)
 259:     {
 260:       throw new InternalError("The GNU implementation of the " +
 261:                   "operating system bean is not a " +
 262:                   "compliant management bean.");
 263:     }
 264:     return osBean;
 265:   }
 266: 
 267:   
 274:   public static RuntimeMXBean getRuntimeMXBean()
 275:   {
 276:     if (runtimeBean == null)
 277:       try
 278:     {
 279:       runtimeBean = new RuntimeMXBeanImpl();
 280:     }
 281:       catch (NotCompliantMBeanException e)
 282:     {
 283:       throw new InternalError("The GNU implementation of the " +
 284:                   "runtime bean is not a compliant " +
 285:                   "management bean.");
 286:     }
 287:     return runtimeBean;
 288:   }
 289: 
 290:   
 297:   public static ClassLoadingMXBean getClassLoadingMXBean()
 298:   {
 299:     if (classLoadingBean == null)
 300:       try
 301:     {
 302:       classLoadingBean = new ClassLoadingMXBeanImpl();
 303:     }
 304:       catch (NotCompliantMBeanException e)
 305:     {
 306:       throw new InternalError("The GNU implementation of the " +
 307:                   "class loading bean is not a " +
 308:                   "compliant management bean.");
 309:     }
 310:     return classLoadingBean;
 311:   }
 312: 
 313:   
 320:   public static ThreadMXBean getThreadMXBean()
 321:   {
 322:     if (threadBean == null)
 323:       try
 324:     {
 325:       threadBean = new ThreadMXBeanImpl();
 326:     }
 327:       catch (NotCompliantMBeanException e)
 328:     {
 329:       throw new InternalError("The GNU implementation of the " +
 330:                   "thread bean is not a compliant " +
 331:                   "management bean.");
 332:     }
 333:     return threadBean;
 334:   }
 335: 
 336:   
 343:   public static MemoryMXBean getMemoryMXBean()
 344:   {
 345:     if (memoryBean == null)
 346:       try
 347:     {
 348:       memoryBean = new MemoryMXBeanImpl();
 349:     }
 350:       catch (NotCompliantMBeanException e)
 351:     {
 352:       throw new InternalError("The GNU implementation of the " +
 353:                   "memory bean is not a compliant " +
 354:                   "management bean.");
 355:     }
 356:     return memoryBean;
 357:   }
 358: 
 359:   
 369:   public static CompilationMXBean getCompilationMXBean()
 370:   {
 371:     if (compilationBean == null &&
 372:     SystemProperties.getProperty("gnu.java.compiler.name") != null)
 373:       try
 374:     {
 375:       compilationBean = new CompilationMXBeanImpl();
 376:     }
 377:       catch (NotCompliantMBeanException e)
 378:     {
 379:       throw new InternalError("The GNU implementation of the " +
 380:                   "compilation bean is not a compliant " +
 381:                   "management bean.");
 382:     }
 383:     return compilationBean;
 384:   }
 385: 
 386:   
 393:   public static List<MemoryPoolMXBean> getMemoryPoolMXBeans()
 394:   {
 395:     List<MemoryPoolMXBean> poolBeans =
 396:       new ArrayList<MemoryPoolMXBean>();
 397:     String[] names = VMManagementFactory.getMemoryPoolNames();
 398:     for (int a = 0; a < names.length; ++a)
 399:       try
 400:     {
 401:       poolBeans.add(new MemoryPoolMXBeanImpl(names[a]));
 402:     }
 403:       catch (NotCompliantMBeanException e)
 404:     {
 405:       throw new InternalError("The GNU implementation of the " +
 406:                   "memory pool bean, " + a + ", is " +
 407:                   "not a compliant management bean.");
 408:     }
 409:     return poolBeans;
 410:   }
 411: 
 412:   
 419:   public static List<MemoryManagerMXBean> getMemoryManagerMXBeans()
 420:   {
 421:     List<MemoryManagerMXBean> managerBeans =
 422:       new ArrayList<MemoryManagerMXBean>();
 423:     String[] names = VMManagementFactory.getMemoryManagerNames();
 424:     for (int a = 0; a < names.length; ++a)
 425:       try
 426:     {
 427:       managerBeans.add(new MemoryManagerMXBeanImpl(names[a]));
 428:     }
 429:       catch (NotCompliantMBeanException e)
 430:     {
 431:       throw new InternalError("The GNU implementation of the " +
 432:                   "memory manager bean, " + a + ", is " +
 433:                   "not a compliant management bean.");
 434:     }
 435:     managerBeans.addAll(getGarbageCollectorMXBeans());
 436:     return managerBeans;
 437:   }
 438: 
 439:   
 446:   public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans()
 447:   {
 448:     List<GarbageCollectorMXBean> gcBeans =
 449:       new ArrayList<GarbageCollectorMXBean>();
 450:     String[] names = VMManagementFactory.getGarbageCollectorNames();
 451:     for (int a = 0; a < names.length; ++a)
 452:       try
 453:     {
 454:       gcBeans.add(new GarbageCollectorMXBeanImpl(names[a]));
 455:     }
 456:       catch (NotCompliantMBeanException e)
 457:     {
 458:       throw new InternalError("The GNU implementation of the " +
 459:                   "garbage collector bean, " + a + 
 460:                   ", is not a compliant management " +
 461:                   "bean.");
 462:     }
 463:     return gcBeans;
 464:   }
 465: 
 466:   
 489:   public static MBeanServer getPlatformMBeanServer()
 490:   {
 491:     if (platformServer == null)
 492:       {
 493:     platformServer = MBeanServerFactory.createMBeanServer();
 494:     try
 495:       {
 496:         platformServer.registerMBean(getOperatingSystemMXBean(),
 497:                      new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME));
 498:         platformServer.registerMBean(getRuntimeMXBean(),
 499:                      new ObjectName(RUNTIME_MXBEAN_NAME));
 500:         platformServer.registerMBean(getClassLoadingMXBean(),
 501:                      new ObjectName(CLASS_LOADING_MXBEAN_NAME));
 502:         platformServer.registerMBean(getThreadMXBean(),
 503:                      new ObjectName(THREAD_MXBEAN_NAME));
 504:         platformServer.registerMBean(getMemoryMXBean(),
 505:                      new ObjectName(MEMORY_MXBEAN_NAME));
 506:         CompilationMXBean compBean = getCompilationMXBean();
 507:         if (compBean != null)
 508:           platformServer.registerMBean(compBean,
 509:                        new ObjectName(COMPILATION_MXBEAN_NAME));
 510:         Iterator beans = getMemoryPoolMXBeans().iterator();
 511:         while (beans.hasNext())
 512:           {
 513:         MemoryPoolMXBean bean = (MemoryPoolMXBean) beans.next();
 514:         platformServer.registerMBean(bean,
 515:                          new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE +
 516:                                 ",name=" +
 517:                                 bean.getName()));
 518:           }
 519:         beans = getMemoryManagerMXBeans().iterator();
 520:         while (beans.hasNext())
 521:           {
 522:         MemoryManagerMXBean bean = (MemoryManagerMXBean) beans.next();
 523:         platformServer.registerMBean(bean,
 524:                          new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE +
 525:                                 ",name=" +
 526:                                 bean.getName()));
 527:           }
 528:         beans = getGarbageCollectorMXBeans().iterator();
 529:         while (beans.hasNext())
 530:           {
 531:         GarbageCollectorMXBean bean = (GarbageCollectorMXBean) beans.next();
 532:         platformServer.registerMBean(bean,
 533:                          new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE +
 534:                                 ",name=" +
 535:                                 bean.getName()));
 536:           }
 537:         platformServer.registerMBean(LogManager.getLoggingMXBean(),
 538:                      new ObjectName(LogManager.LOGGING_MXBEAN_NAME));
 539:       }
 540:     catch (InstanceAlreadyExistsException e)
 541:       {
 542:         throw (Error) 
 543:           (new InternalError("One of the management beans is " +
 544:                  "already registered.").initCause(e));
 545:       }
 546:     catch (MBeanRegistrationException e)
 547:       {
 548:         throw (Error) 
 549:           (new InternalError("One of the management beans' preRegister " +
 550:                  "methods threw an exception.").initCause(e));
 551:       }
 552:     catch (NotCompliantMBeanException e)
 553:       {
 554:         throw (Error) 
 555:           (new InternalError("One of the management beans is " +
 556:                  "not compliant.").initCause(e));
 557:       }
 558:     catch (MalformedObjectNameException e)
 559:       {
 560:         throw (Error) 
 561:           (new InternalError("The object name of a management bean is " +
 562:                  "not compliant.").initCause(e));
 563:       }
 564:       }
 565:     return platformServer;
 566:   }
 567: 
 568:   
 602:   public static <T> T newPlatformMXBeanProxy(MBeanServerConnection connection,
 603:                          String mxbeanName,
 604:                          Class<T> mxbeanInterface)
 605:     throws IOException
 606:   {
 607:     if (!(mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) ||
 608:       mxbeanName.equals(COMPILATION_MXBEAN_NAME) ||
 609:       mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) ||
 610:       mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) ||
 611:       mxbeanName.equals(MEMORY_MXBEAN_NAME) ||
 612:       mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) ||
 613:       mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) ||
 614:       mxbeanName.equals(RUNTIME_MXBEAN_NAME) ||
 615:       mxbeanName.equals(THREAD_MXBEAN_NAME)))
 616:       {
 617:     throw new IllegalArgumentException("The named bean, " + mxbeanName +
 618:                        ", is not a platform name.");
 619:       }
 620:     if ((mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) &&
 621:      mxbeanInterface != ClassLoadingMXBean.class) ||
 622:     (mxbeanName.equals(COMPILATION_MXBEAN_NAME) &&
 623:      mxbeanInterface != CompilationMXBean.class) ||
 624:     (mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) &&
 625:      mxbeanInterface != GarbageCollectorMXBean.class) ||
 626:     (mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) &&
 627:      mxbeanInterface != MemoryManagerMXBean.class) ||
 628:     (mxbeanName.equals(MEMORY_MXBEAN_NAME) &&
 629:      mxbeanInterface != MemoryMXBean.class) ||
 630:     (mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) &&
 631:      mxbeanInterface != MemoryPoolMXBean.class) ||
 632:     (mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) &&
 633:      mxbeanInterface != OperatingSystemMXBean.class) ||
 634:     (mxbeanName.equals(RUNTIME_MXBEAN_NAME) &&
 635:      mxbeanInterface != RuntimeMXBean.class) ||
 636:     (mxbeanName.equals(THREAD_MXBEAN_NAME) &&
 637:      mxbeanInterface != ThreadMXBean.class))
 638:       throw new IllegalArgumentException("The interface, " + mxbeanInterface +
 639:                      ", does not match the bean, " + mxbeanName);
 640:     ObjectName bean;
 641:     try
 642:       {
 643:     bean = new ObjectName(mxbeanName);
 644:       }
 645:     catch (MalformedObjectNameException e)
 646:       {
 647:     throw new IllegalArgumentException("The named bean is invalid.");
 648:       }
 649:     if (!(connection.isRegistered(bean)))
 650:       throw new IllegalArgumentException("The bean is not registered on this connection.");
 651:     Class[] interfaces;
 652:     if (mxbeanName.equals(MEMORY_MXBEAN_NAME))
 653:       interfaces = new Class[] { mxbeanInterface, NotificationEmitter.class };
 654:     else
 655:       interfaces = new Class[] { mxbeanInterface };
 656:     return (T) Proxy.newProxyInstance(mxbeanInterface.getClassLoader(),
 657:                       interfaces,
 658:                       new ManagementInvocationHandler(connection, bean));
 659:   }
 660: 
 661:   
 669:   private static class ManagementInvocationHandler
 670:     implements InvocationHandler
 671:   {
 672: 
 673:     
 676:     private MBeanServerConnection conn;
 677: 
 678:     
 681:     private ObjectName bean;
 682: 
 683:     
 690:     public ManagementInvocationHandler(MBeanServerConnection conn,
 691:                        ObjectName bean)
 692:       throws IOException
 693:     {
 694:       this.conn = conn;
 695:       this.bean = bean;
 696:     }
 697: 
 698:     
 713:     public Object invoke(Object proxy, Method method, Object[] args)
 714:       throws Throwable
 715:     {
 716:       String name = method.getName();
 717:       if (name.equals("toString"))
 718:     return "Proxy for " + bean + " using " + conn;
 719:       if (name.equals("addNotificationListener"))
 720:     {
 721:       conn.addNotificationListener(bean,
 722:                        (NotificationListener) args[0],
 723:                        (NotificationFilter) args[1],
 724:                        args[2]);
 725:       return null;
 726:     }
 727:       if (name.equals("getNotificationInfo"))
 728:     return conn.getMBeanInfo(bean).getNotifications();
 729:       if (name.equals("removeNotificationListener"))
 730:     {
 731:       if (args.length == 1)
 732:         conn.removeNotificationListener(bean, 
 733:                         (NotificationListener)
 734:                         args[0]);
 735:       else
 736:         conn.removeNotificationListener(bean, 
 737:                         (NotificationListener)
 738:                         args[0],
 739:                         (NotificationFilter)
 740:                         args[1], args[2]);
 741:       return null;
 742:     }
 743:       String attrib = null;
 744:       if (name.startsWith("get"))
 745:     attrib = name.substring(3);
 746:       else if (name.startsWith("is"))
 747:     attrib = name.substring(2);
 748:       if (attrib != null)
 749:     return translate(conn.getAttribute(bean, attrib), method);
 750:       else if (name.startsWith("set"))
 751:     {
 752:       conn.setAttribute(bean, new Attribute(name.substring(3),
 753:                         args[0]));
 754:       return null;
 755:     }
 756:       else
 757:     return translate(conn.invoke(bean, name, args, null), method);
 758:     }
 759: 
 760:     
 770:     private final Object translate(Object otype, Method method)
 771:       throws Throwable
 772:     {
 773:       Class<?> returnType = method.getReturnType();
 774:       if (returnType.isEnum())
 775:     {
 776:       String ename = (String) otype;
 777:       Enum[] constants = (Enum[]) returnType.getEnumConstants();
 778:       for (Enum c : constants)
 779:         if (c.name().equals(ename))
 780:           return c;
 781:     }
 782:       if (List.class.isAssignableFrom(returnType))
 783:     {
 784:       Object[] elems = (Object[]) otype;
 785:       List l = new ArrayList(elems.length);
 786:       for (Object elem : elems)
 787:         l.add(elem);
 788:       return l;
 789:     }
 790:       if (Map.class.isAssignableFrom(returnType))
 791:     {
 792:       TabularData data = (TabularData) otype;
 793:       Map m = new HashMap(data.size());
 794:       for (Object val : data.values())
 795:         {
 796:           CompositeData vals = (CompositeData) val;
 797:           m.put(vals.get("key"), vals.get("value"));
 798:         }
 799:       return m;
 800:     }
 801:       try
 802:     {
 803:       Method m = returnType.getMethod("from",
 804:                       new Class[]
 805:         { CompositeData.class });
 806:       return m.invoke(null, (CompositeData) otype);
 807:     }
 808:       catch (NoSuchMethodException e)
 809:     {
 810:       
 812:     }
 813:       return otype;
 814:     }
 815: 
 816:   }
 817: }