KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jmx > MBeanContext


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jmx;
31
32 import com.caucho.loader.Environment;
33 import com.caucho.loader.WeakCloseListener;
34 import com.caucho.log.Log;
35 import com.caucho.util.L10N;
36
37 import javax.management.*;
38 import javax.management.loading.ClassLoaderRepository JavaDoc;
39 import java.lang.ref.WeakReference JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Hashtable JavaDoc;
42 import java.util.LinkedHashMap JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46
47 /**
48  * The context containing mbeans registered at a particular level.
49  */

50 public class MBeanContext {
51   private static final Logger JavaDoc log = Log.open(MBeanContext.class);
52   private static final L10N L = new L10N(MBeanContext.class);
53
54   // The owning MBeanServer
55
private AbstractMBeanServer _mbeanServer;
56
57   private MBeanServerDelegate _delegate;
58   private long _seq;
59   
60   // class loader for this server
61
private ClassLoader JavaDoc _loader;
62
63   private String JavaDoc _domain = "resin";
64   private LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc> _properties =
65     new LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc>();
66
67   private ClassLoaderRepositoryImpl _classLoaderRepository =
68     new ClassLoaderRepositoryImpl();
69   
70   // map of all mbeans
71
private Hashtable JavaDoc<ObjectName,MBeanWrapper> _mbeans
72     = new Hashtable JavaDoc<ObjectName,MBeanWrapper>();
73
74   private ArrayList JavaDoc<Listener> _listeners = new ArrayList JavaDoc<Listener>();
75
76   // The local view associated with the context
77
private MBeanView _view;
78   // The global view associated with the context
79
private MBeanView _globalView;
80
81   MBeanContext(AbstractMBeanServer mbeanServer,
82            ClassLoader JavaDoc loader,
83            MBeanServerDelegate delegate)
84   {
85     _mbeanServer = mbeanServer;
86     _loader = loader;
87     _delegate = delegate;
88
89     Environment.addClassLoaderListener(new WeakCloseListener(this), _loader);
90     
91     _classLoaderRepository.addClassLoader(_loader);
92
93     _view = new MBeanView(mbeanServer, _loader, "resin");
94     _globalView = new MBeanView(mbeanServer, _loader, "resin");
95   }
96
97   /**
98    * Returns the parent view.
99    */

100   protected MBeanView getParentView()
101   {
102     return _mbeanServer.getParentView();
103   }
104
105   /**
106    * Returns the ClassLoaderRepository.
107    */

108   public ClassLoaderRepository JavaDoc getClassLoaderRepository()
109   {
110     return _classLoaderRepository;
111   }
112
113   /**
114    * Returns the class loader.
115    */

116   public ClassLoader JavaDoc getClassLoader()
117   {
118     return _loader;
119   }
120
121   /**
122    * Returns the view for this context.
123    */

124   MBeanView getView()
125   {
126     return _view;
127   }
128
129   /**
130    * Returns the view for this context.
131    */

132   MBeanView getGlobalView()
133   {
134     return _globalView;
135   }
136
137   /**
138    * Sets the properties.
139    */

140   public void setProperties(Map JavaDoc<String JavaDoc,String JavaDoc> props)
141   {
142     _properties.clear();
143     _properties.putAll(props);
144   }
145
146   /**
147    * Sets the properties.
148    */

149   public LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc> copyProperties()
150   {
151     return new LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc>(_properties);
152   }
153
154   /**
155    * Returns the object name.
156    */

157   public ObjectName getObjectName(String JavaDoc name)
158     throws MalformedObjectNameException
159   {
160     if (name.indexOf(':') < 0) {
161       LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc> properties;
162       properties = new LinkedHashMap JavaDoc<String JavaDoc,String JavaDoc>();
163
164       properties.putAll(_properties);
165       Jmx.parseProperties(properties, name);
166
167       return Jmx.getObjectName(_domain, properties);
168     }
169     else
170       return new ObjectName(name);
171   }
172
173   /**
174    * Finds an admin object.
175    */

176   public MBeanWrapper getMBean(ObjectName name)
177   {
178     if (name != null)
179       return _mbeans.get(name);
180     else
181       return null;
182   }
183   
184   /**
185    * Registers an MBean with the server.
186    *
187    * @param mbean the object to be registered as an MBean
188    * @param name the name of the mbean.
189    *
190    * @return the instantiated object.
191    */

192   ObjectInstance registerMBean(MBeanWrapper mbean,
193                    ObjectName name)
194     throws InstanceAlreadyExistsException,
195        MBeanRegistrationException,
196        NotCompliantMBeanException
197   {
198     if (mbean == null)
199       throw new NotCompliantMBeanException(L.l("{0} is a null mbean",
200                            name));
201     if (_mbeans.get(name) != null)
202       throw new InstanceAlreadyExistsException(String.valueOf(name));
203
204     Object JavaDoc object = mbean.getObject();
205     
206     MBeanRegistration registration = null;
207    
208     if (object instanceof MBeanRegistration)
209       registration = (MBeanRegistration) object;
210     
211     try {
212       if (registration != null)
213         name = registration.preRegister(_mbeanServer, name);
214     } catch (Exception JavaDoc e) {
215       throw new MBeanRegistrationException(e);
216     }
217
218     addMBean(name, mbean);
219
220     try {
221       if (registration != null)
222     registration.postRegister(new Boolean JavaDoc(true));
223     } catch (Exception JavaDoc e) {
224       throw new MBeanRegistrationException(e);
225     }
226
227     return mbean.getObjectInstance();
228   }
229   
230   /**
231    * Unregisters an MBean from the server.
232    *
233    * @param name the name of the mbean.
234    */

235   public void unregisterMBean(ObjectName name)
236     throws InstanceNotFoundException,
237        MBeanRegistrationException
238   {
239     if (_mbeans == null) {
240       removeMBean(name);
241       return;
242     }
243
244     if (name.getDomain().equals("JMImplementation"))
245       return;
246     
247     MBeanWrapper mbean = _mbeans.get(name);
248
249     if (mbean == null)
250       throw new InstanceNotFoundException(String.valueOf(name));
251
252     Object JavaDoc obj = mbean.getObject();
253     MBeanRegistration registration = null;
254    
255     if (obj instanceof MBeanRegistration)
256       registration = (MBeanRegistration) obj;
257
258     try {
259       if (registration != null) {
260     try {
261       registration.preDeregister();
262     } catch (Throwable JavaDoc e) {
263       log.log(Level.WARNING, e.toString());
264     }
265       }
266
267       removeMBean(name);
268        
269       if (registration != null) {
270     try {
271       registration.postDeregister();
272     } catch (Throwable JavaDoc e) {
273       log.log(Level.WARNING, e.toString());
274     }
275       }
276     } catch (Exception JavaDoc e) {
277       throw new MBeanRegistrationException(e);
278     }
279   }
280   
281   /**
282    * Returns the MBean registered with the given name.
283    *
284    * @param name the name of the mbean.
285    *
286    * @return the matching mbean object.
287    */

288   public ObjectInstance getObjectInstance(ObjectName name)
289     throws InstanceNotFoundException
290   {
291     MBeanWrapper mbean = getMBean(name);
292
293     if (mbean == null)
294       throw new InstanceNotFoundException(String.valueOf(name));
295
296     return mbean.getObjectInstance();
297   }
298
299   /**
300    * Returns true if the given object is registered with the server.
301    *
302    * @param name the name of the mbean to test.
303    *
304    * @return true if the object is registered.
305    */

306   public boolean isRegistered(ObjectName name)
307   {
308     return _mbeans.get(name) != null;
309   }
310   
311   /**
312    * Returns the number of MBeans registered.
313    *
314    * @return the number of registered mbeans.
315    */

316   public int getMBeanCount()
317   {
318     return _mbeans.size();
319   }
320
321   /**
322    * Adds an object.
323    */

324   private void addMBean(ObjectName name, MBeanWrapper mbean)
325   {
326     if (mbean == null) {
327       log.warning(L.l("'{0}' is an empty mbean", name));
328       return;
329     }
330     
331     log.fine(getDebugName(name, mbean) + " registered in " + this);
332     //log.fine(L.l("{0} registered in {1}", getDebugName(name, mbean), this));
333

334     _mbeans.put(name, mbean);
335
336     _view.add(name, mbean, true);
337     _globalView.add(name, mbean, true);
338
339     sendRegisterNotification(name);
340
341     MBeanContext context = this;
342     while (context._loader != null) {
343       ClassLoader JavaDoc parentLoader = context._loader.getParent();
344       
345       MBeanContext parentContext = _mbeanServer.getContext(parentLoader);
346
347       if (parentContext == null ||
348       parentContext == context)
349     break;
350
351       if (parentContext._globalView == null) {
352     log.finer("global view is empty");
353       }
354       else if (parentContext._globalView.add(name, mbean, false))
355     parentContext.sendRegisterNotification(name);
356       
357       context = parentContext;
358     }
359   }
360
361   /**
362    * Removes an object.
363    */

364   private MBeanWrapper removeMBean(ObjectName name)
365   {
366     MBeanWrapper mbean = null;
367
368     if (_mbeans != null)
369       mbean = _mbeans.remove(name);
370
371     if (_view != null)
372       _view.remove(name);
373     
374     if (_globalView != null && _globalView.remove(name) != null) {
375       try {
376     sendUnregisterNotification(name);
377       } catch (Throwable JavaDoc e) {
378     log.log(Level.WARNING, e.toString(), e);
379       }
380     }
381
382     MBeanContext context = this;
383     while (true) {
384       ClassLoader JavaDoc parentLoader = context._loader.getParent();
385       
386       MBeanContext parentContext = _mbeanServer.getExistingContext(parentLoader);
387
388       if (parentContext == null || parentContext == context) {
389     break;
390       }
391
392       try {
393     if (parentContext._globalView == null) {
394     }
395     else if (mbean == null &&
396          (mbean = parentContext._globalView.remove(name)) != null)
397       parentContext.sendUnregisterNotification(name);
398     else if (mbean != null &&
399          parentContext._globalView.remove(name, mbean) != null)
400       parentContext.sendUnregisterNotification(name);
401       } catch (Throwable JavaDoc e) {
402     log.log(Level.WARNING, e.toString(), e);
403       }
404
405       context = parentContext;
406     }
407     
408     return mbean;
409   }
410   
411   /**
412    * Adds a listener to a registered MBean
413    *
414    * @param name the name of the mbean
415    * @param listener the listener object
416    * @param filter filters events the listener is interested in
417    * @param handback context to be returned to the listener
418    */

419   void addNotificationListener(ObjectName name,
420                    NotificationListener listener,
421                    NotificationFilter filter,
422                    Object JavaDoc handback)
423   {
424     synchronized (_listeners) {
425       _listeners.add(new Listener(name, listener, filter, handback));
426     }
427   }
428   
429   /**
430    * Removes a listener to a registered MBean
431    *
432    * @param mbean the name of the mbean
433    * @param listener the listener object
434    */

435   public void removeNotificationListener(ObjectName mbean,
436                      NotificationListener listener)
437   {
438     synchronized (_listeners) {
439       for (int i = _listeners.size() - 1; i >= 0; i--) {
440     Listener oldListener = _listeners.get(i);
441
442     if (oldListener.match(mbean, listener))
443       _listeners.remove(i);
444       }
445     }
446   }
447   
448   /**
449    * Removes a listener to a registered MBean
450    *
451    * @param mbean the name of the mbean
452    * @param listener the listener object
453    * @param filter filters events the listener is interested in
454    * @param handback context to be returned to the listener
455    */

456   public void removeNotificationListener(ObjectName mbean,
457                      NotificationListener listener,
458                      NotificationFilter filter,
459                      Object JavaDoc handback)
460   {
461     synchronized (_listeners) {
462       for (int i = _listeners.size() - 1; i >= 0; i--) {
463     Listener oldListener = _listeners.get(i);
464
465     if (oldListener.match(mbean, listener, filter, handback))
466       _listeners.remove(i);
467       }
468     }
469   }
470
471   /**
472    * Sends the register notification.
473    */

474   void sendRegisterNotification(ObjectName name)
475   {
476     serverNotification(name, MBeanServerNotification.REGISTRATION_NOTIFICATION);
477   }
478
479   /**
480    * Sends the register notification.
481    */

482   void sendUnregisterNotification(ObjectName name)
483   {
484     serverNotification(name, MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
485   }
486
487   /**
488    * Sends the notification
489    */

490   private void serverNotification(ObjectName name, String JavaDoc type)
491   {
492     MBeanServerNotification notif;
493
494     ObjectName delegateName = _mbeanServer.SERVER_DELEGATE_NAME;
495     
496     notif = new MBeanServerNotification(type, delegateName, _seq++, name);
497
498     _delegate.sendNotification(notif);
499   }
500
501   /**
502    * Closes the context server.
503    */

504   public void destroy()
505   {
506     if (_mbeans == null)
507       return;
508     
509     ArrayList JavaDoc<ObjectName> list = new ArrayList JavaDoc<ObjectName>(_mbeans.keySet());
510
511     ArrayList JavaDoc<Listener> listeners = new ArrayList JavaDoc<Listener>(_listeners);
512
513     for (int i = 0; i < listeners.size(); i++) {
514       Listener listener = listeners.get(i);
515
516       try {
517     MBeanWrapper mbean = _globalView.getMBean(listener.getName());
518
519     if (mbean != null)
520       mbean.removeNotificationListener(listener.getListener(),
521                        listener.getFilter(),
522                        listener.getHandback());
523       } catch (Throwable JavaDoc e) {
524     log.log(Level.FINER, e.toString(), e);
525       }
526     }
527
528     for (int i = 0; i < list.size(); i++) {
529       ObjectName name = list.get(i);
530
531       try {
532         unregisterMBean(name);
533       } catch (Throwable JavaDoc e) {
534         log.log(Level.FINE, e.toString(), e);
535       }
536     }
537
538     _mbeanServer.removeContext(this, _loader);
539
540     _listeners = null;
541     _mbeans = null;
542     _view = null;
543     _globalView = null;
544   }
545
546   /**
547    * Returns the debug name for a registered mbean.
548    *
549    * @param name the name of the mbean
550    * @param mbean the mbean instance
551    * @return
552    */

553   private String JavaDoc getDebugName(ObjectName name, MBeanWrapper mbean)
554   {
555     String JavaDoc className = mbean.getMBeanInfo().getClassName();
556
557     int p = className.lastIndexOf('.');
558     if (p > 0)
559       className = className.substring(p + 1);
560
561     return className + "[" + name + "]";
562   }
563
564   /**
565    * Display name.
566    */

567   public String JavaDoc toString()
568   {
569     return "MBeanContext[" + _loader + "]";
570   }
571
572   /**
573    * Finalizer.
574    */

575   /*
576   protected void finalize()
577     throws Throwable
578   {
579     super.finalize();
580     
581     destroy();
582   }
583   */

584
585   /**
586    * Listener references.
587    */

588   static class Listener {
589     private ObjectName _name;
590     private WeakReference JavaDoc<NotificationListener> _listenerRef;
591     private WeakReference JavaDoc<NotificationFilter> _filterRef;
592     private WeakReference JavaDoc<Object JavaDoc> _handbackRef;
593
594     Listener(ObjectName name,
595          NotificationListener listener,
596          NotificationFilter filter,
597          Object JavaDoc handback)
598     {
599       _name = name;
600       _listenerRef = new WeakReference JavaDoc<NotificationListener>(listener);
601
602       if (filter != null)
603     _filterRef = new WeakReference JavaDoc<NotificationFilter>(filter);
604
605       if (handback != null)
606     _handbackRef = new WeakReference JavaDoc<Object JavaDoc>(handback);
607     }
608
609     ObjectName getName()
610     {
611       return _name;
612     }
613
614     NotificationListener getListener()
615     {
616       return _listenerRef.get();
617     }
618
619     NotificationFilter getFilter()
620     {
621       return _filterRef != null ? _filterRef.get() : null;
622     }
623
624     Object JavaDoc getHandback()
625     {
626       return _handbackRef != null ? _handbackRef.get() : null;
627     }
628
629     boolean match(ObjectName name,
630           NotificationListener listener,
631           NotificationFilter filter,
632           Object JavaDoc handback)
633     {
634       if (! _name.equals(name))
635     return false;
636
637       else if (listener != _listenerRef.get())
638     return false;
639
640       else if (filter == null && _filterRef != null)
641     return false;
642       
643       else if (_filterRef != null && _filterRef.get() != filter)
644     return false;
645
646       else if (handback == null && _handbackRef != null)
647     return false;
648       
649       else if (_handbackRef != null && _handbackRef.get() != handback)
650     return false;
651       
652       else
653     return true;
654     }
655
656     boolean match(ObjectName name,
657           NotificationListener listener)
658     {
659       if (! _name.equals(name))
660     return false;
661
662       else if (listener != _listenerRef.get())
663     return false;
664       
665       else
666     return true;
667     }
668   }
669 }
670
671
Popular Tags