KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > server > MX4JMBeanServer


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.server;
10
11 import java.io.ByteArrayInputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.ObjectInputStream JavaDoc;
14 import java.security.AccessController JavaDoc;
15 import java.security.PrivilegedAction JavaDoc;
16 import java.security.PrivilegedActionException JavaDoc;
17 import java.security.PrivilegedExceptionAction JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.HashSet JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24
25 import javax.management.Attribute JavaDoc;
26 import javax.management.AttributeList JavaDoc;
27 import javax.management.AttributeNotFoundException JavaDoc;
28 import javax.management.BadAttributeValueExpException JavaDoc;
29 import javax.management.BadBinaryOpValueExpException JavaDoc;
30 import javax.management.BadStringOperationException JavaDoc;
31 import javax.management.InstanceAlreadyExistsException JavaDoc;
32 import javax.management.InstanceNotFoundException JavaDoc;
33 import javax.management.IntrospectionException JavaDoc;
34 import javax.management.InvalidApplicationException JavaDoc;
35 import javax.management.InvalidAttributeValueException JavaDoc;
36 import javax.management.JMRuntimeException JavaDoc;
37 import javax.management.ListenerNotFoundException JavaDoc;
38 import javax.management.MBeanException JavaDoc;
39 import javax.management.MBeanInfo JavaDoc;
40 import javax.management.MBeanPermission JavaDoc;
41 import javax.management.MBeanRegistrationException JavaDoc;
42 import javax.management.MBeanServer JavaDoc;
43 import javax.management.MBeanServerDelegate JavaDoc;
44 import javax.management.MBeanServerNotification JavaDoc;
45 import javax.management.MBeanServerPermission JavaDoc;
46 import javax.management.MalformedObjectNameException JavaDoc;
47 import javax.management.NotCompliantMBeanException JavaDoc;
48 import javax.management.NotificationBroadcaster JavaDoc;
49 import javax.management.NotificationEmitter JavaDoc;
50 import javax.management.NotificationFilter JavaDoc;
51 import javax.management.NotificationListener JavaDoc;
52 import javax.management.ObjectInstance JavaDoc;
53 import javax.management.ObjectName JavaDoc;
54 import javax.management.OperationsException JavaDoc;
55 import javax.management.QueryExp JavaDoc;
56 import javax.management.ReflectionException JavaDoc;
57 import javax.management.RuntimeOperationsException JavaDoc;
58 import javax.management.loading.ClassLoaderRepository JavaDoc;
59 import javax.management.loading.PrivateClassLoader JavaDoc;
60
61 import mx4j.ImplementationException;
62 import mx4j.MX4JSystemKeys;
63 import mx4j.loading.ClassLoaderObjectInputStream;
64 import mx4j.log.Log;
65 import mx4j.log.Logger;
66 import mx4j.server.interceptor.ContextClassLoaderMBeanServerInterceptor;
67 import mx4j.server.interceptor.InvokerMBeanServerInterceptor;
68 import mx4j.server.interceptor.MBeanServerInterceptor;
69 import mx4j.server.interceptor.MBeanServerInterceptorConfigurator;
70 import mx4j.server.interceptor.NotificationListenerMBeanServerInterceptor;
71 import mx4j.server.interceptor.SecurityMBeanServerInterceptor;
72 import mx4j.util.Utils;
73
74 /**
75  * The MX4J MBeanServer implementation. <br>
76  * The MBeanServer accomplishes these roles:
77  * <ul>
78  * <li> Returns information about the Agent
79  * <li> Acts as a repository for MBeans
80  * <li> Acts as an invoker, on behalf of the user, on MBeans
81  * </ul>
82  * <br>
83  * The repository function is delegated to instances of {@link MBeanRepository} classes.
84  * This class acts as a factory for MBeanRepository instances, that can be controlled via the system property
85  * {@link mx4j.MX4JSystemKeys#MX4J_MBEANSERVER_REPOSITORY} to the qualified name of the implementation class. <br>
86  * <p/>
87  * This class also acts as an invoker on MBeans. The architecture is interceptor-based, that is whenever you call
88  * from a client an MBeanServer method that will end up to call the MBean instance, the call is dispatched to
89  * the interceptor chain and eventually to the MBean. <br>
90  * The interceptors are configurable via the MBean {@link MBeanServerInterceptorConfigurator}.
91  * When the call is about to arrive to the MBean instance, the last interceptor dispatches the call depending on
92  * the MBean type: if the MBean is a dynamic MBean, the call is dispatched directly; if the MBean is a standard
93  * MBean an {@link MBeanInvoker} is delegated to invoke on the MBean instance.
94  *
95  * @version $Revision: 1.31 $
96  */

97 public class MX4JMBeanServer implements MBeanServer JavaDoc
98 {
99    private String JavaDoc defaultDomain;
100    private MBeanRepository mbeanRepository;
101    private MBeanServerDelegate JavaDoc delegate;
102    private ObjectName JavaDoc delegateName;
103    private MBeanIntrospector introspector;
104    private MBeanServerInterceptorConfigurator invoker;
105    private static long notifications;
106    private ModifiableClassLoaderRepository classLoaderRepository;
107    private Map JavaDoc domains = new HashMap JavaDoc();
108
109    private static final String JavaDoc[] EMPTY_PARAMS = new String JavaDoc[0];
110    private static final Object JavaDoc[] EMPTY_ARGS = new Object JavaDoc[0];
111
112    /**
113     * Create a new MBeanServer implementation with the specified default domain.
114     * If the default domain is null, then the empty string is assumed.
115     *
116     * @param defaultDomain The default domain to be used
117     * @throws SecurityException if access is not granted to create an MBeanServer instance
118     */

119    public MX4JMBeanServer(String JavaDoc defaultDomain, MBeanServer JavaDoc outer, MBeanServerDelegate JavaDoc delegate)
120    {
121       Logger logger = getLogger();
122       if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Creating MBeanServer instance...");
123
124       SecurityManager JavaDoc sm = System.getSecurityManager();
125       if (sm != null)
126       {
127          if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking permission to create MBeanServer...");
128          sm.checkPermission(new MBeanServerPermission JavaDoc("newMBeanServer"));
129       }
130
131       if (defaultDomain == null) defaultDomain = "DefaultDomain";
132       this.defaultDomain = defaultDomain;
133
134       if (delegate == null) throw new JMRuntimeException JavaDoc("Delegate can't be null");
135       this.delegate = delegate;
136
137       if (logger.isEnabledFor(Logger.TRACE)) logger.trace("MBeanServer default domain is: '" + this.defaultDomain + "'");
138
139       mbeanRepository = createMBeanRepository();
140
141       classLoaderRepository = createClassLoaderRepository();
142       // JMX 1.2 requires the CLR to have as first entry the classloader of this class
143
classLoaderRepository.addClassLoader(getClass().getClassLoader());
144       // The system classloader must be there as well, in case this class is in the bootclasspath
145
classLoaderRepository.addClassLoader(ClassLoader.getSystemClassLoader());
146
147       introspector = new MBeanIntrospector();
148
149       // This is the official name of the delegate, it is used as a source for MBeanServerNotifications
150
try
151       {
152          delegateName = new ObjectName JavaDoc("JMImplementation", "type", "MBeanServerDelegate");
153       }
154       catch (MalformedObjectNameException JavaDoc ignored)
155       {
156       }
157
158       try
159       {
160          ObjectName JavaDoc invokerName = new ObjectName JavaDoc(MBeanServerInterceptorConfigurator.OBJECT_NAME);
161          invoker = new MBeanServerInterceptorConfigurator(this);
162
163          ContextClassLoaderMBeanServerInterceptor ccl = new ContextClassLoaderMBeanServerInterceptor();
164          NotificationListenerMBeanServerInterceptor notif = new NotificationListenerMBeanServerInterceptor();
165          SecurityMBeanServerInterceptor sec = new SecurityMBeanServerInterceptor();
166          InvokerMBeanServerInterceptor inv = new InvokerMBeanServerInterceptor(outer == null ? this : outer);
167
168          invoker.addPreInterceptor(ccl);
169          invoker.addPreInterceptor(notif);
170          invoker.addPreInterceptor(sec);
171          invoker.addPostInterceptor(inv);
172          invoker.start();
173
174          // The interceptor stack is in place, register the configurator and all interceptors
175
privilegedRegisterMBean(invoker, invokerName);
176
177          ObjectName JavaDoc cclName = new ObjectName JavaDoc("JMImplementation", "interceptor", "contextclassloader");
178          ObjectName JavaDoc notifName = new ObjectName JavaDoc("JMImplementation", "interceptor", "notificationwrapper");
179          ObjectName JavaDoc secName = new ObjectName JavaDoc("JMImplementation", "interceptor", "security");
180          ObjectName JavaDoc invName = new ObjectName JavaDoc("JMImplementation", "interceptor", "invoker");
181
182          privilegedRegisterMBean(ccl, cclName);
183          privilegedRegisterMBean(notif, notifName);
184          privilegedRegisterMBean(sec, secName);
185          privilegedRegisterMBean(inv, invName);
186       }
187       catch (Exception JavaDoc x)
188       {
189          logger.error("MBeanServerInterceptorConfigurator cannot be registered", x);
190          throw new ImplementationException();
191       }
192
193       // Now register the delegate
194
try
195       {
196          privilegedRegisterMBean(delegate, delegateName);
197       }
198       catch (Exception JavaDoc x)
199       {
200          logger.error("MBeanServerDelegate cannot be registered", x);
201          throw new ImplementationException(x.toString());
202       }
203
204       if (logger.isEnabledFor(Logger.TRACE)) logger.trace("MBeanServer instance created successfully");
205    }
206
207    /**
208     * Returns the ClassLoaderRepository for this MBeanServer.
209     * When first the ClassLoaderRepository is created in the constructor, the system property
210     * {@link mx4j.MX4JSystemKeys#MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY} is tested;
211     * if it is non-null and defines a subclass of
212     * {@link ModifiableClassLoaderRepository}, then that class is used instead of the default one.
213     */

214    public ClassLoaderRepository JavaDoc getClassLoaderRepository()
215    {
216       SecurityManager JavaDoc sm = System.getSecurityManager();
217       if (sm != null)
218       {
219          sm.checkPermission(new MBeanPermission JavaDoc("-#-[-]", "getClassLoaderRepository"));
220       }
221
222       return getModifiableClassLoaderRepository();
223    }
224
225    private ModifiableClassLoaderRepository getModifiableClassLoaderRepository()
226    {
227       return classLoaderRepository;
228    }
229
230    public ClassLoader JavaDoc getClassLoader(ObjectName JavaDoc name) throws InstanceNotFoundException JavaDoc
231    {
232       SecurityManager JavaDoc sm = System.getSecurityManager();
233       if (sm != null)
234       {
235          name = secureObjectName(name);
236
237          if (name == null)
238          {
239             sm.checkPermission(new MBeanPermission JavaDoc("-#-[-]", "getClassLoader"));
240          }
241          else
242          {
243             MBeanMetaData metadata = findMBeanMetaData(name);
244             sm.checkPermission(new MBeanPermission JavaDoc(metadata.getMBeanInfo().getClassName(), "-", name, "getClassLoader"));
245          }
246       }
247
248       return getClassLoaderImpl(name);
249    }
250
251    public ClassLoader JavaDoc getClassLoaderFor(ObjectName JavaDoc name) throws InstanceNotFoundException JavaDoc
252    {
253       SecurityManager JavaDoc sm = System.getSecurityManager();
254       if (sm != null)
255       {
256          name = secureObjectName(name);
257       }
258
259       // If name is null, I get InstanceNotFoundException
260
MBeanMetaData metadata = findMBeanMetaData(name);
261
262       if (sm != null)
263       {
264          sm.checkPermission(new MBeanPermission JavaDoc(metadata.getMBeanInfo().getClassName(), "-", name, "getClassLoaderFor"));
265       }
266
267       return metadata.getMBean().getClass().getClassLoader();
268    }
269
270    /**
271     * Returns the MBean classloader corrispondent to the given ObjectName.
272     * If <code>name</code> is null, the classloader of this class is returned.
273     */

274    private ClassLoader JavaDoc getClassLoaderImpl(ObjectName JavaDoc name) throws InstanceNotFoundException JavaDoc
275    {
276       if (name == null)
277       {
278          return getClass().getClassLoader();
279       }
280       else
281       {
282          MBeanMetaData metadata = findMBeanMetaData(name);
283          if (metadata.getMBean() instanceof ClassLoader JavaDoc)
284          {
285             return (ClassLoader JavaDoc)metadata.getMBean();
286          }
287          else
288          {
289             throw new InstanceNotFoundException JavaDoc(name.getCanonicalName());
290          }
291       }
292    }
293
294    public ObjectInputStream JavaDoc deserialize(String JavaDoc className, ObjectName JavaDoc loaderName, byte[] bytes)
295            throws InstanceNotFoundException JavaDoc, OperationsException JavaDoc, ReflectionException JavaDoc
296    {
297       if (className == null || className.trim().length() == 0)
298       {
299          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid class name '" + className + "'"));
300       }
301
302       ClassLoader JavaDoc cl = getClassLoader(loaderName);
303
304       try
305       {
306          Class JavaDoc cls = cl.loadClass(className);
307          return deserializeImpl(cls.getClassLoader(), bytes);
308       }
309       catch (ClassNotFoundException JavaDoc x)
310       {
311          throw new ReflectionException JavaDoc(x);
312       }
313    }
314
315    public ObjectInputStream JavaDoc deserialize(String JavaDoc className, byte[] bytes)
316            throws OperationsException JavaDoc, ReflectionException JavaDoc
317    {
318       if (className == null || className.trim().length() == 0)
319       {
320          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid class name '" + className + "'"));
321       }
322
323       // Find the classloader that can load the given className using the ClassLoaderRepository
324
try
325       {
326          Class JavaDoc cls = getClassLoaderRepository().loadClass(className);
327          return deserializeImpl(cls.getClassLoader(), bytes);
328       }
329       catch (ClassNotFoundException JavaDoc x)
330       {
331          throw new ReflectionException JavaDoc(x);
332       }
333    }
334
335    public ObjectInputStream JavaDoc deserialize(ObjectName JavaDoc objectName, byte[] bytes)
336            throws InstanceNotFoundException JavaDoc, OperationsException JavaDoc
337    {
338       ClassLoader JavaDoc cl = getClassLoaderFor(objectName);
339       return deserializeImpl(cl, bytes);
340    }
341
342    /**
343     * Deserializes the given bytes using the specified classloader.
344     */

345    private ObjectInputStream JavaDoc deserializeImpl(ClassLoader JavaDoc classloader, byte[] bytes) throws OperationsException JavaDoc
346    {
347       if (bytes == null || bytes.length == 0)
348       {
349          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid byte array " + bytes));
350       }
351
352       ByteArrayInputStream JavaDoc bais = new ByteArrayInputStream JavaDoc(bytes);
353       try
354       {
355          return new ClassLoaderObjectInputStream(bais, classloader);
356       }
357       catch (IOException JavaDoc x)
358       {
359          throw new OperationsException JavaDoc(x.toString());
360       }
361    }
362
363    private MBeanServerInterceptor getHeadInterceptor()
364    {
365       MBeanServerInterceptor head = invoker.getHeadInterceptor();
366
367       if (head == null) throw new IllegalStateException JavaDoc("No MBeanServer interceptor, probably the configurator has been stopped");
368
369       return head;
370    }
371
372    private Logger getLogger()
373    {
374       return Log.getLogger(getClass().getName());
375    }
376
377    /**
378     * Creates a new repository for MBeans.
379     * The system property {@link mx4j.MX4JSystemKeys#MX4J_MBEANSERVER_REPOSITORY} is tested
380     * for a full qualified name of a class implementing the {@link MBeanRepository} interface.
381     * In case the system property is not defined or the class is not loadable or instantiable, a default
382     * implementation is returned.
383     */

384    private MBeanRepository createMBeanRepository()
385    {
386       Logger logger = getLogger();
387
388       if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking for system property " + MX4JSystemKeys.MX4J_MBEANSERVER_REPOSITORY);
389
390       String JavaDoc value = (String JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc()
391       {
392          public Object JavaDoc run()
393          {
394             return System.getProperty(MX4JSystemKeys.MX4J_MBEANSERVER_REPOSITORY);
395          }
396       });
397
398       if (value != null)
399       {
400          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Property found for custom MBeanServer registry; class is: " + value);
401
402          try
403          {
404             MBeanRepository registry = (MBeanRepository)Thread.currentThread().getContextClassLoader().loadClass(value).newInstance();
405             if (logger.isEnabledFor(Logger.TRACE))
406             {
407                logger.trace("Custom MBeanServer registry created successfully");
408             }
409             return registry;
410          }
411          catch (Exception JavaDoc x)
412          {
413             if (logger.isEnabledFor(Logger.TRACE))
414             {
415                logger.trace("Custom MBeanServer registry could not be created", x);
416             }
417          }
418       }
419
420       return new DefaultMBeanRepository();
421    }
422
423    /**
424     * Creates a new ClassLoaderRepository for ClassLoader MBeans.
425     * The system property {@link mx4j.MX4JSystemKeys#MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY}
426     * is tested for a full qualified name of a class
427     * extending the {@link ModifiableClassLoaderRepository} class.
428     * In case the system property is not defined or the class is not loadable or instantiable, a default
429     * implementation is returned.
430     */

431    private ModifiableClassLoaderRepository createClassLoaderRepository()
432    {
433       Logger logger = getLogger();
434
435       if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking for system property " + MX4JSystemKeys.MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY);
436
437       String JavaDoc value = (String JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc()
438       {
439          public Object JavaDoc run()
440          {
441             return System.getProperty(MX4JSystemKeys.MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY);
442          }
443       });
444
445       if (value != null)
446       {
447          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Property found for custom ClassLoaderRepository; class is: " + value);
448
449          try
450          {
451             ModifiableClassLoaderRepository repository = (ModifiableClassLoaderRepository)Thread.currentThread().getContextClassLoader().loadClass(value).newInstance();
452             if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Custom ClassLoaderRepository created successfully " + repository);
453             return repository;
454          }
455          catch (Exception JavaDoc x)
456          {
457             if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Custom ClassLoaderRepository could not be created", x);
458          }
459       }
460       return new DefaultClassLoaderRepository();
461    }
462
463    /**
464     * Returns the repository of MBeans for this MBeanServer
465     */

466    private MBeanRepository getMBeanRepository()
467    {
468       return mbeanRepository;
469    }
470
471    /**
472     * Looks up the metadata associated with the given ObjectName.
473     *
474     * @throws InstanceNotFoundException if the given ObjectName is not a registered MBean
475     */

476    private MBeanMetaData findMBeanMetaData(ObjectName JavaDoc objectName) throws InstanceNotFoundException JavaDoc
477    {
478       MBeanMetaData metadata = null;
479       if (objectName != null)
480       {
481          objectName = normalizeObjectName(objectName);
482
483          MBeanRepository repository = getMBeanRepository();
484          synchronized (repository)
485          {
486             metadata = repository.get(objectName);
487          }
488       }
489       if (metadata == null)
490       {
491          throw new InstanceNotFoundException JavaDoc("MBeanServer cannot find MBean with ObjectName " + objectName);
492       }
493       return metadata;
494    }
495
496    public void addNotificationListener(ObjectName JavaDoc observed, ObjectName JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
497            throws InstanceNotFoundException JavaDoc
498    {
499       listener = secureObjectName(listener);
500
501       Object JavaDoc mbean = findMBeanMetaData(listener).getMBean();
502       if (!(mbean instanceof NotificationListener JavaDoc))
503       {
504          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + listener + " is not a NotificationListener"));
505       }
506       addNotificationListener(observed, (NotificationListener JavaDoc)mbean, filter, handback);
507    }
508
509    public void addNotificationListener(ObjectName JavaDoc observed, NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
510            throws InstanceNotFoundException JavaDoc
511    {
512       if (observed == null)
513       {
514          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("ObjectName cannot be null"));
515       }
516       if (listener == null)
517       {
518          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("NotificationListener cannot be null"));
519       }
520
521       observed = secureObjectName(observed);
522
523       MBeanMetaData metadata = findMBeanMetaData(observed);
524
525       Object JavaDoc mbean = metadata.getMBean();
526
527       if (!(mbean instanceof NotificationBroadcaster JavaDoc))
528       {
529          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + observed + " is not a NotificationBroadcaster"));
530       }
531
532       addNotificationListenerImpl(metadata, listener, filter, handback);
533    }
534
535    private void addNotificationListenerImpl(MBeanMetaData metadata, NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
536    {
537       getHeadInterceptor().addNotificationListener(metadata, listener, filter, handback);
538    }
539
540    public void removeNotificationListener(ObjectName JavaDoc observed, ObjectName JavaDoc listener)
541            throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc
542    {
543       listener = secureObjectName(listener);
544
545       Object JavaDoc mbean = findMBeanMetaData(listener).getMBean();
546       if (!(mbean instanceof NotificationListener JavaDoc))
547       {
548          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + listener + " is not a NotificationListener"));
549       }
550       removeNotificationListener(observed, (NotificationListener JavaDoc)mbean);
551    }
552
553    public void removeNotificationListener(ObjectName JavaDoc observed, NotificationListener JavaDoc listener)
554            throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc
555    {
556       if (listener == null)
557       {
558          throw new ListenerNotFoundException JavaDoc("NotificationListener cannot be null");
559       }
560
561       observed = secureObjectName(observed);
562
563       MBeanMetaData metadata = findMBeanMetaData(observed);
564       Object JavaDoc mbean = metadata.getMBean();
565
566       if (!(mbean instanceof NotificationBroadcaster JavaDoc))
567       {
568          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + observed + " is not a NotificationBroadcaster"));
569       }
570
571       removeNotificationListenerImpl(metadata, listener);
572    }
573
574    public void removeNotificationListener(ObjectName JavaDoc observed, ObjectName JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
575            throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc
576    {
577       listener = secureObjectName(listener);
578
579       Object JavaDoc mbean = findMBeanMetaData(listener).getMBean();
580       if (!(mbean instanceof NotificationListener JavaDoc))
581       {
582          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + listener + " is not a NotificationListener"));
583       }
584       removeNotificationListener(observed, (NotificationListener JavaDoc)mbean, filter, handback);
585    }
586
587    public void removeNotificationListener(ObjectName JavaDoc observed, NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
588            throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc
589    {
590       if (listener == null)
591       {
592          throw new ListenerNotFoundException JavaDoc("NotificationListener cannot be null");
593       }
594
595       observed = secureObjectName(observed);
596
597       MBeanMetaData metadata = findMBeanMetaData(observed);
598       Object JavaDoc mbean = metadata.getMBean();
599
600       if (!(mbean instanceof NotificationEmitter JavaDoc))
601       {
602          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean " + observed + " is not a NotificationEmitter"));
603       }
604
605       removeNotificationListenerImpl(metadata, listener, filter, handback);
606    }
607
608    private void removeNotificationListenerImpl(MBeanMetaData metadata, NotificationListener JavaDoc listener)
609            throws ListenerNotFoundException JavaDoc
610    {
611       getHeadInterceptor().removeNotificationListener(metadata, listener);
612    }
613
614    private void removeNotificationListenerImpl(MBeanMetaData metadata, NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
615            throws ListenerNotFoundException JavaDoc
616    {
617       getHeadInterceptor().removeNotificationListener(metadata, listener, filter, handback);
618    }
619
620    public Object JavaDoc instantiate(String JavaDoc className)
621            throws ReflectionException JavaDoc, MBeanException JavaDoc
622    {
623       return instantiate(className, null, null);
624    }
625
626    public Object JavaDoc instantiate(String JavaDoc className, Object JavaDoc[] args, String JavaDoc[] parameters)
627            throws ReflectionException JavaDoc, MBeanException JavaDoc
628    {
629       if (className == null || className.trim().length() == 0)
630       {
631          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Class name cannot be null or empty"));
632       }
633
634       try
635       {
636          Class JavaDoc cls = getModifiableClassLoaderRepository().loadClass(className);
637          return instantiateImpl(className, cls.getClassLoader(), null, parameters, args).getMBean();
638       }
639       catch (ClassNotFoundException JavaDoc x)
640       {
641          throw new ReflectionException JavaDoc(x);
642       }
643    }
644
645    public Object JavaDoc instantiate(String JavaDoc className, ObjectName JavaDoc loaderName)
646            throws ReflectionException JavaDoc, MBeanException JavaDoc, InstanceNotFoundException JavaDoc
647    {
648       return instantiate(className, loaderName, null, null);
649    }
650
651    public Object JavaDoc instantiate(String JavaDoc className, ObjectName JavaDoc loaderName, Object JavaDoc[] args, String JavaDoc[] parameters)
652            throws ReflectionException JavaDoc, MBeanException JavaDoc, InstanceNotFoundException JavaDoc
653    {
654       if (className == null || className.trim().length() == 0)
655       {
656          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Class name cannot be null or empty"));
657       }
658
659       // loaderName can be null: means using this class' ClassLoader
660

661       loaderName = secureObjectName(loaderName);
662       if (loaderName != null && loaderName.isPattern())
663       {
664          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("ObjectName for the ClassLoader cannot be a pattern ObjectName: " + loaderName));
665       }
666
667       ClassLoader JavaDoc cl = getClassLoaderImpl(loaderName);
668       return instantiateImpl(className, cl, null, parameters, args).getMBean();
669    }
670
671    private MBeanMetaData instantiateImpl(String JavaDoc className, ClassLoader JavaDoc classloader, ObjectName JavaDoc name, String JavaDoc[] params, Object JavaDoc[] args)
672            throws ReflectionException JavaDoc, MBeanException JavaDoc
673    {
674       if (params == null) params = EMPTY_PARAMS;
675       if (args == null) args = EMPTY_ARGS;
676
677       MBeanMetaData metadata = createMBeanMetaData();
678       metadata.setClassLoader(classloader);
679       metadata.setObjectName(secureObjectName(name));
680
681       getHeadInterceptor().instantiate(metadata, className, params, args);
682
683       return metadata;
684    }
685
686    public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc objectName)
687            throws ReflectionException JavaDoc, InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, MBeanException JavaDoc, NotCompliantMBeanException JavaDoc
688    {
689       return createMBean(className, objectName, null, null);
690    }
691
692    public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc objectName, Object JavaDoc[] args, String JavaDoc[] parameters)
693            throws ReflectionException JavaDoc, InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, MBeanException JavaDoc, NotCompliantMBeanException JavaDoc
694    {
695       try
696       {
697          Class JavaDoc cls = getModifiableClassLoaderRepository().loadClass(className);
698          MBeanMetaData metadata;
699
700          // todo we should change the interceptor stack so that an InstantiationException
701
// can be thrown directly and handled appropriately. However, I think
702
// that should wait until a major release so am hacking this in here
703
try
704          {
705             metadata = instantiateImpl(className, cls.getClassLoader(), objectName, parameters, args);
706          }
707          catch (ReflectionException JavaDoc e)
708          {
709             Exception JavaDoc target = e.getTargetException();
710             if (target instanceof InstantiationException JavaDoc)
711             {
712                throw new NotCompliantMBeanException JavaDoc();
713             }
714             else
715             {
716                throw e;
717             }
718          }
719
720          registerImpl(metadata, false);
721
722          return metadata.getObjectInstance();
723       }
724       catch (ClassNotFoundException JavaDoc x)
725       {
726          throw new ReflectionException JavaDoc(x);
727       }
728    }
729
730    public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc objectName, ObjectName JavaDoc loaderName)
731            throws ReflectionException JavaDoc, InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, MBeanException JavaDoc, NotCompliantMBeanException JavaDoc, InstanceNotFoundException JavaDoc
732    {
733       return createMBean(className, objectName, loaderName, null, null);
734    }
735
736    public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc objectName, ObjectName JavaDoc loaderName, Object JavaDoc[] args, String JavaDoc[] parameters)
737            throws ReflectionException JavaDoc, InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, MBeanException JavaDoc, NotCompliantMBeanException JavaDoc, InstanceNotFoundException JavaDoc
738    {
739       loaderName = secureObjectName(loaderName);
740
741       ClassLoader JavaDoc cl = getClassLoaderImpl(loaderName);
742
743       MBeanMetaData metadata = instantiateImpl(className, cl, objectName, parameters, args);
744
745       registerImpl(metadata, false);
746
747       return metadata.getObjectInstance();
748    }
749
750    public ObjectInstance JavaDoc registerMBean(Object JavaDoc mbean, ObjectName JavaDoc objectName)
751            throws InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, NotCompliantMBeanException JavaDoc
752    {
753       return registerMBeanImpl(mbean, objectName, false);
754    }
755
756    private ObjectInstance JavaDoc registerMBeanImpl(Object JavaDoc mbean, ObjectName JavaDoc objectName, boolean privileged)
757            throws InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, NotCompliantMBeanException JavaDoc
758    {
759       if (mbean == null)
760       {
761          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("MBean instance cannot be null"));
762       }
763
764       MBeanMetaData metadata = createMBeanMetaData();
765       metadata.setMBean(mbean);
766       metadata.setClassLoader(mbean.getClass().getClassLoader());
767       metadata.setObjectName(secureObjectName(objectName));
768
769       registerImpl(metadata, privileged);
770
771       return metadata.getObjectInstance();
772    }
773
774    /**
775     * Returns a new instance of the metadata class used to store MBean information.
776     */

777    private MBeanMetaData createMBeanMetaData()
778    {
779       return MBeanMetaData.Factory.create();
780    }
781
782    /**
783     * This method is called only to register implementation MBeans from the constructor.
784     * Since to create an instance of this class already requires a permission, here we hide the registration
785     * of implementation MBeans to the client that thus need no further permissions.
786     */

787    private ObjectInstance JavaDoc privilegedRegisterMBean(final Object JavaDoc mbean, final ObjectName JavaDoc name)
788            throws InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, NotCompliantMBeanException JavaDoc
789    {
790       try
791       {
792          return (ObjectInstance JavaDoc)AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
793          {
794             public Object JavaDoc run() throws Exception JavaDoc
795             {
796                return registerMBeanImpl(mbean, name, true);
797             }
798          });
799       }
800       catch (PrivilegedActionException JavaDoc x)
801       {
802          Exception JavaDoc xx = x.getException();
803          if (xx instanceof InstanceAlreadyExistsException JavaDoc)
804             throw (InstanceAlreadyExistsException JavaDoc)xx;
805          else if (xx instanceof MBeanRegistrationException JavaDoc)
806             throw (MBeanRegistrationException JavaDoc)xx;
807          else if (xx instanceof NotCompliantMBeanException JavaDoc)
808             throw (NotCompliantMBeanException JavaDoc)xx;
809          else
810             throw new MBeanRegistrationException JavaDoc(xx);
811       }
812    }
813
814    private void registerImpl(MBeanMetaData metadata, boolean privileged) throws InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc, NotCompliantMBeanException JavaDoc
815    {
816       introspector.introspect(metadata);
817
818       if (!introspector.isMBeanCompliant(metadata)) throw new NotCompliantMBeanException JavaDoc("MBean is not compliant");
819
820       MBeanServerInterceptor head = getHeadInterceptor();
821
822       head.registration(metadata, MBeanServerInterceptor.PRE_REGISTER);
823
824       // The MBean implementor could have replaced the ObjectName with a subclass that is not secure, secure it again
825
metadata.setObjectName(secureObjectName(metadata.getObjectName()));
826
827       int postRegisterFlag = MBeanServerInterceptor.POST_REGISTER_FALSE;
828       try
829       {
830          register(metadata, privileged);
831          postRegisterFlag = MBeanServerInterceptor.POST_REGISTER_TRUE;
832       }
833       finally
834       {
835          head.registration(metadata, postRegisterFlag);
836       }
837
838       Object JavaDoc mbean = metadata.getMBean();
839       if (mbean instanceof ClassLoader JavaDoc && !(mbean instanceof PrivateClassLoader JavaDoc))
840       {
841          ClassLoader JavaDoc cl = (ClassLoader JavaDoc)mbean;
842          getModifiableClassLoaderRepository().addClassLoader(cl);
843       }
844    }
845
846    private void register(MBeanMetaData metadata, boolean privileged) throws InstanceAlreadyExistsException JavaDoc
847    {
848       metadata.setObjectName(normalizeObjectName(metadata.getObjectName()));
849
850       ObjectName JavaDoc objectName = metadata.getObjectName();
851       if (objectName == null || objectName.isPattern())
852       {
853          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("ObjectName cannot be null or a pattern ObjectName"));
854       }
855       if (objectName.getDomain().equals("JMImplementation") && !privileged)
856       {
857          throw new JMRuntimeException JavaDoc("Domain 'JMImplementation' is reserved for the JMX Agent");
858       }
859
860       MBeanRepository repository = getMBeanRepository();
861       synchronized (repository)
862       {
863          if (repository.get(objectName) != null) throw new InstanceAlreadyExistsException JavaDoc(objectName.toString());
864
865          repository.put(objectName, metadata);
866       }
867       addDomain(objectName.getDomain());
868
869       notify(objectName, MBeanServerNotification.REGISTRATION_NOTIFICATION);
870    }
871
872    private void notify(ObjectName JavaDoc objectName, String JavaDoc notificationType)
873    {
874       long sequenceNumber = 0;
875       synchronized (MX4JMBeanServer.class)
876       {
877          sequenceNumber = notifications;
878          ++notifications;
879       }
880
881       delegate.sendNotification(new MBeanServerNotification JavaDoc(notificationType, delegateName, sequenceNumber, objectName));
882    }
883
884    private void addDomain(String JavaDoc domain)
885    {
886       synchronized (domains)
887       {
888          Integer JavaDoc count = (Integer JavaDoc)domains.get(domain);
889          if (count == null)
890             domains.put(domain, new Integer JavaDoc(1));
891          else
892             domains.put(domain, new Integer JavaDoc(count.intValue() + 1));
893       }
894    }
895
896    private void removeDomain(String JavaDoc domain)
897    {
898       synchronized (domains)
899       {
900          Integer JavaDoc count = (Integer JavaDoc)domains.get(domain);
901          if (count == null) throw new ImplementationException();
902          if (count.intValue() < 2)
903             domains.remove(domain);
904          else
905             domains.put(domain, new Integer JavaDoc(count.intValue() - 1));
906       }
907    }
908
909    public void unregisterMBean(ObjectName JavaDoc objectName)
910            throws InstanceNotFoundException JavaDoc, MBeanRegistrationException JavaDoc
911    {
912       objectName = secureObjectName(objectName);
913
914       if (objectName == null || objectName.isPattern())
915       {
916          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("ObjectName cannot be null or a pattern ObjectName"));
917       }
918
919       if (objectName.getDomain().equals("JMImplementation"))
920       {
921          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Domain 'JMImplementation' is reserved for the JMX Agent"));
922       }
923
924       MBeanMetaData metadata = findMBeanMetaData(objectName);
925
926       MBeanServerInterceptor head = getHeadInterceptor();
927       head.registration(metadata, MBeanServerInterceptor.PRE_DEREGISTER);
928       unregister(metadata);
929
930       getHeadInterceptor().registration(metadata, MBeanServerInterceptor.POST_DEREGISTER);
931
932       Object JavaDoc mbean = metadata.getMBean();
933       if (mbean instanceof ClassLoader JavaDoc && !(mbean instanceof PrivateClassLoader JavaDoc))
934       {
935          getModifiableClassLoaderRepository().removeClassLoader((ClassLoader JavaDoc)mbean);
936       }
937    }
938
939    private void unregister(MBeanMetaData metadata)
940    {
941       ObjectName JavaDoc objectName = metadata.getObjectName();
942
943       MBeanRepository repository = getMBeanRepository();
944       synchronized (repository)
945       {
946          repository.remove(objectName);
947       }
948       removeDomain(objectName.getDomain());
949
950       notify(objectName, MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
951    }
952
953    public Object JavaDoc getAttribute(ObjectName JavaDoc objectName, String JavaDoc attribute)
954            throws InstanceNotFoundException JavaDoc, MBeanException JavaDoc, AttributeNotFoundException JavaDoc, ReflectionException JavaDoc
955    {
956       if (attribute == null || attribute.trim().length() == 0)
957       {
958          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid attribute"));
959       }
960
961       objectName = secureObjectName(objectName);
962
963       MBeanMetaData metadata = findMBeanMetaData(objectName);
964
965       return getHeadInterceptor().getAttribute(metadata, attribute);
966    }
967
968
969    public void setAttribute(ObjectName JavaDoc objectName, Attribute JavaDoc attribute)
970            throws InstanceNotFoundException JavaDoc, AttributeNotFoundException JavaDoc, InvalidAttributeValueException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
971    {
972       if (attribute == null || attribute.getName().trim().length() == 0)
973       {
974          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid attribute"));
975       }
976
977       objectName = secureObjectName(objectName);
978
979       MBeanMetaData metadata = findMBeanMetaData(objectName);
980
981       getHeadInterceptor().setAttribute(metadata, attribute);
982    }
983
984    public AttributeList JavaDoc getAttributes(ObjectName JavaDoc objectName, String JavaDoc[] attributes)
985            throws InstanceNotFoundException JavaDoc, ReflectionException JavaDoc
986    {
987       if (attributes == null)
988       {
989          throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid attribute list"));
990       }
991
992       objectName = secureObjectName(objectName);
993
994       MBeanMetaData metadata = findMBeanMetaData(objectName);
995
996       SecurityManager JavaDoc sm = System.getSecurityManager();
997       if (sm != null)
998       {
999          // Must check if the user has the right to call this method, regardless of the attributes
1000
sm.checkPermission(new MBeanPermission JavaDoc(metadata.getMBeanInfo().getClassName(), "-", objectName, "getAttribute"));
1001      }
1002
1003      return getHeadInterceptor().getAttributes(metadata, attributes);
1004   }
1005
1006   public AttributeList JavaDoc setAttributes(ObjectName JavaDoc objectName, AttributeList JavaDoc attributes)
1007           throws InstanceNotFoundException JavaDoc, ReflectionException JavaDoc
1008   {
1009      if (attributes == null)
1010      {
1011         throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid attribute list"));
1012      }
1013
1014      objectName = secureObjectName(objectName);
1015
1016      MBeanMetaData metadata = findMBeanMetaData(objectName);
1017
1018      SecurityManager JavaDoc sm = System.getSecurityManager();
1019      if (sm != null)
1020      {
1021         // Must check if the user has the right to call this method, regardless of the attributes
1022
sm.checkPermission(new MBeanPermission JavaDoc(metadata.getMBeanInfo().getClassName(), "-", objectName, "setAttribute"));
1023      }
1024
1025      return getHeadInterceptor().setAttributes(metadata, attributes);
1026   }
1027
1028   public Object JavaDoc invoke(ObjectName JavaDoc objectName, String JavaDoc methodName, Object JavaDoc[] args, String JavaDoc[] parameters)
1029           throws InstanceNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
1030   {
1031      if (methodName == null || methodName.trim().length() == 0)
1032      {
1033         throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid operation name '" + methodName + "'"));
1034      }
1035
1036      if (args == null) args = EMPTY_ARGS;
1037      if (parameters == null) parameters = EMPTY_PARAMS;
1038
1039      objectName = secureObjectName(objectName);
1040
1041      MBeanMetaData metadata = findMBeanMetaData(objectName);
1042
1043      return getHeadInterceptor().invoke(metadata, methodName, parameters, args);
1044   }
1045
1046   public String JavaDoc getDefaultDomain()
1047   {
1048      return defaultDomain;
1049   }
1050
1051   public String JavaDoc[] getDomains()
1052   {
1053      SecurityManager JavaDoc sm = System.getSecurityManager();
1054      if (sm != null)
1055      {
1056         sm.checkPermission(new MBeanPermission JavaDoc(null, null, null, "getDomains"));
1057      }
1058      Set JavaDoc keys;
1059      synchronized (domains)
1060      {
1061         keys = new HashSet JavaDoc(domains.keySet());
1062      }
1063      if (sm != null)
1064      {
1065         for (Iterator JavaDoc i = keys.iterator(); i.hasNext();)
1066         {
1067            String JavaDoc domain = (String JavaDoc)i.next();
1068            try
1069            {
1070               ObjectName JavaDoc name = new ObjectName JavaDoc(domain, "x", "x");
1071               sm.checkPermission(new MBeanPermission JavaDoc(null, null, name, "getDomains"));
1072            }
1073            catch (SecurityException JavaDoc e)
1074            {
1075               i.remove();
1076               continue;
1077            }
1078            catch (MalformedObjectNameException JavaDoc e)
1079            {
1080               throw new ImplementationException("Unexpected MalformedObjectNameException for registered domain: " + domain);
1081            }
1082         }
1083      }
1084      return (String JavaDoc[])keys.toArray(new String JavaDoc[keys.size()]);
1085   }
1086
1087   public Integer JavaDoc getMBeanCount()
1088   {
1089      MBeanRepository repository = getMBeanRepository();
1090      synchronized (repository)
1091      {
1092         return new Integer JavaDoc(repository.size());
1093      }
1094   }
1095
1096   public boolean isRegistered(ObjectName JavaDoc objectName)
1097   {
1098      try
1099      {
1100         return findMBeanMetaData(objectName) != null;
1101      }
1102      catch (InstanceNotFoundException JavaDoc x)
1103      {
1104         return false;
1105      }
1106   }
1107
1108   public MBeanInfo JavaDoc getMBeanInfo(ObjectName JavaDoc objectName)
1109           throws InstanceNotFoundException JavaDoc, IntrospectionException JavaDoc, ReflectionException JavaDoc
1110   {
1111      objectName = secureObjectName(objectName);
1112
1113      MBeanMetaData metadata = findMBeanMetaData(objectName);
1114
1115      MBeanInfo JavaDoc info = getHeadInterceptor().getMBeanInfo(metadata);
1116      if (info == null) throw new JMRuntimeException JavaDoc("MBeanInfo returned for MBean " + objectName + " is null");
1117      return info;
1118   }
1119
1120   public ObjectInstance JavaDoc getObjectInstance(ObjectName JavaDoc objectName)
1121           throws InstanceNotFoundException JavaDoc
1122   {
1123      SecurityManager JavaDoc sm = System.getSecurityManager();
1124      if (sm != null)
1125      {
1126         objectName = secureObjectName(objectName);
1127      }
1128
1129      MBeanMetaData metadata = findMBeanMetaData(objectName);
1130
1131      if (sm != null)
1132      {
1133         sm.checkPermission(new MBeanPermission JavaDoc(metadata.getMBeanInfo().getClassName(), "-", objectName, "getObjectInstance"));
1134      }
1135
1136      return metadata.getObjectInstance();
1137   }
1138
1139   public boolean isInstanceOf(ObjectName JavaDoc objectName, String JavaDoc className)
1140           throws InstanceNotFoundException JavaDoc
1141   {
1142      if (className == null || className.trim().length() == 0)
1143      {
1144         throw new RuntimeOperationsException JavaDoc(new IllegalArgumentException JavaDoc("Invalid class name"));
1145      }
1146
1147      objectName = secureObjectName(objectName);
1148
1149      MBeanMetaData metadata = findMBeanMetaData(objectName);
1150      String JavaDoc infoClassName = metadata.getMBeanInfo().getClassName();
1151
1152      SecurityManager JavaDoc sm = System.getSecurityManager();
1153      if (sm != null)
1154      {
1155         sm.checkPermission(new MBeanPermission JavaDoc(infoClassName, "-", objectName, "isInstanceOf"));
1156      }
1157      if (className.equals(infoClassName)) return true;
1158
1159      try
1160      {
1161         ClassLoader JavaDoc loader = metadata.getClassLoader();
1162         if (loader == null) loader = Thread.currentThread().getContextClassLoader();
1163         Class JavaDoc cls = loader.loadClass(className);
1164         Class JavaDoc infoClass = loader.loadClass(infoClassName);
1165         return cls.isAssignableFrom(infoClass);
1166      }
1167      catch (ClassNotFoundException JavaDoc x)
1168      {
1169         return false;
1170      }
1171   }
1172
1173   public Set JavaDoc queryMBeans(ObjectName JavaDoc patternName, QueryExp JavaDoc filter)
1174   {
1175      SecurityManager JavaDoc sm = System.getSecurityManager();
1176      if (sm != null)
1177      {
1178         patternName = secureObjectName(patternName);
1179         // Must check if the user has the right to call this method,
1180
// no matter which ObjectName has been passed.
1181
sm.checkPermission(new MBeanPermission JavaDoc("-#-[-]", "queryMBeans"));
1182      }
1183
1184      Set JavaDoc match = queryObjectNames(patternName, filter, true);
1185
1186      Set JavaDoc set = new HashSet JavaDoc();
1187      for (Iterator JavaDoc i = match.iterator(); i.hasNext();)
1188      {
1189         ObjectName JavaDoc name = (ObjectName JavaDoc)i.next();
1190         try
1191         {
1192            MBeanMetaData metadata = findMBeanMetaData(name);
1193            set.add(metadata.getObjectInstance());
1194         }
1195         catch (InstanceNotFoundException JavaDoc ignored)
1196         {
1197            // A concurrent thread removed the MBean after queryNames, ignore
1198
}
1199      }
1200      return set;
1201   }
1202
1203   public Set JavaDoc queryNames(ObjectName JavaDoc patternName, QueryExp JavaDoc filter)
1204   {
1205      SecurityManager JavaDoc sm = System.getSecurityManager();
1206      if (sm != null)
1207      {
1208         patternName = secureObjectName(patternName);
1209         // Must check if the user has the right to call this method,
1210
// no matter which ObjectName has been passed.
1211
sm.checkPermission(new MBeanPermission JavaDoc("-#-[-]", "queryNames"));
1212      }
1213
1214      return queryObjectNames(patternName, filter, false);
1215   }
1216
1217   /**
1218    * Utility method for queryNames and queryMBeans that returns a set of ObjectNames.
1219    * It does 3 things:
1220    * 1) filter the MBeans following the given ObjectName pattern
1221    * 2) filter the MBeans following the permissions that client code has
1222    * 3) filter the MBeans following the given QueryExp
1223    * It is important that these 3 operations are done in this order
1224    */

1225   private Set JavaDoc queryObjectNames(ObjectName JavaDoc patternName, QueryExp JavaDoc filter, boolean instances)
1226   {
1227      // First, retrieve the scope of the query: all mbeans matching the patternName
1228
Set JavaDoc scope = findMBeansByPattern(patternName);
1229
1230      // Second, filter the scope by checking the caller's permissions
1231
Set JavaDoc secureScope = filterMBeansBySecurity(scope, instances);
1232
1233      // Third, filter the scope using the given QueryExp
1234
Set JavaDoc match = filterMBeansByQuery(secureScope, filter);
1235
1236      return match;
1237   }
1238
1239   /**
1240    * Returns a set of ObjectNames of the registered MBeans that match the given ObjectName pattern
1241    */

1242   private Set JavaDoc findMBeansByPattern(ObjectName JavaDoc pattern)
1243   {
1244      if (pattern == null)
1245      {
1246         try
1247         {
1248            pattern = new ObjectName JavaDoc("*:*");
1249         }
1250         catch (MalformedObjectNameException JavaDoc ignored)
1251         {
1252         }
1253      }
1254
1255      pattern = normalizeObjectName(pattern);
1256
1257      String JavaDoc patternDomain = pattern.getDomain();
1258      Hashtable JavaDoc patternProps = pattern.getKeyPropertyList();
1259
1260      Set JavaDoc set = new HashSet JavaDoc();
1261
1262      // Clone the repository, we are faster than holding the lock while iterating
1263
MBeanRepository repository = null;
1264      MBeanRepository original = getMBeanRepository();
1265      synchronized (original)
1266      {
1267         repository = (MBeanRepository)original.clone();
1268      }
1269
1270      for (Iterator JavaDoc i = repository.iterator(); i.hasNext();)
1271      {
1272         MBeanMetaData metadata = (MBeanMetaData)i.next();
1273         ObjectName JavaDoc name = metadata.getObjectName();
1274         Hashtable JavaDoc props = name.getKeyPropertyList();
1275
1276         String JavaDoc domain = name.getDomain();
1277         if (Utils.wildcardMatch(patternDomain, domain))
1278         {
1279            // Domain matches, now check properties
1280
if (pattern.isPropertyPattern())
1281            {
1282               // A property pattern with no entries, can only be '*'
1283
if (patternProps.size() == 0)
1284               {
1285                  // User wants all properties
1286
set.add(name);
1287               }
1288               else
1289               {
1290                  // Loop on the properties of the pattern.
1291
// If one is not found then the current ObjectName does not match
1292
boolean found = true;
1293                  for (Iterator JavaDoc j = patternProps.entrySet().iterator(); j.hasNext();)
1294                  {
1295                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc)j.next();
1296                     Object JavaDoc patternKey = entry.getKey();
1297                     Object JavaDoc patternValue = entry.getValue();
1298                     if (patternKey.equals("*"))
1299                     {
1300                        continue;
1301                     }
1302
1303                     // Try to see if the current ObjectName contains this entry
1304
if (!props.containsKey(patternKey))
1305                     {
1306                        // Not even the key is present
1307
found = false;
1308                        break;
1309                     }
1310                     else
1311                     {
1312                        // The key is present, let's check if the values are equal
1313
Object JavaDoc value = props.get(patternKey);
1314                        if (value == null && patternValue == null)
1315                        {
1316                           // Values are equal, go on with next pattern entry
1317
continue;
1318                        }
1319                        if (value != null && value.equals(patternValue))
1320                        {
1321                           // Values are equal, go on with next pattern entry
1322
continue;
1323                        }
1324                        // Here values are different
1325
found = false;
1326                        break;
1327                     }
1328                  }
1329                  if (found) set.add(name);
1330               }
1331            }
1332            else
1333            {
1334               if (props.entrySet().equals(patternProps.entrySet())) set.add(name);
1335            }
1336         }
1337      }
1338      return set;
1339   }
1340
1341   /**
1342    * Filters the given set of ObjectNames following the permission that client code has granted.
1343    * Returns a set containing the allowed ObjectNames.
1344    */

1345   private Set JavaDoc filterMBeansBySecurity(Set JavaDoc mbeans, boolean instances)
1346   {
1347      SecurityManager JavaDoc sm = System.getSecurityManager();
1348      if (sm == null) return mbeans;
1349
1350      HashSet JavaDoc set = new HashSet JavaDoc();
1351      for (Iterator JavaDoc i = mbeans.iterator(); i.hasNext();)
1352      {
1353         ObjectName JavaDoc name = (ObjectName JavaDoc)i.next();
1354         try
1355         {
1356            MBeanMetaData metadata = findMBeanMetaData(name);
1357            String JavaDoc className = metadata.getMBeanInfo().getClassName();
1358            sm.checkPermission(new MBeanPermission JavaDoc(className, "-", name, instances ? "queryMBeans" : "queryNames"));
1359            set.add(name);
1360         }
1361         catch (InstanceNotFoundException JavaDoc ignored)
1362         {
1363            // A concurrent thread removed this MBean, continue
1364
continue;
1365         }
1366         catch (SecurityException JavaDoc ignored)
1367         {
1368            // Don't add the name to the list, and go on.
1369
}
1370      }
1371      return set;
1372   }
1373
1374   /**
1375    * Filters the given set of ObjectNames following the given QueryExp.
1376    * Returns a set of ObjectNames that match the given QueryExp.
1377    */

1378   private Set JavaDoc filterMBeansByQuery(Set JavaDoc scope, QueryExp JavaDoc filter)
1379   {
1380      if (filter == null) return scope;
1381
1382      Set JavaDoc set = new HashSet JavaDoc();
1383      for (Iterator JavaDoc i = scope.iterator(); i.hasNext();)
1384      {
1385         ObjectName JavaDoc name = (ObjectName JavaDoc)i.next();
1386         filter.setMBeanServer(this);
1387         try
1388         {
1389            if (filter.apply(name)) set.add(name);
1390         }
1391         catch (BadStringOperationException JavaDoc ignored)
1392         {
1393         }
1394         catch (BadBinaryOpValueExpException JavaDoc ignored)
1395         {
1396         }
1397         catch (BadAttributeValueExpException JavaDoc x)
1398         {
1399         }
1400         catch (InvalidApplicationException JavaDoc x)
1401         {
1402         }
1403         catch (SecurityException JavaDoc x)
1404         {
1405         }
1406         catch (Exception JavaDoc x)
1407         {
1408            // The 1.2 spec says Exceptions must not be propagated
1409
}
1410      }
1411      return set;
1412   }
1413
1414   /**
1415    * Returns a normalized ObjectName from the given one.
1416    * If an ObjectName is specified with the abbreviated notation for the default domain, that is ':key=value'
1417    * this method returns an ObjectName whose domain is the default domain of this MBeanServer and with the same
1418    * properties.
1419    */

1420   private ObjectName JavaDoc normalizeObjectName(ObjectName JavaDoc name)
1421   {
1422      if (name == null) return null;
1423
1424      String JavaDoc defaultDomain = getDefaultDomain();
1425      String JavaDoc domain = name.getDomain();
1426
1427      if (domain.length() == 0 && defaultDomain.length() > 0)
1428      {
1429         // The given object name specifies the abbreviated form to indicate the default domain,
1430
// ie ':key=value', the empty string as domain. I must convert this abbreviated form
1431
// to the full one, if the default domain of this mbeanserver is not the empty string as well
1432
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(defaultDomain).append(":").append(name.getKeyPropertyListString());
1433         if (name.isPropertyPattern())
1434         {
1435            if (name.getKeyPropertyList().size() > 0)
1436               buffer.append(",*");
1437            else
1438               buffer.append("*");
1439         }
1440         try
1441         {
1442            name = new ObjectName JavaDoc(buffer.toString());
1443         }
1444         catch (MalformedObjectNameException JavaDoc ignored)
1445         {
1446         }
1447      }
1448      return name;
1449   }
1450
1451   /**
1452    * Returns an ObjectName instance even if the provided ObjectName is a subclass.
1453    * This is done to avoid security holes: a nasty ObjectName subclass can bypass security checks.
1454    */

1455   private ObjectName JavaDoc secureObjectName(ObjectName JavaDoc name)
1456   {
1457      // I cannot trust ObjectName, since a malicious user can send a subclass that overrides equals and hashcode
1458
// to match another ObjectName for which it does not have permission, or returns different results from
1459
// ObjectName.getCanonicalName() for different calls, so that passes the security checks but in fact will
1460
// later refer to a different ObjectName for which it does not have permission.
1461
if (name == null) return null;
1462      return ObjectName.getInstance(name);
1463   }
1464}
1465
Popular Tags