KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > MBeanServerFactory


1 /*
2  * @(#)MBeanServerFactory.java 1.55 04/02/23
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management;
9
10 // java import
11
import java.security.AccessController JavaDoc;
12 import java.security.Permission JavaDoc;
13 import java.security.PrivilegedAction JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 // RI import
18
import javax.management.loading.ClassLoaderRepository JavaDoc;
19
20 import com.sun.jmx.defaults.ServiceName;
21 import com.sun.jmx.defaults.JmxProperties;
22 import com.sun.jmx.mbeanserver.GetPropertyAction;
23 import com.sun.jmx.trace.Trace;
24
25 /**
26  * <p>Provides MBean server references. There are no instances of
27  * this class.</p>
28  *
29  * <p>Since JMX 1.2 this class makes it possible to replace the default
30  * MBeanServer implementation. This is done using the
31  * {@link javax.management.MBeanServerBuilder} class.
32  * The class of the initial MBeanServerBuilder to be
33  * instantiated can be specified through the
34  * <b>javax.management.builder.initial</b> system property.
35  * The specified class must be a public subclass of
36  * {@link javax.management.MBeanServerBuilder}, and must have a public
37  * empty constructor.
38  * <p>By default, if no value for that property is specified, an instance of
39  * {@link
40  * javax.management.MBeanServerBuilder javax.management.MBeanServerBuilder}
41  * is created. Otherwise, the MBeanServerFactory attempts to load the
42  * specified class using
43  * {@link java.lang.Thread#getContextClassLoader()
44  * Thread.currentThread().getContextClassLoader()}, or if that is null,
45  * {@link java.lang.Class#forName(java.lang.String) Class.forName()}. Then
46  * it creates an initial instance of that Class using
47  * {@link java.lang.Class#newInstance()}. If any checked exception
48  * is raised during this process (e.g.
49  * {@link java.lang.ClassNotFoundException},
50  * {@link java.lang.InstantiationException}) the MBeanServerFactory
51  * will propagate this exception from within a RuntimeException.</p>
52  *
53  * <p>The <b>javax.management.builder.initial</b> system property is
54  * consulted every time a new MBeanServer needs to be created, and the
55  * class pointed to by that property is loaded. If that class is different
56  * from that of the current MBeanServerBuilder, then a new MBeanServerBuilder
57  * is created. Otherwise, the MBeanServerFactory may create a new
58  * MBeanServerBuilder or reuse the current one.</p>
59  *
60  * <p>If the class pointed to by the property cannot be
61  * loaded, or does not correspond to a valid subclass of MBeanServerBuilder
62  * then an exception is propagated, and no MBeanServer can be created until
63  * the <b>javax.management.builder.initial</b> system property is reset to
64  * valid value.</p>
65  *
66  * <p>The MBeanServerBuilder makes it possible to wrap the MBeanServers
67  * returned by the default MBeanServerBuilder implementation, for the purpose
68  * of e.g. adding an additional security layer.</p>
69  *
70  * @since 1.5
71  */

72 public class MBeanServerFactory {
73
74     /*
75      * There are no instances of this class so don't generate the
76      * default public constructor.
77      */

78     private MBeanServerFactory() {
79     
80     }
81
82     /**
83      * The builder that will be used to construct MBeanServers.
84      *
85      * @since.unbundled JMX 1.2
86      **/

87     private static MBeanServerBuilder JavaDoc builder = null;
88
89     /**
90      * Provide a new {@link javax.management.MBeanServerBuilder}.
91      * @param builder The new MBeanServerBuilder that will be used to
92      * create {@link javax.management.MBeanServer}s.
93      * @exception IllegalArgumentException if the given builder is null.
94      *
95      * @exception SecurityException if there is a SecurityManager and
96      * the caller's permissions do not include or imply <code>{@link
97      * MBeanServerPermission}("setMBeanServerBuilder")</code>.
98      *
99      * @since.unbundled JMX 1.2
100      **/

101     // public static synchronized void
102
// setMBeanServerBuilder(MBeanServerBuilder builder) {
103
// checkPermission("setMBeanServerBuilder");
104
// MBeanServerFactory.builder = builder;
105
// }
106

107     /**
108      * Get the current {@link javax.management.MBeanServerBuilder}.
109      *
110      * @return the current {@link javax.management.MBeanServerBuilder}.
111      *
112      * @exception SecurityException if there is a SecurityManager and
113      * the caller's permissions do not include or imply <code>{@link
114      * MBeanServerPermission}("getMBeanServerBuilder")</code>.
115      *
116      * @since.unbundled JMX 1.2
117      **/

118     // public static synchronized MBeanServerBuilder getMBeanServerBuilder() {
119
// checkPermission("getMBeanServerBuilder");
120
// return builder;
121
// }
122

123     /**
124      * Remove internal MBeanServerFactory references to a created
125      * MBeanServer. This allows the garbage collector to remove the
126      * MBeanServer object.
127      *
128      * @param mbeanServer the MBeanServer object to remove.
129      *
130      * @exception java.lang.IllegalArgumentException if
131      * <code>mbeanServer</code> was not generated by one of the
132      * <code>createMBeanServer</code> methods, or if
133      * <code>releaseMBeanServer</code> was already called on it.
134      *
135      * @exception SecurityException if there is a SecurityManager and
136      * the caller's permissions do not include or imply <code>{@link
137      * MBeanServerPermission}("releaseMBeanServer")</code>.
138      */

139     public static void releaseMBeanServer(MBeanServer JavaDoc mbeanServer) {
140     checkPermission("releaseMBeanServer");
141
142     removeMBeanServer(mbeanServer);
143     }
144
145     /**
146      * <p>Return a new object implementing the MBeanServer interface
147      * with a standard default domain name. The default domain name
148      * is used as the domain part in the ObjectName of MBeans when the
149      * domain is specified by the user is null.</p>
150      *
151      * <p>The standard default domain name is
152      * <code>DefaultDomain</code>.</p>
153      *
154      * <p>The MBeanServer reference is internally kept. This will
155      * allow <CODE>findMBeanServer</CODE> to return a reference to
156      * this MBeanServer object.</p>
157      *
158      * <p>This method is equivalent to <code>createMBeanServer(null)</code>.
159      *
160      * @return the newly created MBeanServer.
161      *
162      * @exception SecurityException if there is a SecurityManager and the
163      * caller's permissions do not include or imply <code>{@link
164      * MBeanServerPermission}("createMBeanServer")</code>.
165      *
166      * @exception JMRuntimeException if the property
167      * <code>javax.management.builder.initial</code> exists but the
168      * class it names cannot be instantiated through a public
169      * no-argument constructor; or if the instantiated builder returns
170      * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
171      * newMBeanServerDelegate} or {@link
172      * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
173      *
174      * @exception ClassCastException if the property
175      * <code>javax.management.builder.initial</code> exists and can be
176      * instantiated but is not assignment compatible with {@link
177      * MBeanServerBuilder}.
178      */

179     public static MBeanServer JavaDoc createMBeanServer() {
180     return createMBeanServer(null);
181     }
182
183     /**
184      * <p>Return a new object implementing the {@link MBeanServer}
185      * interface with the specified default domain name. The given
186      * domain name is used as the domain part in the ObjectName of
187      * MBeans when the domain is specified by the user is null.</p>
188      *
189      * <p>The MBeanServer reference is internally kept. This will
190      * allow <CODE>findMBeanServer</CODE> to return a reference to
191      * this MBeanServer object.</p>
192      *
193      * @param domain the default domain name for the created
194      * MBeanServer. This is the value that will be returned by {@link
195      * MBeanServer#getDefaultDomain}.
196      *
197      * @return the newly created MBeanServer.
198      *
199      * @exception SecurityException if there is a SecurityManager and
200      * the caller's permissions do not include or imply <code>{@link
201      * MBeanServerPermission}("createMBeanServer")</code>.
202      *
203      * @exception JMRuntimeException if the property
204      * <code>javax.management.builder.initial</code> exists but the
205      * class it names cannot be instantiated through a public
206      * no-argument constructor; or if the instantiated builder returns
207      * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
208      * newMBeanServerDelegate} or {@link
209      * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
210      *
211      * @exception ClassCastException if the property
212      * <code>javax.management.builder.initial</code> exists and can be
213      * instantiated but is not assignment compatible with {@link
214      * MBeanServerBuilder}.
215      */

216     public static MBeanServer JavaDoc createMBeanServer(String JavaDoc domain) {
217     checkPermission("createMBeanServer");
218
219     final MBeanServer JavaDoc mBeanServer = newMBeanServer(domain);
220     addMBeanServer(mBeanServer);
221     return mBeanServer;
222     }
223
224     /**
225      * <p>Return a new object implementing the MBeanServer interface
226      * with a standard default domain name, without keeping an
227      * internal reference to this new object. The default domain name
228      * is used as the domain part in the ObjectName of MBeans when the
229      * domain is specified by the user is null.</p>
230      *
231      * <p>The standard default domain name is
232      * <code>DefaultDomain</code>.</p>
233      *
234      * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not
235      * be able to return a reference to this MBeanServer object, but
236      * the garbage collector will be able to remove the MBeanServer
237      * object when it is no longer referenced.</p>
238      *
239      * <p>This method is equivalent to <code>newMBeanServer(null)</code>.</p>
240      *
241      * @return the newly created MBeanServer.
242      *
243      * @exception SecurityException if there is a SecurityManager and the
244      * caller's permissions do not include or imply <code>{@link
245      * MBeanServerPermission}("newMBeanServer")</code>.
246      *
247      * @exception JMRuntimeException if the property
248      * <code>javax.management.builder.initial</code> exists but the
249      * class it names cannot be instantiated through a public
250      * no-argument constructor; or if the instantiated builder returns
251      * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
252      * newMBeanServerDelegate} or {@link
253      * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
254      *
255      * @exception ClassCastException if the property
256      * <code>javax.management.builder.initial</code> exists and can be
257      * instantiated but is not assignment compatible with {@link
258      * MBeanServerBuilder}.
259      */

260     public static MBeanServer JavaDoc newMBeanServer() {
261     return newMBeanServer(null);
262     }
263
264     /**
265      * <p>Return a new object implementing the MBeanServer interface
266      * with the specified default domain name, without keeping an
267      * internal reference to this new object. The given domain name
268      * is used as the domain part in the ObjectName of MBeans when the
269      * domain is specified by the user is null.</p>
270      *
271      * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not
272      * be able to return a reference to this MBeanServer object, but
273      * the garbage collector will be able to remove the MBeanServer
274      * object when it is no longer referenced.</p>
275      *
276      * @param domain the default domain name for the created
277      * MBeanServer. This is the value that will be returned by {@link
278      * MBeanServer#getDefaultDomain}.
279      *
280      * @return the newly created MBeanServer.
281      *
282      * @exception SecurityException if there is a SecurityManager and the
283      * caller's permissions do not include or imply <code>{@link
284      * MBeanServerPermission}("newMBeanServer")</code>.
285      *
286      * @exception JMRuntimeException if the property
287      * <code>javax.management.builder.initial</code> exists but the
288      * class it names cannot be instantiated through a public
289      * no-argument constructor; or if the instantiated builder returns
290      * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
291      * newMBeanServerDelegate} or {@link
292      * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
293      *
294      * @exception ClassCastException if the property
295      * <code>javax.management.builder.initial</code> exists and can be
296      * instantiated but is not assignment compatible with {@link
297      * MBeanServerBuilder}.
298      */

299     public static MBeanServer JavaDoc newMBeanServer(String JavaDoc domain) {
300     checkPermission("newMBeanServer");
301
302     // Get the builder. Creates a new one if necessary.
303
//
304
final MBeanServerBuilder JavaDoc mbsBuilder = getNewMBeanServerBuilder();
305     // Returned value cannot be null. NullPointerException if violated.
306

307     synchronized(mbsBuilder) {
308         final MBeanServerDelegate JavaDoc delegate =
309         mbsBuilder.newMBeanServerDelegate();
310         if (delegate == null) {
311         final String JavaDoc msg =
312             "MBeanServerBuilder.newMBeanServerDelegate() " +
313             "returned null";
314         throw new JMRuntimeException JavaDoc(msg);
315         }
316         final MBeanServer JavaDoc mbeanServer =
317         mbsBuilder.newMBeanServer(domain,null,delegate);
318         if (mbeanServer == null) {
319         final String JavaDoc msg =
320             "MBeanServerBuilder.newMBeanServer() returned null";
321         throw new JMRuntimeException JavaDoc(msg);
322         }
323         return mbeanServer;
324     }
325     }
326
327     /**
328      * <p>Return a list of registered MBeanServer objects. A
329      * registered MBeanServer object is one that was created by one of
330      * the <code>createMBeanServer</code> methods and not subsequently
331      * released with <code>releaseMBeanServer</code>.</p>
332      *
333      * @param agentId The agent identifier of the MBeanServer to
334      * retrieve. If this parameter is null, all registered
335      * MBeanServers in this JVM are returned. Otherwise, only
336      * MBeanServers whose id is equal to <code>agentId</code> are
337      * returned. The id of an MBeanServer is the
338      * <code>MBeanServerId</code> attribute of its delegate MBean.
339      *
340      * @return A list of MBeanServer objects.
341      *
342      * @exception SecurityException if there is a SecurityManager and the
343      * caller's permissions do not include or imply <code>{@link
344      * MBeanServerPermission}("findMBeanServer")</code>.
345      */

346     public synchronized static ArrayList JavaDoc findMBeanServer(String JavaDoc agentId) {
347     checkPermission("findMBeanServer");
348
349     if (agentId == null)
350         return (ArrayList JavaDoc) mBeanServerList.clone();
351
352     ArrayList JavaDoc result = new ArrayList JavaDoc();
353     for (Iterator JavaDoc i = mBeanServerList.iterator(); i.hasNext(); ) {
354         MBeanServer JavaDoc mbs = (MBeanServer JavaDoc) i.next();
355         String JavaDoc name = mBeanServerName(mbs);
356         if (agentId.equals(name))
357         result.add(mbs);
358     }
359     return result;
360     }
361
362     /**
363      * Return the ClassLoaderRepository used by the given MBeanServer.
364      * This method is equivalent to {@link MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}.
365      * @param server The MBeanServer under examination. Since JMX 1.2,
366      * if <code>server</code> is <code>null</code>, the result is a
367      * {@link NullPointerException}. This behavior differs from what
368      * was implemented in JMX 1.1 - where the possibility to use
369      * <code>null</code> was deprecated.
370      * @return The Class Loader Repository used by the given MBeanServer.
371      * @exception SecurityException if there is a SecurityManager and
372      * the caller's permissions do not include or imply <code>{@link
373      * MBeanPermission}("getClassLoaderRepository")</code>.
374      *
375      * @exception NullPointerException if <code>server</code> is null.
376      *
377      * @since.unbundled JMX 1.1
378      **/

379     public static ClassLoaderRepository JavaDoc getClassLoaderRepository(
380                         MBeanServer JavaDoc server) {
381     return server.getClassLoaderRepository();
382     }
383
384     private static final ObjectName JavaDoc delegateName;
385     static {
386     ObjectName JavaDoc name;
387     try {
388         name = new ObjectName JavaDoc(ServiceName.DELEGATE);
389     } catch (JMException JavaDoc e) {
390         /* This can only happen if ServiceName.DELEGATE is an invalid
391            ObjectName, which means serious brokenness! */

392         name = null;
393         trace("<clinit>",
394           "internal error creating delegate ObjectName: " + e);
395     }
396     delegateName = name;
397     }
398
399     private static String JavaDoc mBeanServerName(MBeanServer JavaDoc mbs) {
400     try {
401         return (String JavaDoc) mbs.getAttribute(delegateName, "MBeanServerId");
402     } catch (JMException JavaDoc e) {
403         return null;
404     }
405     }
406
407     private static void checkPermission(String JavaDoc action)
408         throws SecurityException JavaDoc {
409     SecurityManager JavaDoc sm = System.getSecurityManager();
410     if (sm != null) {
411         Permission JavaDoc perm = new MBeanServerPermission JavaDoc(action);
412         sm.checkPermission(perm);
413     }
414     }
415
416     private static synchronized void addMBeanServer(MBeanServer JavaDoc mbs) {
417         mBeanServerList.add(mbs);
418     }
419
420     private static synchronized void removeMBeanServer(MBeanServer JavaDoc mbs) {
421     boolean removed = mBeanServerList.remove(mbs);
422     if (!removed) {
423         trace("removeMBeanServer", "MBeanServer was not in list!");
424         throw new IllegalArgumentException JavaDoc("MBeanServer was not in list!");
425     }
426     }
427
428     private static final ArrayList JavaDoc mBeanServerList = new ArrayList JavaDoc();
429
430     /**
431      * Load the builder class through the context class loader.
432      * @param builderClassName The name of the builder class.
433      **/

434     private static Class JavaDoc loadBuilderClass(String JavaDoc builderClassName)
435         throws ClassNotFoundException JavaDoc {
436     final ClassLoader JavaDoc loader =
437         Thread.currentThread().getContextClassLoader();
438
439     if (loader != null) {
440         // Try with context class loader
441
return loader.loadClass(builderClassName);
442     }
443
444     // No context class loader? Try with Class.forName()
445
return Class.forName(builderClassName);
446     }
447
448     /**
449      * Creates the initial builder according to the
450      * javax.management.builder.initial System property - if specified.
451      * If any checked exception needs to be thrown, it is embedded in
452      * a JMRuntimeException.
453      **/

454     private static MBeanServerBuilder JavaDoc newBuilder(Class JavaDoc builderClass) {
455     try {
456         final Object JavaDoc builder = builderClass.newInstance();
457         return (MBeanServerBuilder JavaDoc)builder;
458     } catch (RuntimeException JavaDoc x) {
459         throw x;
460     } catch (Exception JavaDoc x) {
461         final String JavaDoc msg =
462                "Failed to instantiate a MBeanServerBuilder from " +
463            builderClass + ": " + x;
464         throw new JMRuntimeException JavaDoc(msg, x);
465     }
466     }
467
468     /**
469      * Instantiate a new builder according to the
470      * javax.management.builder.initial System property - if needed.
471      **/

472     private static synchronized void checkMBeanServerBuilder() {
473     try {
474         PrivilegedAction JavaDoc act =
475         new GetPropertyAction(JmxProperties.JMX_INITIAL_BUILDER);
476         String JavaDoc builderClassName = (String JavaDoc)
477         AccessController.doPrivileged(act);
478
479         try {
480         final Class JavaDoc newBuilderClass;
481         if (builderClassName == null || builderClassName.length() == 0)
482             newBuilderClass = MBeanServerBuilder JavaDoc.class;
483         else
484             newBuilderClass = loadBuilderClass(builderClassName);
485
486         // Check whether a new builder needs to be created
487
if (builder != null) {
488             final Class JavaDoc builderClass = builder.getClass();
489             if (newBuilderClass == builderClass)
490             return; // no need to create a new builder...
491
}
492
493         // Create a new builder
494
builder = newBuilder(newBuilderClass);
495         } catch (ClassNotFoundException JavaDoc x) {
496         final String JavaDoc msg =
497             "Failed to load MBeanServerBuilder class " +
498             builderClassName + ": " + x;
499         throw new JMRuntimeException JavaDoc(msg, x);
500         }
501     } catch (RuntimeException JavaDoc x) {
502         debug("checkMBeanServerBuilder",
503           "Failed to instantiate MBeanServerBuilder: " + x +
504           "\n\t\tCheck the value of the " +
505           JmxProperties.JMX_INITIAL_BUILDER + " property." );
506         throw x;
507     }
508     }
509
510     /**
511      * Get the current {@link javax.management.MBeanServerBuilder},
512      * as specified by the current value of the
513      * javax.management.builder.initial property.
514      *
515      * This method consults the property and instantiates a new builder
516      * if needed.
517      *
518      * @return the new current {@link javax.management.MBeanServerBuilder}.
519      *
520      * @exception SecurityException if there is a SecurityManager and
521      * the caller's permissions do not make it possible to instantiate
522      * a new builder.
523      * @exception JMRuntimeException if the builder instantiation
524      * fails with a checked exception -
525      * {@link java.lang.ClassNotFoundException} etc...
526      *
527      * @since.unbundled JMX 1.2
528      **/

529     private static synchronized MBeanServerBuilder JavaDoc getNewMBeanServerBuilder() {
530     checkMBeanServerBuilder();
531     return builder;
532     }
533
534     /** Private Stuff **/
535     private static void trace(String JavaDoc method, String JavaDoc message) {
536     if (Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER)) {
537         Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER,
538                MBeanServerFactory JavaDoc.class.getName(), method, message);
539     }
540     }
541     /** Private Stuff **/
542     private static void debug(String JavaDoc method, String JavaDoc message) {
543     if (Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER)) {
544         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER,
545                MBeanServerFactory JavaDoc.class.getName(), method, message);
546     }
547     }
548     /** Private Stuff **/
549     private static void error(String JavaDoc method, String JavaDoc message) {
550     if (Trace.isSelected(Trace.LEVEL_ERROR, Trace.INFO_MBEANSERVER)) {
551         Trace.send(Trace.LEVEL_ERROR, Trace.INFO_MBEANSERVER,
552                MBeanServerFactory JavaDoc.class.getName(), method, message);
553     }
554     }
555 }
556
Popular Tags