KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > system > ListenerServiceMBeanSupport


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

22 package org.jboss.system;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import javax.management.InstanceNotFoundException JavaDoc;
30 import javax.management.ListenerNotFoundException JavaDoc;
31 import javax.management.MBeanServer JavaDoc;
32 import javax.management.MBeanServerNotification JavaDoc;
33 import javax.management.MalformedObjectNameException JavaDoc;
34 import javax.management.Notification JavaDoc;
35 import javax.management.NotificationFilter JavaDoc;
36 import javax.management.NotificationFilterSupport JavaDoc;
37 import javax.management.NotificationListener JavaDoc;
38 import javax.management.ObjectName JavaDoc;
39
40 import org.jboss.logging.Logger;
41 import org.jboss.mx.server.ServerConstants;
42 import org.w3c.dom.Element JavaDoc;
43 import org.w3c.dom.Node JavaDoc;
44 import org.w3c.dom.NodeList JavaDoc;
45
46 /**
47  * An abstract base class that provides for declarative JMX notification
48  * subscription handling.
49  * <p>
50  * A JBoss service that is in addition a NotificationListener can
51  * subclass ListenerServiceMBeanSupport instead of ServiceMBeanSupport
52  * and specify at run-time, inline in the MBean descriptor using the
53  * SubscriptionList attribute, the set of MBeans/notifications the
54  * service wants to subscribe/receive.
55  * <p>
56  * Call subscribe(boolean dynamicSubscriptions) at anytime to register to
57  * those MBeans and for those notifications that match the specified criteria.
58  * Call unsubscribe() to unsubscribe for Notifications.
59  * <p>
60  * If true is passed to subscribe() the baseclass will monitor for
61  * registration events from the MBeanServer and automatically subscribe
62  * to new instances of MBeans that match the subscription criteria.
63  * Monitoring for unsubscribe events in not necessary, since the MBeanServer
64  * automatically removes subscriptions to unregistering MBeans.
65  * <p>
66  * An alternative subscribe(boolean dynamicSubscription, ObjectName listener)
67  * can be used to specify a different MBean as the receiver of the
68  * subscribed notifications. The specified MBean must be a NotificationListener.
69  * <p>
70  * To handle the incoming notifications override the handleNotification2()
71  * method. The usual handleNotification() method should not be overriden,
72  * since it is used to monitor the incoming notifications for registration
73  * events coming from the MBeanServer, before delegating to
74  * handleNotification2(), in order to implement dynamic subscriptions.
75  *
76  * @see ListenerServiceMBean
77  * @see NotificationFilterFactory
78  *
79  * REVISIONS
80  * =========
81  * 14/03/05, dimitris
82  * The filter mechanism has been extended to support specification
83  * of arbitrary filters, using dynamic filter factory plugins
84  * implementing the NotificationFilterFactory interface.
85  * Three filter factories corresponding to the "standard" jmx
86  * notification filters are supplied by default in package
87  * org.jboss.system.filterfactory.
88  *
89  * 19/10/04, dimitris
90  * renamed inner class MBeanInfo to SubscriptionInfo and made public,
91  * using NotificationFilter instead of NotificationFilterSupport and added new
92  * subscribe(List subscriptionList, boolean dynamicSubscriptions, ObjectName listener)
93  * to allow external programmatic specification of the subscription list.
94  *
95  * 28/02/04, dimitris
96  * explicit subscribe()/unsubscribe() replaced implicit start()/stop();
97  * dynamic subscription behaviour can be enabled/disabled, plus it is
98  * now possible to specify an external MBean as notification listener.
99  *
100  * 02/02/04, dimitris
101  * Initial version, that resulted by generalizing the notification
102  * subscription mechanism of the snmp adapter.
103  *
104  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
105  *
106  * @version $Revision: 58544 $
107 **/

108 public abstract class ListenerServiceMBeanSupport
109    extends ServiceMBeanSupport
110    implements ListenerServiceMBean, NotificationListener JavaDoc
111 {
112    // Private Data --------------------------------------------------
113

114    /** The list of mbean subscriptions */
115    private List JavaDoc sublist; // if null, subscriptions not made
116

117    /** The mbean subscription config in XML form */
118    private Element JavaDoc xmllist; // set through SubscriptionList attribute
119

120    /** monitoring and registering to new MBeans, as they appear */
121    private boolean dynamicSubscriptions;
122    
123    /** the receiver of the notifications */
124    private ObjectName JavaDoc listener;
125    
126    /** Handback to identify our own MBeanServerDelegate subscription */
127    private Object JavaDoc myHandback;
128    
129    /** Filter to receive only registration events */
130    private NotificationFilterSupport JavaDoc myFilter;
131   
132    /** Has subscribe() been called and unsubscribe not been called? */
133    private boolean subscribed;
134    
135    // Constructors -------------------------------------------------
136

137    /**
138     * Constructs a <tt>ListenerServiceMBeanSupport</tt>.
139    **/

140    public ListenerServiceMBeanSupport()
141    {
142         super();
143         init();
144    }
145
146    /**
147     * Constructs a <tt>ListenerServiceMBeanSupport</tt>.
148     *
149     * Pass-through to ServiceMBeanSupport.
150     *
151     * @param type The class type to determine Logger name from.
152    **/

153    public ListenerServiceMBeanSupport(final Class JavaDoc type)
154    {
155       super(type);
156       init();
157    }
158    
159    /**
160     * Constructs a <tt>ListenerServiceMBeanSupport</tt>.
161     *
162     * Pass-through to ServiceMBeanSupport.
163     *
164     * @param category The logger category name.
165    **/

166    public ListenerServiceMBeanSupport(final String JavaDoc category)
167    {
168       super(category);
169       init();
170    }
171
172    /**
173     * Constructs a <tt>ListenerServiceMBeanSupport</tt>.
174     *
175     * Pass-through to ServiceMBeanSupport.
176     *
177     * @param log The logger to use.
178    **/

179    public ListenerServiceMBeanSupport(final Logger log)
180    {
181       super(log);
182       init();
183    }
184     
185    // ListenerServiceMBean Implementation ---------------------------
186

187    /**
188     * Used to configure the JMX notification subscriptions.
189     *
190     * The configuration is done inline in the mbean descriptor.
191     *
192     * See jboss-subscription.dtd
193    **/

194    public void setSubscriptionList(Element JavaDoc list)
195    {
196       // deep copy the provided Element for later use
197
// not sure if really necessary - play it safe
198
this.xmllist = (Element JavaDoc)list.cloneNode(true);
199    }
200    
201    // Public API ----------------------------------------------------
202

203    public List JavaDoc<SubscriptionInfo> getSubscriptions()
204    {
205       return sublist;
206    }
207
208    public void setSubscriptions(List JavaDoc<SubscriptionInfo> list)
209    {
210       this.sublist = list;
211    }
212    
213    /**
214     * Subscribes this MBean for JMX notifications.
215     *
216     * @param dynamicSubscriptions indicates whether to monitor and subscribe
217     * to new MBeans that match the specification.
218    **/

219    public void subscribe(boolean dynamicSubscriptions)
220       throws Exception JavaDoc
221    {
222       subscribe(dynamicSubscriptions, this.getServiceName());
223    }
224    
225    /**
226     * Subscribes a listener MBean for JMX notifications.
227     *
228     * @param dynamicSubscriptions indicates whether to monitor and subscribe
229     * to new MBeans that match the specification.
230     * @param listener the receiver of the notifications.
231    **/

232    public void subscribe(boolean dynamicSubscriptions, ObjectName JavaDoc listener)
233       throws Exception JavaDoc
234    {
235       // we need an xml subscription specification
236
if (this.xmllist != null && this.sublist == null)
237       {
238          // Parse the XML spec
239
log.debug("Parsing subscription specification");
240          List JavaDoc 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    /**
253     * Subscribes a listener MBean for JMX notifications.
254     *
255     * @param subscriptionList the list containing SubscriptionInfo data.
256     * @param dynamicSubscriptions indicates whether to monitor and subscribe
257     * to new MBeans that match the specification.
258     * @param listener the receiver of the notifications.
259    **/

260    public void subscribe(List JavaDoc subscriptionList, boolean dynamicSubscriptions, ObjectName JavaDoc listener)
261       throws Exception JavaDoc
262    {
263       // return if already subscribed
264
if (subscribed)
265          return;
266
267       // we need an subscription specification
268
if (subscriptionList != null)
269       {
270          // store input
271
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             // Subscribe to MBeanServerDelegate MBean for registrations
287
getServer().addNotificationListener(
288                new ObjectName JavaDoc(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    /**
304     * Unsubscribes for JMX notifications
305    **/

306    public void unsubscribe()
307    {
308       // return if not subscribed
309
if (!subscribed)
310          return;
311       
312       log.debug("Removing all JMX notification subscriptions");
313       bulkUnregister();
314       
315       if (this.dynamicSubscriptions == true)
316       {
317          // Unbscribe from MBeanServerDelegate MBean for registrations
318
try {
319             getServer().removeNotificationListener(
320                new ObjectName JavaDoc(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 JavaDoc e)
329          {
330             // shouldn't happen!
331
log.warn("Could not convert '" + ServerConstants.MBEAN_SERVER_DELEGATE
332                    + "' to ObjectName", e);
333          }
334          catch (InstanceNotFoundException JavaDoc e)
335          {
336             // shouldn't happen
337
log.warn("Could not unsubscribe from non-existent MBeanServerDelegate!", e);
338          }
339          catch (ListenerNotFoundException JavaDoc e)
340          {
341             // shouldn't happend
342
log.warn("Could not unsubscribe from MBeanServerDelegate", e);
343          }
344       }
345       // indicate we've unsubscribed
346
this.subscribed = false;
347    }
348    
349    // NotificationListener -----------------------------------------
350

351    /**
352     * DO NOT OVERRIDE THIS!
353     *
354     * Handles dynamic subscriptions before delegating to
355     * handleNotification2()
356    **/

357    public void handleNotification(Notification JavaDoc notification, Object JavaDoc handback)
358    {
359       // check if the notification is for me!
360
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 JavaDoc type = notification.getType();
366          ObjectName JavaDoc target = null;
367          try {
368             target = ((MBeanServerNotification JavaDoc)notification).getMBeanName();
369          }
370          catch (ClassCastException JavaDoc 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             // iterate over the subscription specification
379
Iterator JavaDoc i = this.sublist.iterator();
380       
381             while (i.hasNext())
382             {
383                SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next();
384          
385                ObjectName JavaDoc objectName = mbeanInfo.getObjectName();
386                   
387                try
388                {
389                   if(objectName.apply(target))
390                   {
391                      log.debug("ObjectName: '" + target + "' matched '" + objectName + "'");
392                      
393                      // go for it!
394
singleRegister(
395                         this.getServer(),
396                         target,
397                         this.listener,
398                         mbeanInfo.getFilter(),
399                         mbeanInfo.getHandback()
400                      );
401                   }
402                }
403                catch (Exception JavaDoc e)
404                {
405                   // catch exceptions from apply()
406
// shouldn't happen
407
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 // delegate to subclass
419
handleNotification2(notification, handback);
420    }
421
422    /**
423     * Override to add notification handling!
424    **/

425    public void handleNotification2(Notification JavaDoc notification, Object JavaDoc handback)
426    {
427       // empty!
428
}
429    
430    // Private Methods -----------------------------------------------
431

432    /**
433     * Initialises myself
434    **/

435    private void init()
436    {
437       // just pickup a unique object
438
this.myHandback = new Integer JavaDoc(Integer.MAX_VALUE);
439       
440       // allow only registration events
441
this.myFilter = new NotificationFilterSupport JavaDoc();
442       this.myFilter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
443    }
444
445    /**
446     * Subscribes for notifications to a single MBean
447    **/

448    private void singleRegister(
449       MBeanServer JavaDoc server, ObjectName JavaDoc target, ObjectName JavaDoc listener,
450       NotificationFilter JavaDoc filter, Object JavaDoc handback)
451    {
452       try
453       {
454          server.addNotificationListener(target, listener, filter, handback);
455                
456          logSubscription(target, listener, handback, filter);
457       }
458       catch (InstanceNotFoundException JavaDoc e)
459       {
460          // ignore - mbean might not be registered
461
log.debug("Could not subscribe to: '" + target
462                     + "', target or listener MBean not registered");
463       }
464       catch (RuntimeException JavaDoc 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    /**
473     * Unsubscribes for notifications from a single MBean
474    **/

475    private void singleUnregister(
476       MBeanServer JavaDoc server, ObjectName JavaDoc target, ObjectName JavaDoc listener,
477       NotificationFilter JavaDoc filter, Object JavaDoc handback)
478    {
479       try
480       {
481          // remove the matching subscription
482
server.removeNotificationListener(target, listener, filter, handback);
483          
484          log.debug("Unsubscribed from: '" + target + "'");
485       }
486       catch (InstanceNotFoundException JavaDoc e)
487       {
488          // ignore - target mbean not present
489
log.debug("Could not unsubscribe from non-existent: '"
490                     + target + "'");
491       }
492       catch (ListenerNotFoundException JavaDoc e)
493       {
494          // May happen if target is not a notification broadcaster
495
// and so we hadn't registered in the first place
496
log.debug("Could not unsubscribe from: '" + target + "'");
497       }
498       catch (RuntimeException JavaDoc e)
499       {
500          // whatever
501
log.debug("Could not unsubscribe from: '" + target + "'");
502       }
503    }
504    
505    /**
506     * Performs the notification subscriptions
507    **/

508    private void bulkRegister()
509    {
510       // iterate over the subscription specification
511
Iterator JavaDoc i = this.sublist.iterator();
512       
513       // find out my server
514
MBeanServer JavaDoc server = this.getServer();
515       
516       while (i.hasNext())
517       {
518          SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next();
519          
520          ObjectName JavaDoc objectName = mbeanInfo.getObjectName();
521          Object JavaDoc handback = mbeanInfo.getHandback();
522          NotificationFilter JavaDoc filter = mbeanInfo.getFilter();
523          
524          if (objectName.isPattern())
525          {
526             Set JavaDoc mset = server.queryNames(objectName, null);
527             
528             log.debug("ObjectName: '" + objectName + "' matched " + mset.size() + " MBean(s)");
529                
530             Iterator JavaDoc j = mset.iterator();
531             while (j.hasNext())
532                singleRegister(server, (ObjectName JavaDoc)j.next(), this.listener,
533                               filter, handback);
534          }
535          else
536             singleRegister(server, objectName, this.listener, filter, handback);
537       }
538    }
539    
540    /**
541     * Performs bulk unregistration
542    **/

543    private void bulkUnregister()
544    {
545       // iterate over the subscription specification
546
Iterator JavaDoc i = this.sublist.iterator();
547       
548       // find out my server
549
MBeanServer JavaDoc server = this.getServer();
550       
551       while (i.hasNext())
552       {
553          SubscriptionInfo mbeanInfo = (SubscriptionInfo)i.next();
554          
555          ObjectName JavaDoc objectName = mbeanInfo.getObjectName();
556          Object JavaDoc handback = mbeanInfo.getHandback();
557          NotificationFilter JavaDoc filter = mbeanInfo.getFilter();
558          
559          if (objectName.isPattern())
560          {
561             Set JavaDoc mset = server.queryNames(objectName, null);
562             
563             log.debug("ObjectName: '" + objectName + "' matched " + mset.size() + " MBean(s)");
564                
565             Iterator JavaDoc j = mset.iterator();
566             while (j.hasNext())
567                singleUnregister(server, (ObjectName JavaDoc)j.next(), this.listener,
568                                 filter, handback);
569          }
570          else
571             singleUnregister(server, objectName, this.listener, filter, handback);
572       }
573    }
574    
575    /**
576     * Logs subscription info
577    **/

578    private void logSubscription(
579       ObjectName JavaDoc objectName, ObjectName JavaDoc listener,
580       Object JavaDoc handback, NotificationFilter JavaDoc filter)
581    {
582       StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(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    /**
595     * Encapsulte the factory and filter creation logic
596     */

597    private NotificationFilter JavaDoc createNotificationFilter(String JavaDoc factoryClass, Element JavaDoc filterConfig)
598       throws Exception JavaDoc
599    {
600       NotificationFilterFactory factory;
601       try
602       {
603          // try to load the factory Class
604
Class JavaDoc clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass);
605          factory = (NotificationFilterFactory)clazz.newInstance();
606       }
607       catch (Exception JavaDoc e) // ClassNotFoundException, IllegalAccessException, InstantiationException
608
{
609          // factory class not found. Make a second try using
610
// the 'org.jboss.system.filterfactory.' package prefix
611
// for the "standard" filter factories provided with jboss.
612
// If that fails, too, rethrow the original exception.
613
try
614          {
615             factoryClass = "org.jboss.system.filterfactory." + factoryClass;
616             Class JavaDoc clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass);
617             factory = (NotificationFilterFactory)clazz.newInstance();
618          }
619          catch (Exception JavaDoc inner)
620          {
621             throw e;
622          }
623       }
624       // delegate the filter creation/configuration to the factory
625
return factory.createNotificationFilter(filterConfig);
626    }
627    
628    /**
629     * Parses the XML subscription specification
630    **/

631    private ArrayList JavaDoc parseXMLSubscriptionSpec(Element JavaDoc root)
632        throws Exception JavaDoc
633    {
634       ArrayList JavaDoc slist = new ArrayList JavaDoc();
635       
636       // parse level 0 - subscription-list
637
if (!root.getNodeName().equals(SL_ROOT_ELEMENT))
638       {
639          throw new Exception JavaDoc("Expected '" + SL_ROOT_ELEMENT + "' element, "
640                     + "got: " + "'" + root.getNodeName() + "'");
641       }
642       else
643       {
644          NodeList JavaDoc rootlist = root.getChildNodes();
645             
646          for (int i = 0; i < rootlist.getLength(); i++)
647          {
648             // Parse level 1 - look for mbeans
649
Node JavaDoc mbean = rootlist.item(i);
650                 
651             if (mbean.getNodeName().equals(SL_MBEAN_ELEMENT))
652             {
653                // mbean found look for name & handback attrs
654
String JavaDoc name = null;
655                
656                if (((Element JavaDoc)mbean).hasAttribute(SL_MBEAN_NAME_ATTRIBUTE))
657                {
658                   name = ((Element JavaDoc)mbean).getAttribute(SL_MBEAN_NAME_ATTRIBUTE);
659                }
660                else
661                {
662                   throw new Exception JavaDoc("'" + SL_MBEAN_ELEMENT + "' element must have a '"
663                                     + SL_MBEAN_NAME_ATTRIBUTE + "' attribute");
664                }
665
666                String JavaDoc handback = null;
667                if (((Element JavaDoc)mbean).hasAttribute(SL_MBEAN_HANDBACK_ATTRIBUTE))
668                {
669                   handback = ((Element JavaDoc)mbean).getAttribute(SL_MBEAN_HANDBACK_ATTRIBUTE);
670                }
671                
672                // try to convert name to the correct data type
673
// may throw MalformedObjectNameException
674
ObjectName JavaDoc objectName = new ObjectName JavaDoc(name);
675                
676                // Parse level 2 - see if we have a filter for this subscription
677
NotificationFilter JavaDoc filter = null;
678                
679                NodeList JavaDoc mbeanChildren = mbean.getChildNodes();
680
681                // check for filter spec, as a single mbean child node
682
for (int j = 0; j < mbeanChildren.getLength(); j++)
683                {
684                   Node JavaDoc mbeanChildNode = mbeanChildren.item(j);
685                   
686                   // check if this is a 'filter' node
687
if (mbeanChildNode.getNodeName().equals(SL_FILTER_ELEMENT))
688                   {
689                      // look for the 'factory' attribute
690
String JavaDoc factory = null;
691                      if (((Element JavaDoc)mbeanChildNode).hasAttribute(SL_FILTER_FACTORY_ATTRIBUTE))
692                      {
693                         factory = ((Element JavaDoc)mbeanChildNode).getAttribute(SL_FILTER_FACTORY_ATTRIBUTE);
694                         
695                         // instantiate the factory and request the filter
696
filter = createNotificationFilter(factory, (Element JavaDoc)mbeanChildNode);
697                         break;
698                      }
699                      else
700                      {
701                         throw new Exception JavaDoc("'" + SL_FILTER_ELEMENT + "' element must have a '"
702                               + SL_FILTER_FACTORY_ATTRIBUTE + "' attribute");
703                      }
704                   }
705                }
706                
707                if (filter == null)
708                {
709                   // if no filter has been set check for old-style
710
// <notification type="..."/> construct that results
711
// in a fixed NotificationFilterSupport filter
712

713                   // need to find out all notification types (if any)
714
// in order to create the Notification filter
715
ArrayList JavaDoc tmplist = new ArrayList JavaDoc(mbeanChildren.getLength());
716                
717                   for (int j = 0; j < mbeanChildren.getLength(); j++)
718                   {
719                      Node JavaDoc mbeanChildNode = mbeanChildren.item(j);
720                   
721                      // check if this is a 'notification' element
722
if (mbeanChildNode.getNodeName().equals(SL_NOTIFICATION_ELEMENT))
723                      {
724                         // look for 'type' attribute
725
String JavaDoc type = null;
726                         if (((Element JavaDoc)mbeanChildNode).hasAttribute(SL_NOTIFICATION_TYPE_ATTRIBUTE))
727                         {
728                            type = ((Element JavaDoc)mbeanChildNode).getAttribute(SL_NOTIFICATION_TYPE_ATTRIBUTE);
729                            tmplist.add(type);
730                         }
731                         else
732                         {
733                            throw new Exception JavaDoc("'" + SL_NOTIFICATION_ELEMENT + "' element must have a '"
734                                  + SL_NOTIFICATION_TYPE_ATTRIBUTE + "' attribute");
735                         }
736                      }
737                   }
738                   // create the filter (if needed)
739
if (tmplist.size() > 0)
740                   {
741                      NotificationFilterSupport JavaDoc sfilter = new NotificationFilterSupport JavaDoc();
742                      for (int j = 0; j < tmplist.size(); j++)
743                      {
744                         sfilter.enableType((String JavaDoc)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    // Inner Class ---------------------------------------------------
757

758    /**
759     * Inner data holder class to store the parsed subscription specification.
760    **/

761    public static final class SubscriptionInfo
762    {
763       // Private Data -----------------------------------------------
764

765       /** MBean notification broadcaster or pattern */
766       private ObjectName JavaDoc objectName;
767       
768       /** Optional handback object to identify a subscription */
769       private Object JavaDoc handback;
770       
771       /** Arbitrary NotificationFilter */
772       private NotificationFilter JavaDoc filter;
773       
774       // Constructor ------------------------------------------------
775

776       /**
777        * Simple CTOR
778       **/

779       public SubscriptionInfo(ObjectName JavaDoc objectName, Object JavaDoc handback, NotificationFilter JavaDoc filter)
780       {
781          this.objectName = objectName;
782          this.handback = handback;
783          this.filter = filter;
784       }
785       
786       // Accessors --------------------------------------------------
787
/**
788        * Gets objectname
789       **/

790       public ObjectName JavaDoc getObjectName()
791       {
792          return this.objectName;
793       }
794       
795       /**
796        * Gets handback object
797       **/

798       public Object JavaDoc getHandback()
799       {
800          return this.handback;
801       }
802       
803       /**
804        * Gets notification filter
805       **/

806       public NotificationFilter JavaDoc getFilter()
807       {
808          return this.filter;
809       }
810       
811       /**
812        * Pretty prints
813       **/

814       public String JavaDoc toString()
815       {
816          StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(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