diff options
Diffstat (limited to 'libjava/classpath/javax/management/MBeanServerFactory.java')
-rw-r--r-- | libjava/classpath/javax/management/MBeanServerFactory.java | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/libjava/classpath/javax/management/MBeanServerFactory.java b/libjava/classpath/javax/management/MBeanServerFactory.java new file mode 100644 index 000000000..f9bd4566f --- /dev/null +++ b/libjava/classpath/javax/management/MBeanServerFactory.java @@ -0,0 +1,413 @@ +/* MBeanServerFactory.java -- Manages server instances. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management; + +import gnu.classpath.SystemProperties; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.management.loading.ClassLoaderRepository; + +/** + * <p> + * Creates and maintains a set of {@link MBeanServer} instances. + * Server instances, as of JMX 1.2, are created using a subclass + * of {@link MBeanServerBuilder}. The exact class used is controlled + * by the property <code>javax.management.builder.initial</code>, + * and allows the instances created by {@link MBeanServerBuilder} + * to be wrapped, thus providing additional functionality. + * </p> + * <p> + * The property is used as follows: + * </p> + * <ol> + * <li>If the property has no value, then an instance of + * {@link MBeanServerBuilder} is used.</li> + * <li>If a value is given, then: + * <ol> + * <li>The class is loaded using + * <code>Thread.currentThread().getContextClassLoader()</code>, or, + * if this is <code>null</code>, by <code>Class.forName()</code>.</li> + * <li><code>Class.newInstance()</code> is used to create an instance + * of the class. The class must be public and have a public empty + * constructor. If an exception is thrown, it is propogated as + * a {@link JMRuntimeException} and no new server instances may be + * created until the property is set to a valid value.</li> + * </ol></li> + * <li>The value is checked on each successive request for a server. + * If it differs from the class of the existing instance of + * {@link MBeanServerBuilder}, then the value is used to create + * a new instance.</li> + * </ol> + */ +public class MBeanServerFactory +{ + + /** + * The last builder instance. + */ + private static MBeanServerBuilder builder; + + /** + * The map of registered servers (identifiers to servers). + */ + private static final Map<Object,MBeanServer> servers = + new HashMap<Object,MBeanServer>(); + + /** + * Private constructor to prevent instance creation. + */ + private MBeanServerFactory() {} + + /** + * Returns a server implementation using the default domain name + * of <code>"DefaultDomain"</code>. The default domain name is + * used when the domain name specified by the user is <code>null</code. + * A reference to the created server is retained, so that it can + * be retrieved at a later date using {@link #findMBeanServer}. + * Calling this method is equivalent to calling + * {@link createMBeanServer(String)} with a <code>null</code> value. + * + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + * @see #createMBeanServer(String) + */ + public static MBeanServer createMBeanServer() + { + return createMBeanServer(null); + } + + /** + * Returns a server implementation using the default domain name + * given, or <code>"DefaultDomain"</code> if this is <code>null</code>. + * The default domain name is used when the domain name specified by + * the user is <code>null</code. A reference to the created server is + * retained, so that it can be retrieved at a later date using + * {@link #findMBeanServer}. + * + * @param domain the default domain name of the server. + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + public static MBeanServer createMBeanServer(String domain) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("createMBeanServer")); + MBeanServer server = createServer(domain); + try + { + ObjectName dn = new + ObjectName("JMImplementation:type=MBeanServerDelegate"); + servers.put(server.getAttribute(dn, "MBeanServerId"), server); + } + catch (MalformedObjectNameException e) + { + throw (Error) + (new InternalError("Malformed delegate bean name.").initCause(e)); + } + catch (MBeanException e) + { + throw (Error) + (new InternalError("Exception in getMBeanServerId().").initCause(e)); + } + catch (AttributeNotFoundException e) + { + throw (Error) + (new InternalError("Could not find MBeanServerId attribute.").initCause(e)); + } + catch (InstanceNotFoundException e) + { + throw (Error) + (new InternalError("Could not find the delegate bean.").initCause(e)); + } + catch (ReflectionException e) + { + throw (Error) + (new InternalError("Could not call getMBeanServerId().").initCause(e)); + } + return server; + } + + /** + * Returns the specified server, or, if <code>id</code> is <code>null</code>, + * a list of all registered servers. A registered server is one that + * was created using {@link #createMBeanServer()} or + * {@link #createMBeanServer(String)} and has not yet been released + * using {@link releaseMBeanServer(MBeanServer)}. + * + * @param id the id of the server to retrieve, or <code>null</code> + * to return all servers. + * @return a list of {@link MBeanServer}s. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("findMBeanServer") + */ + public static ArrayList<MBeanServer> findMBeanServer(String id) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("findMBeanServer")); + if (id == null) + return new ArrayList<MBeanServer>(servers.values()); + ArrayList<MBeanServer> list = new ArrayList<MBeanServer>(); + MBeanServer server = servers.get(id); + if (server != null) + list.add(servers.get(id)); + return list; + } + + /** + * Returns the class loader repository used by the specified server. + * This is equivalent to calling {@link MBeanServer#getClassLoaderRepository()} + * on the given server. + * + * @param server the server whose class loader repository should be + * retrieved. + * @throws NullPointerException if <code>server</code> is <code>null</code>. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanPermission(String,String,ObjectName,String) + * <code>MBeanPermission(null, null, null, + * "getClassLoaderRepository")</code> + */ + public static ClassLoaderRepository getClassLoaderRepository(MBeanServer server) + { + return server.getClassLoaderRepository(); + } + + /** + * Returns a server implementation using the default domain name + * of <code>"DefaultDomain"</code>. The default domain name is + * used when the domain name specified by the user is <code>null</code. + * No reference to the created server is retained, so the server is + * garbage collected when it is no longer used, but it can not be + * retrieved at a later date using {@link #findMBeanServer}. + * Calling this method is equivalent to calling + * {@link newMBeanServer(String)} with a <code>null</code> value. + * + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("newMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + * @see #newMBeanServer(String) + */ + public static MBeanServer newMBeanServer() + { + return newMBeanServer(null); + } + + /** + * Returns a server implementation using the default domain name + * given, or <code>"DefaultDomain"</code> if this is <code>null</code>. + * The default domain name is used when the domain name specified by + * the user is <code>null</code. No reference to the created server is + * retained, so the server is garbage collected when it is no longer + * used, but it can not be retrieved at a later date using + * {@link #findMBeanServer}. + * + * @param domain the default domain name of the server. + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("newMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + public static MBeanServer newMBeanServer(String domain) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("newMBeanServer")); + return createServer(domain); + } + + /** + * Common method to create a server for the {@link #createMBeanServer(String)} + * and {@link #newMBeanServer(String)} methods above. + * + * @param domain the default domain name of the server. + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + private static MBeanServer createServer(String domain) + { + if (domain == null) + domain = "DefaultDomain"; + String builderClass = + SystemProperties.getProperty("javax.management.builder.initial"); + if (builderClass == null) + { + if (builder == null || + builder.getClass() != MBeanServerBuilder.class) + builder = new MBeanServerBuilder(); + } + else if (!(builder != null && + builderClass.equals(builder.getClass().getName()))) + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) + cl = MBeanServerFactory.class.getClassLoader(); + try + { + Class<?> bClass = Class.forName(builderClass, true, cl); + builder = (MBeanServerBuilder) bClass.newInstance(); + } + catch (ClassNotFoundException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be found.")) + .initCause(e); + } + catch (InstantiationException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be instantiated.")) + .initCause(e); + } + catch (IllegalAccessException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be accessed.")) + .initCause(e); + } + } + MBeanServerDelegate delegate = builder.newMBeanServerDelegate(); + if (delegate == null) + throw new JMRuntimeException("A delegate could not be created."); + MBeanServer server = builder.newMBeanServer(domain, null, delegate); + if (server == null) + throw new JMRuntimeException("A server could not be created."); + return server; + } + + /** + * Removes the reference to the specified server, thus allowing it to + * be garbage collected. + * + * @param server the server to remove. + * @throws IllegalArgumentException if a reference to the server is not + * held (i.e. it wasn't created by + * {@link #createMBeanServer(String)} + * or this method has already been called + * on it. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("releaseMBeanServer") + */ + public static void releaseMBeanServer(MBeanServer server) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("releaseMBeanServer")); + Iterator<MBeanServer> i = servers.values().iterator(); + while (i.hasNext()) + { + MBeanServer s = i.next(); + if (server == s) + { + i.remove(); + return; + } + } + throw new IllegalArgumentException("The server given is not referenced."); + } + + +} |