1 22 package org.jboss.system; 23 24 import java.util.ArrayList ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Set ; 28 29 import javax.management.InstanceNotFoundException ; 30 import javax.management.ListenerNotFoundException ; 31 import javax.management.MBeanServer ; 32 import javax.management.MBeanServerNotification ; 33 import javax.management.MalformedObjectNameException ; 34 import javax.management.Notification ; 35 import javax.management.NotificationFilter ; 36 import javax.management.NotificationFilterSupport ; 37 import javax.management.NotificationListener ; 38 import javax.management.ObjectName ; 39 40 import org.jboss.logging.Logger; 41 import org.jboss.mx.server.ServerConstants; 42 import org.w3c.dom.Element ; 43 import org.w3c.dom.Node ; 44 import org.w3c.dom.NodeList ; 45 46 108 public abstract class ListenerServiceMBeanSupport 109 extends ServiceMBeanSupport 110 implements ListenerServiceMBean, NotificationListener 111 { 112 114 115 private List sublist; 117 118 private Element xmllist; 120 121 private boolean dynamicSubscriptions; 122 123 124 private ObjectName listener; 125 126 127 private Object myHandback; 128 129 130 private NotificationFilterSupport myFilter; 131 132 133 private boolean subscribed; 134 135 137 140 public ListenerServiceMBeanSupport() 141 { 142 super(); 143 init(); 144 } 145 146 153 public ListenerServiceMBeanSupport(final Class type) 154 { 155 super(type); 156 init(); 157 } 158 159 166 public ListenerServiceMBeanSupport(final String category) 167 { 168 super(category); 169 init(); 170 } 171 172 179 public ListenerServiceMBeanSupport(final Logger log) 180 { 181 super(log); 182 init(); 183 } 184 185 187 194 public void setSubscriptionList(Element list) 195 { 196 this.xmllist = (Element )list.cloneNode(true); 199 } 200 201 203 public List <SubscriptionInfo> getSubscriptions() 204 { 205 return sublist; 206 } 207 208 public void setSubscriptions(List <SubscriptionInfo> list) 209 { 210 this.sublist = list; 211 } 212 213 219 public void subscribe(boolean dynamicSubscriptions) 220 throws Exception 221 { 222 subscribe(dynamicSubscriptions, this.getServiceName()); 223 } 224 225 232 public void subscribe(boolean dynamicSubscriptions, ObjectName listener) 233 throws Exception 234 { 235 if (this.xmllist != null && this.sublist == null) 237 { 238 log.debug("Parsing subscription specification"); 240 List subscriptionList = parseXMLSubscriptionSpec(this.xmllist); 241 242 subscribe(subscriptionList, dynamicSubscriptions, listener); 243 } 244 else if (this.sublist != null) 245 { 246 subscribe(sublist, dynamicSubscriptions, listener); 247 } 248 else 249 log.debug("Subscription specification not provided"); 250 } 251 252 260 public void subscribe(List subscriptionList, boolean dynamicSubscriptions, ObjectName listener) 261 throws Exception 262 { 263 if (subscribed) 265 return; 266 267 if (subscriptionList != null) 269 { 270 this.sublist = subscriptionList; 272 this.dynamicSubscriptions = dynamicSubscriptions; 273 this.listener = listener; 274 275 log.debug(this.sublist); 276 277 log.debug("Subscribing for JMX notifications" + 278 ", dynamic=" + dynamicSubscriptions + 279 (this.getServiceName().equals(listener) ? "" : 280 ", listener='" + listener + "'")); 281 282 bulkRegister(); 283 284 if (dynamicSubscriptions == true) 285 { 286 getServer().addNotificationListener( 288 new ObjectName (ServerConstants.MBEAN_SERVER_DELEGATE), 289 this.getServiceName(), 290 this.myFilter, 291 this.myHandback 292 ); 293 294 log.debug("Subscribed to MBeanServerDelegate, too"); 295 } 296 297 subscribed = true; 298 } 299 else 300 log.debug("Subscription list not provided"); 301 } 302 303 306 public void unsubscribe() 307 { 308 if (!subscribed) 310 return; 311 312 log.debug("Removing all JMX notification subscriptions"); 313 bulkUnregister(); 314 315 if (this.dynamicSubscriptions == true) 316 { 317 try { 319 getServer().removeNotificationListener( 320 new ObjectName (ServerConstants.MBEAN_SERVER_DELEGATE), 321 this.getServiceName(), 322 this.myFilter, 323 this.myHandback 324 ); 325 326 log.debug("Unsubscribed from MBeanServerDelegate, too"); 327 } 328 catch (MalformedObjectNameException e) 329 { 330 log.warn("Could not convert '" + ServerConstants.MBEAN_SERVER_DELEGATE 332 + "' to ObjectName", e); 333 } 334 catch (InstanceNotFoundException e) 335 { 336 log.warn("Could not unsubscribe from non-existent MBeanServerDelegate!", e); 338 } 339 catch (ListenerNotFoundException e) 340 { 341 log.warn("Could not unsubscribe from MBeanServerDelegate", e); 343 } 344 } 345 this.subscribed = false; 347 } 348 349 351 357 public void handleNotification(Notification notification, Object handback) 358 { 359 if (this.dynamicSubscriptions == true && handback == this.myHandback) 361 { 362 if (log.isTraceEnabled()) 363 log.trace("It's for me: " + notification + ", handback:" + handback); 364 365 String type = notification.getType(); 366 ObjectName target = null; 367 try { 368 target = ((MBeanServerNotification )notification).getMBeanName(); 369 } 370 catch (ClassCastException e) { 371 log.warn("MBeanServer sent unknown notification class type: " + 372 notification.getClass().getName()); 373 return; 374 } 375 376 if (type.equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) 377 { 378 Iterator i = this.sublist.iterator(); 380 381 while (i.hasNext()) 382 { 383 SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next(); 384 385 ObjectName objectName = mbeanInfo.getObjectName(); 386 387 try 388 { 389 if(objectName.apply(target)) 390 { 391 log.debug("ObjectName: '" + target + "' matched '" + objectName + "'"); 392 393 singleRegister( 395 this.getServer(), 396 target, 397 this.listener, 398 mbeanInfo.getFilter(), 399 mbeanInfo.getHandback() 400 ); 401 } 402 } 403 catch (Exception e) 404 { 405 log.warn("Caught exception from ObjectName.apply(" 408 + target + ")", e); 409 } 410 } 411 } 412 else 413 { 414 log.warn("Got unknown notification type from MBeanServerDelegate: " 415 + type); 416 } 417 } 418 else handleNotification2(notification, handback); 420 } 421 422 425 public void handleNotification2(Notification notification, Object handback) 426 { 427 } 429 430 432 435 private void init() 436 { 437 this.myHandback = new Integer (Integer.MAX_VALUE); 439 440 this.myFilter = new NotificationFilterSupport (); 442 this.myFilter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION); 443 } 444 445 448 private void singleRegister( 449 MBeanServer server, ObjectName target, ObjectName listener, 450 NotificationFilter filter, Object handback) 451 { 452 try 453 { 454 server.addNotificationListener(target, listener, filter, handback); 455 456 logSubscription(target, listener, handback, filter); 457 } 458 catch (InstanceNotFoundException e) 459 { 460 log.debug("Could not subscribe to: '" + target 462 + "', target or listener MBean not registered"); 463 } 464 catch (RuntimeException e) 465 { 466 log.warn("Failed to subscribe to: '" + target 467 + "', maybe not a notification broadcaster or: '" + listener 468 + "', maybe not a notification listener"); 469 } 470 } 471 472 475 private void singleUnregister( 476 MBeanServer server, ObjectName target, ObjectName listener, 477 NotificationFilter filter, Object handback) 478 { 479 try 480 { 481 server.removeNotificationListener(target, listener, filter, handback); 483 484 log.debug("Unsubscribed from: '" + target + "'"); 485 } 486 catch (InstanceNotFoundException e) 487 { 488 log.debug("Could not unsubscribe from non-existent: '" 490 + target + "'"); 491 } 492 catch (ListenerNotFoundException e) 493 { 494 log.debug("Could not unsubscribe from: '" + target + "'"); 497 } 498 catch (RuntimeException e) 499 { 500 log.debug("Could not unsubscribe from: '" + target + "'"); 502 } 503 } 504 505 508 private void bulkRegister() 509 { 510 Iterator i = this.sublist.iterator(); 512 513 MBeanServer server = this.getServer(); 515 516 while (i.hasNext()) 517 { 518 SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next(); 519 520 ObjectName objectName = mbeanInfo.getObjectName(); 521 Object handback = mbeanInfo.getHandback(); 522 NotificationFilter filter = mbeanInfo.getFilter(); 523 524 if (objectName.isPattern()) 525 { 526 Set mset = server.queryNames(objectName, null); 527 528 log.debug("ObjectName: '" + objectName + "' matched " + mset.size() + " MBean(s)"); 529 530 Iterator j = mset.iterator(); 531 while (j.hasNext()) 532 singleRegister(server, (ObjectName )j.next(), this.listener, 533 filter, handback); 534 } 535 else 536 singleRegister(server, objectName, this.listener, filter, handback); 537 } 538 } 539 540 543 private void bulkUnregister() 544 { 545 Iterator i = this.sublist.iterator(); 547 548 MBeanServer server = this.getServer(); 550 551 while (i.hasNext()) 552 { 553 SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next(); 554 555 ObjectName objectName = mbeanInfo.getObjectName(); 556 Object handback = mbeanInfo.getHandback(); 557 NotificationFilter filter = mbeanInfo.getFilter(); 558 559 if (objectName.isPattern()) 560 { 561 Set mset = server.queryNames(objectName, null); 562 563 log.debug("ObjectName: '" + objectName + "' matched " + mset.size() + " MBean(s)"); 564 565 Iterator j = mset.iterator(); 566 while (j.hasNext()) 567 singleUnregister(server, (ObjectName )j.next(), this.listener, 568 filter, handback); 569 } 570 else 571 singleUnregister(server, objectName, this.listener, filter, handback); 572 } 573 } 574 575 578 private void logSubscription( 579 ObjectName objectName, ObjectName listener, 580 Object handback, NotificationFilter filter) 581 { 582 StringBuffer sbuf = new StringBuffer (100); 583 584 sbuf.append("Subscribed to: { objectName='").append(objectName); 585 sbuf.append("', listener='").append(listener); 586 sbuf.append("', handback=").append(handback); 587 sbuf.append(", filter="); 588 sbuf.append(filter == null ? null : filter.toString()); 589 sbuf.append(" }"); 590 591 log.debug(sbuf.toString()); 592 } 593 594 597 private NotificationFilter createNotificationFilter(String factoryClass, Element filterConfig) 598 throws Exception 599 { 600 NotificationFilterFactory factory; 601 try 602 { 603 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass); 605 factory = (NotificationFilterFactory)clazz.newInstance(); 606 } 607 catch (Exception e) { 609 try 614 { 615 factoryClass = "org.jboss.system.filterfactory." + factoryClass; 616 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass); 617 factory = (NotificationFilterFactory)clazz.newInstance(); 618 } 619 catch (Exception inner) 620 { 621 throw e; 622 } 623 } 624 return factory.createNotificationFilter(filterConfig); 626 } 627 628 631 private ArrayList parseXMLSubscriptionSpec(Element root) 632 throws Exception 633 { 634 ArrayList slist = new ArrayList (); 635 636 if (!root.getNodeName().equals(SL_ROOT_ELEMENT)) 638 { 639 throw new Exception ("Expected '" + SL_ROOT_ELEMENT + "' element, " 640 + "got: " + "'" + root.getNodeName() + "'"); 641 } 642 else 643 { 644 NodeList rootlist = root.getChildNodes(); 645 646 for (int i = 0; i < rootlist.getLength(); i++) 647 { 648 Node mbean = rootlist.item(i); 650 651 if (mbean.getNodeName().equals(SL_MBEAN_ELEMENT)) 652 { 653 String name = null; 655 656 if (((Element )mbean).hasAttribute(SL_MBEAN_NAME_ATTRIBUTE)) 657 { 658 name = ((Element )mbean).getAttribute(SL_MBEAN_NAME_ATTRIBUTE); 659 } 660 else 661 { 662 throw new Exception ("'" + SL_MBEAN_ELEMENT + "' element must have a '" 663 + SL_MBEAN_NAME_ATTRIBUTE + "' attribute"); 664 } 665 666 String handback = null; 667 if (((Element )mbean).hasAttribute(SL_MBEAN_HANDBACK_ATTRIBUTE)) 668 { 669 handback = ((Element )mbean).getAttribute(SL_MBEAN_HANDBACK_ATTRIBUTE); 670 } 671 672 ObjectName objectName = new ObjectName (name); 675 676 NotificationFilter filter = null; 678 679 NodeList mbeanChildren = mbean.getChildNodes(); 680 681 for (int j = 0; j < mbeanChildren.getLength(); j++) 683 { 684 Node mbeanChildNode = mbeanChildren.item(j); 685 686 if (mbeanChildNode.getNodeName().equals(SL_FILTER_ELEMENT)) 688 { 689 String factory = null; 691 if (((Element )mbeanChildNode).hasAttribute(SL_FILTER_FACTORY_ATTRIBUTE)) 692 { 693 factory = ((Element )mbeanChildNode).getAttribute(SL_FILTER_FACTORY_ATTRIBUTE); 694 695 filter = createNotificationFilter(factory, (Element )mbeanChildNode); 697 break; 698 } 699 else 700 { 701 throw new Exception ("'" + SL_FILTER_ELEMENT + "' element must have a '" 702 + SL_FILTER_FACTORY_ATTRIBUTE + "' attribute"); 703 } 704 } 705 } 706 707 if (filter == null) 708 { 709 713 ArrayList tmplist = new ArrayList (mbeanChildren.getLength()); 716 717 for (int j = 0; j < mbeanChildren.getLength(); j++) 718 { 719 Node mbeanChildNode = mbeanChildren.item(j); 720 721 if (mbeanChildNode.getNodeName().equals(SL_NOTIFICATION_ELEMENT)) 723 { 724 String type = null; 726 if (((Element )mbeanChildNode).hasAttribute(SL_NOTIFICATION_TYPE_ATTRIBUTE)) 727 { 728 type = ((Element )mbeanChildNode).getAttribute(SL_NOTIFICATION_TYPE_ATTRIBUTE); 729 tmplist.add(type); 730 } 731 else 732 { 733 throw new Exception ("'" + SL_NOTIFICATION_ELEMENT + "' element must have a '" 734 + SL_NOTIFICATION_TYPE_ATTRIBUTE + "' attribute"); 735 } 736 } 737 } 738 if (tmplist.size() > 0) 740 { 741 NotificationFilterSupport sfilter = new NotificationFilterSupport (); 742 for (int j = 0; j < tmplist.size(); j++) 743 { 744 sfilter.enableType((String )tmplist.get(j)); 745 } 746 filter = sfilter; 747 } 748 } 749 slist.add(new SubscriptionInfo(objectName, handback, filter)); 750 } 751 } 752 } 753 return slist; 754 } 755 756 758 761 public static final class SubscriptionInfo 762 { 763 765 766 private ObjectName objectName; 767 768 769 private Object handback; 770 771 772 private NotificationFilter filter; 773 774 776 779 public SubscriptionInfo(ObjectName objectName, Object handback, NotificationFilter filter) 780 { 781 this.objectName = objectName; 782 this.handback = handback; 783 this.filter = filter; 784 } 785 786 790 public ObjectName getObjectName() 791 { 792 return this.objectName; 793 } 794 795 798 public Object getHandback() 799 { 800 return this.handback; 801 } 802 803 806 public NotificationFilter getFilter() 807 { 808 return this.filter; 809 } 810 811 814 public String toString() 815 { 816 StringBuffer sbuf = new StringBuffer (100); 817 818 sbuf.append("SubscriptionInfo { objectName='").append(this.objectName); 819 sbuf.append("', handback=").append(this.handback); 820 sbuf.append(", filter="); 821 sbuf.append(this.filter == null ? null : this.filter.toString()); 822 823 sbuf.append(" }"); 824 825 return sbuf.toString(); 826 } 827 } 828 } 829 | Popular Tags |