OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / management / MBeanServerFactory.java
1 /* MBeanServerFactory.java -- Manages server instances.
2    Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package javax.management;
39
40 import gnu.classpath.SystemProperties;
41
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.Map;
46
47 import javax.management.loading.ClassLoaderRepository;
48
49 /**
50  * <p>
51  * Creates and maintains a set of {@link MBeanServer} instances.
52  * Server instances, as of JMX 1.2, are created using a subclass
53  * of {@link MBeanServerBuilder}.  The exact class used is controlled
54  * by the property <code>javax.management.builder.initial</code>,
55  * and allows the instances created by {@link MBeanServerBuilder}
56  * to be wrapped, thus providing additional functionality.
57  * </p>
58  * <p>
59  * The property is used as follows:
60  * </p>
61  * <ol>
62  * <li>If the property has no value, then an instance of
63  * {@link MBeanServerBuilder} is used.</li>
64  * <li>If a value is given, then:
65  * <ol>
66  * <li>The class is loaded using
67  * <code>Thread.currentThread().getContextClassLoader()</code>, or,
68  * if this is <code>null</code>, by <code>Class.forName()</code>.</li>
69  * <li><code>Class.newInstance()</code> is used to create an instance
70  * of the class.  The class must be public and have a public empty
71  * constructor.  If an exception is thrown, it is propogated as
72  * a {@link JMRuntimeException} and no new server instances may be
73  * created until the property is set to a valid value.</li>
74  * </ol></li>
75  * <li>The value is checked on each successive request for a server.
76  * If it differs from the class of the existing instance of
77  * {@link MBeanServerBuilder}, then the value is used to create
78  * a new instance.</li>
79  * </ol>
80  */
81 public class MBeanServerFactory
82 {
83
84   /**
85    * The last builder instance.
86    */
87   private static MBeanServerBuilder builder;
88
89   /**
90    * The map of registered servers (identifiers to servers).
91    */
92   private static Map servers;
93
94   /**
95    * Private constructor to prevent instance creation.
96    */
97   private MBeanServerFactory() {}
98
99   /**
100    * Returns a server implementation using the default domain name
101    * of <code>"DefaultDomain"</code>.  The default domain name is
102    * used when the domain name specified by the user is <code>null</code.
103    * A reference to the created server is retained, so that it can
104    * be retrieved at a later date using {@link #findMBeanServer}.
105    * Calling this method is equivalent to calling
106    * {@link createMBeanServer(String)} with a <code>null</code> value.
107    *
108    * @return a new {@link MBeanServer} instance.
109    * @throws SecurityException if a security manager exists and the
110    *                           caller's permissions don't imply {@link
111    *                           MBeanServerPermission(String)}("createMBeanServer")
112    * @throws JMRuntimeException if the property
113    *                     <code>javax.management.builder.initial</code>
114    *                     exists but names a class which either can not be
115    *                     instantiated or provides an implementation that returns
116    *                     <code>null</code> from either
117    *                     {@link MBeanServerBuilder#newMBeanServerDelegate()}
118    *                     or {@link MBeanServerBuilder#newMBeanServer()}
119    * @throws ClassCastException if the property
120    *                     <code>javax.management.builder.initial</code>
121    *                     exists but names a class which is not a subclass
122    *                     of {@link MBeanServerBuilder}.
123    * @see #createMBeanServer(String)
124    */
125   public static MBeanServer createMBeanServer()
126   {
127     return createMBeanServer(null);
128   }
129
130   /**
131    * Returns a server implementation using the default domain name
132    * given, or <code>"DefaultDomain"</code> if this is <code>null</code>.
133    * The default domain name is used when the domain name specified by
134    * the user is <code>null</code.  A reference to the created server is
135    * retained, so that it can be retrieved at a later date using
136    * {@link #findMBeanServer}.  
137    *
138    * @param domain the default domain name of the server.
139    * @return a new {@link MBeanServer} instance.
140    * @throws SecurityException if a security manager exists and the
141    *                           caller's permissions don't imply {@link
142    *                           MBeanServerPermission(String)}("createMBeanServer")
143    * @throws JMRuntimeException if the property
144    *                     <code>javax.management.builder.initial</code>
145    *                     exists but names a class which either can not be
146    *                     instantiated or provides an implementation that returns
147    *                     <code>null</code> from either
148    *                     {@link MBeanServerBuilder#newMBeanServerDelegate()}
149    *                     or {@link MBeanServerBuilder#newMBeanServer()}
150    * @throws ClassCastException if the property
151    *                     <code>javax.management.builder.initial</code>
152    *                     exists but names a class which is not a subclass
153    *                     of {@link MBeanServerBuilder}.
154    */
155   public static MBeanServer createMBeanServer(String domain)
156   {
157     SecurityManager sm = System.getSecurityManager();
158     if (sm != null)
159       sm.checkPermission(new MBeanServerPermission("createMBeanServer"));
160     MBeanServer server = createServer(domain);
161     if (servers == null)
162       servers = new HashMap();
163     try
164       {
165         ObjectName dn = new
166           ObjectName("JMImplementation:type=MBeanServerDelegate");
167         servers.put(server.getAttribute(dn, "MBeanServerId"), server);
168       }
169     catch (MalformedObjectNameException e)
170       {
171         throw (Error) 
172           (new InternalError("Malformed delegate bean name.").initCause(e));
173       }
174     catch (MBeanException e)
175       {
176         throw (Error) 
177           (new InternalError("Exception in getMBeanServerId().").initCause(e));
178       }
179     catch (AttributeNotFoundException e)
180       {
181         throw (Error) 
182           (new InternalError("Could not find MBeanServerId attribute.").initCause(e));
183       }
184     catch (InstanceNotFoundException e)
185       {
186         throw (Error) 
187           (new InternalError("Could not find the delegate bean.").initCause(e));
188       }
189     catch (ReflectionException e)
190       {
191         throw (Error) 
192           (new InternalError("Could not call getMBeanServerId().").initCause(e));
193       }
194     return server;
195   }
196
197   /**
198    * Returns the specified server, or, if <code>id</code> is <code>null</code>,
199    * a list of all registered servers.  A registered server is one that
200    * was created using {@link #createMBeanServer()} or
201    * {@link #createMBeanServer(String)} and has not yet been released
202    * using {@link releaseMBeanServer(MBeanServer)}.
203    *
204    * @param id the id of the server to retrieve, or <code>null</code>
205    *           to return all servers.
206    * @return a list of {@link MBeanServer}s.
207    * @throws SecurityException if a security manager exists and the
208    *                           caller's permissions don't imply {@link
209    *                           MBeanServerPermission(String)}("findMBeanServer")
210    */
211   public static ArrayList findMBeanServer(String id)
212   {
213     SecurityManager sm = System.getSecurityManager();
214     if (sm != null)
215       sm.checkPermission(new MBeanServerPermission("findMBeanServer"));
216     if (id == null)
217       return new ArrayList(servers.values());
218     ArrayList list = new ArrayList();
219     MBeanServer server = (MBeanServer) servers.get(id);
220     if (server != null)
221       list.add(servers.get(id));
222     return list;
223   }
224
225   /**
226    * Returns the class loader repository used by the specified server.
227    * This is equivalent to calling {@link MBeanServer#getClassLoaderRepository()}
228    * on the given server.
229    * 
230    * @param server the server whose class loader repository should be
231    *               retrieved.
232    * @throws NullPointerException if <code>server</code> is <code>null</code>.
233    * @throws SecurityException if a security manager exists and the
234    *                           caller's permissions don't imply {@link
235    *                           MBeanPermission(String,String,ObjectName,String)
236    *                           <code>MBeanPermission(null, null, null,
237    *                           "getClassLoaderRepository")</code>
238    */
239   public static ClassLoaderRepository getClassLoaderRepository(MBeanServer server)
240   {
241     return server.getClassLoaderRepository();
242   }
243
244   /**
245    * Returns a server implementation using the default domain name
246    * of <code>"DefaultDomain"</code>.  The default domain name is
247    * used when the domain name specified by the user is <code>null</code.
248    * No reference to the created server is retained, so the server is
249    * garbage collected when it is no longer used, but it can not be
250    * retrieved at a later date using {@link #findMBeanServer}.   
251    * Calling this method is equivalent to calling
252    * {@link newMBeanServer(String)} with a <code>null</code> value.
253    *
254    * @return a new {@link MBeanServer} instance.
255    * @throws SecurityException if a security manager exists and the
256    *                           caller's permissions don't imply {@link
257    *                           MBeanServerPermission(String)}("newMBeanServer")
258    * @throws JMRuntimeException if the property
259    *                     <code>javax.management.builder.initial</code>
260    *                     exists but names a class which either can not be
261    *                     instantiated or provides an implementation that returns
262    *                     <code>null</code> from either
263    *                     {@link MBeanServerBuilder#newMBeanServerDelegate()}
264    *                     or {@link MBeanServerBuilder#newMBeanServer()}
265    * @throws ClassCastException if the property
266    *                     <code>javax.management.builder.initial</code>
267    *                     exists but names a class which is not a subclass
268    *                     of {@link MBeanServerBuilder}.
269    * @see #newMBeanServer(String)
270    */
271   public static MBeanServer newMBeanServer()
272   {
273     return newMBeanServer(null);
274   }
275
276   /**
277    * Returns a server implementation using the default domain name
278    * given, or <code>"DefaultDomain"</code> if this is <code>null</code>.
279    * The default domain name is used when the domain name specified by
280    * the user is <code>null</code.  No reference to the created server is
281    * retained, so the server is garbage collected when it is no longer
282    * used, but it can not be retrieved at a later date using
283    * {@link #findMBeanServer}.
284    *
285    * @param domain the default domain name of the server.
286    * @return a new {@link MBeanServer} instance.
287    * @throws SecurityException if a security manager exists and the
288    *                           caller's permissions don't imply {@link
289    *                           MBeanServerPermission(String)}("newMBeanServer")
290    * @throws JMRuntimeException if the property
291    *                     <code>javax.management.builder.initial</code>
292    *                     exists but names a class which either can not be
293    *                     instantiated or provides an implementation that returns
294    *                     <code>null</code> from either
295    *                     {@link MBeanServerBuilder#newMBeanServerDelegate()}
296    *                     or {@link MBeanServerBuilder#newMBeanServer()}
297    * @throws ClassCastException if the property
298    *                     <code>javax.management.builder.initial</code>
299    *                     exists but names a class which is not a subclass
300    *                     of {@link MBeanServerBuilder}.
301    */
302   public static MBeanServer newMBeanServer(String domain)
303   {
304     SecurityManager sm = System.getSecurityManager();
305     if (sm != null)
306       sm.checkPermission(new MBeanServerPermission("newMBeanServer"));
307     return createServer(domain);
308   }
309
310   /**
311    * Common method to create a server for the {@link #createMBeanServer(String)}
312    * and {@link #newMBeanServer(String)} methods above.
313    *
314    * @param domain the default domain name of the server.
315    * @throws JMRuntimeException if the property
316    *                     <code>javax.management.builder.initial</code>
317    *                     exists but names a class which either can not be
318    *                     instantiated or provides an implementation that returns
319    *                     <code>null</code> from either
320    *                     {@link MBeanServerBuilder#newMBeanServerDelegate()}
321    *                     or {@link MBeanServerBuilder#newMBeanServer()}
322    * @throws ClassCastException if the property
323    *                     <code>javax.management.builder.initial</code>
324    *                     exists but names a class which is not a subclass
325    *                     of {@link MBeanServerBuilder}.
326    */
327   private static MBeanServer createServer(String domain)
328     {
329     if (domain == null)
330       domain = "DefaultDomain";
331     String builderClass =
332       SystemProperties.getProperty("javax.management.builder.initial");
333     if (builderClass == null)
334       {
335         if (builder == null ||
336             builder.getClass() != MBeanServerBuilder.class)
337           builder = new MBeanServerBuilder();
338       }
339     else if (!(builderClass.equals(builder.getClass().getName())))
340       {
341         ClassLoader cl = Thread.currentThread().getContextClassLoader();
342         if (cl == null)
343           cl = MBeanServerFactory.class.getClassLoader();
344         try
345           {
346             Class bClass = Class.forName(builderClass, true, cl);
347             builder = (MBeanServerBuilder) bClass.newInstance();
348           }
349         catch (ClassNotFoundException e)
350           {
351             throw (JMRuntimeException) (new JMRuntimeException("The builder class, " 
352                                                                + builderClass +
353                                                                ", could not be found."))
354               .initCause(e);
355           }
356         catch (InstantiationException e)
357           {
358             throw (JMRuntimeException) (new JMRuntimeException("The builder class, " 
359                                                                + builderClass +
360                                                                ", could not be instantiated."))
361               .initCause(e);
362           }
363         catch (IllegalAccessException e)
364           {
365             throw (JMRuntimeException) (new JMRuntimeException("The builder class, " 
366                                                                + builderClass +
367                                                                ", could not be accessed."))
368               .initCause(e);
369           }
370       }
371     MBeanServerDelegate delegate = builder.newMBeanServerDelegate();
372     if (delegate == null)
373       throw new JMRuntimeException("A delegate could not be created.");
374     MBeanServer server = builder.newMBeanServer("DefaultDomain", null, delegate);
375     if (server == null)
376       throw new JMRuntimeException("A server could not be created.");
377     return server;
378   }
379
380   /**
381    * Removes the reference to the specified server, thus allowing it to
382    * be garbage collected.
383    *
384    * @param server the server to remove.
385    * @throws IllegalArgumentException if a reference to the server is not
386    *                                  held (i.e. it wasn't created by
387    *                                  {@link #createMBeanServer(String)}
388    *                                  or this method has already been called
389    *                                  on it.
390    * @throws SecurityException if a security manager exists and the
391    *                           caller's permissions don't imply {@link
392    *                           MBeanServerPermission(String)}("releaseMBeanServer")
393    */
394   public static void releaseMBeanServer(MBeanServer server)
395   {
396     SecurityManager sm = System.getSecurityManager();
397     if (sm != null)
398       sm.checkPermission(new MBeanServerPermission("releaseMBeanServer"));
399     Iterator i = servers.values().iterator();
400     while (i.hasNext())
401       {
402         MBeanServer s = (MBeanServer) i.next();
403         if (server == s)
404           {
405             i.remove();
406             return;
407           }
408       }
409     throw new IllegalArgumentException("The server given is not referenced.");
410   }
411
412
413 }