From ffde862e033a0825e1e9972a89c0f1f80b261a8e Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 14 Aug 2006 23:12:35 +0000 Subject: 2006-08-14 Mark Wielaard Imported GNU Classpath 0.92 * HACKING: Add more importing hints. Update automake version requirement. * configure.ac (gconf-peer): New enable AC argument. Add --disable-gconf-peer and --enable-default-preferences-peer to classpath configure when gconf is disabled. * scripts/makemake.tcl: Set gnu/java/util/prefs/gconf and gnu/java/awt/dnd/peer/gtk to bc. Classify gnu/java/security/Configuration.java as generated source file. * gnu/java/lang/management/VMGarbageCollectorMXBeanImpl.java, gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java, gnu/java/lang/management/VMClassLoadingMXBeanImpl.java, gnu/java/lang/management/VMRuntimeMXBeanImpl.java, gnu/java/lang/management/VMMemoryManagerMXBeanImpl.java, gnu/java/lang/management/VMThreadMXBeanImpl.java, gnu/java/lang/management/VMMemoryMXBeanImpl.java, gnu/java/lang/management/VMCompilationMXBeanImpl.java: New VM stub classes. * java/lang/management/VMManagementFactory.java: Likewise. * java/net/VMURLConnection.java: Likewise. * gnu/java/nio/VMChannel.java: Likewise. * java/lang/Thread.java (getState): Add stub implementation. * java/lang/Class.java (isEnum): Likewise. * java/lang/Class.h (isEnum): Likewise. * gnu/awt/xlib/XToolkit.java (getClasspathTextLayoutPeer): Removed. * javax/naming/spi/NamingManager.java: New override for StackWalker functionality. * configure, sources.am, Makefile.in, gcj/Makefile.in, include/Makefile.in, testsuite/Makefile.in: Regenerated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116139 138bc75d-0d04-0410-961f-82ee72b054a4 --- .../classpath/javax/management/StandardMBean.java | 925 +++++++++++++++++++++ 1 file changed, 925 insertions(+) create mode 100644 libjava/classpath/javax/management/StandardMBean.java (limited to 'libjava/classpath/javax/management/StandardMBean.java') diff --git a/libjava/classpath/javax/management/StandardMBean.java b/libjava/classpath/javax/management/StandardMBean.java new file mode 100644 index 00000000000..736192ee2ac --- /dev/null +++ b/libjava/classpath/javax/management/StandardMBean.java @@ -0,0 +1,925 @@ +/* StandardMBean.java -- A standard reflection-based management bean. + 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 java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Provides a dynamic management bean by using reflection on an + * interface and an implementing class. By default, a bean instance + * is paired up with its interface based on specific naming + * conventions (if the implementation is called X, the interface must + * be XMBean). Using this class removes the need to use a specific + * naming system to match up the two. Instead, an instance of this + * bean is created either via explicit construction or subclassing, + * and this provides access to the attributes, constructors and + * operations of the implementation via reflection. Various hooks are + * provided in order to allow customization of this process. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class StandardMBean + implements DynamicMBean +{ + + /** + * The interface for this bean. + */ + private Class iface; + + /** + * The implementation of the interface. + */ + private Object impl; + + /** + * Cached bean information. + */ + private MBeanInfo info; + + /** + * Constructs a new {@link StandardMBean} using the specified + * interface and this as the instance. This should + * be used to create an instance via subclassing. + * + * @param iface the interface this bean implements, or null + * if the interface should be determined using the naming + * convention (class X has interface XMBean). + * @throws NotCompliantMBeanException if this class doesn't implement + * the interface or a method appears + * in the interface that doesn't comply + * with the naming conventions. + */ + protected StandardMBean(Class iface) + throws NotCompliantMBeanException + { + if (iface == null) + { + String className = getClass().getName(); + try + { + iface = Class.forName(className + "MBean"); + } + catch (ClassNotFoundException e) + { + throw (NotCompliantMBeanException) + (new NotCompliantMBeanException("An interface for the class " + + className + " was not found.").initCause(e)); + } + } + if (!(iface.isInstance(this))) + throw new NotCompliantMBeanException("The instance, " + impl + + ", is not an instance of " + iface); + impl = this; + this.iface = iface; + } + + /** + * Constructs a new {@link StandardMBean} using the specified + * interface and the supplied instance as the implementation. + * + * @param impl the implementation. + * @param iface the interface the bean implements, or null + * if the interface should be determined using the naming + * convention (class X has interface XMBean). + * @throws IllegalArgumentException if impl is null. + * @throws NotCompliantMBeanException if impl doesn't implement + * the interface or a method appears + * in the interface that doesn't comply + * with the naming conventions. + */ + public StandardMBean(Object impl, Class iface) + throws NotCompliantMBeanException + { + if (impl == null) + throw new IllegalArgumentException("The specified implementation is null."); + if (iface == null) + { + String className = impl.getClass().getName(); + try + { + iface = Class.forName(className + "MBean"); + } + catch (ClassNotFoundException e) + { + throw (NotCompliantMBeanException) + (new NotCompliantMBeanException("An interface for the class " + + className + " was not found.").initCause(e)); + } + } + if (!(iface.isInstance(impl))) + throw new NotCompliantMBeanException("The instance, " + impl + + ", is not an instance of " + iface); + this.impl = impl; + this.iface = iface; + } + + /** + * Caches the {@link MBeanInfo} instance for this object. This is a + * customization hook, so that subclasses can choose the caching policy + * used. The default implementation caches the value in the instance + * itself. Subclasses may override this so as to not cache the data + * at all, or so as to use a cache shared between multiple beans. + * + * @param info the {@link MBeanInfo} instance to cache, or null + * if there is no new value to cache. When the value is not + * null, the cache should replace the current value + * with the value supplied here. + * @see #getCachedMBeanInfo() + */ + protected void cacheMBeanInfo(MBeanInfo info) + { + if (info != null) + this.info = info; + } + + /** + * Obtains the value of the specified attribute of the + * management bean. The management bean should perform + * a lookup for the named attribute, and return its value + * by calling the appropriate getter method, if possible. + * + * @param name the name of the attribute to retrieve. + * @return the value of the specified attribute. + * @throws AttributeNotFoundException if the name does not + * correspond to an attribute + * of the bean. + * @throws MBeanException if retrieving the attribute causes + * the bean to throw an exception (which + * becomes the cause of this exception). + * @throws ReflectionException if an exception occurred in trying + * to use the reflection interface + * to lookup the attribute. The + * thrown exception is the cause of + * this exception. + * @see #setAttribute(String) + */ + public Object getAttribute(String name) + throws AttributeNotFoundException, MBeanException, + ReflectionException + { + Method getter; + try + { + getter = iface.getMethod("get" + + name.substring(0, 1).toUpperCase() + + name.substring(1), null); + } + catch (NoSuchMethodException e) + { + try + { + getter = iface.getMethod("is" + + name.substring(0, 1).toUpperCase() + + name.substring(1), null); + } + catch (NoSuchMethodException ex) + { + throw ((AttributeNotFoundException) + new AttributeNotFoundException("The attribute, " + name + + ", was not found.").initCause(ex)); + } + } + Object result; + try + { + result = getter.invoke(impl, null); + } + catch (IllegalAccessException e) + { + throw new ReflectionException(e, "Failed to retrieve " + name); + } + catch (IllegalArgumentException e) + { + throw new ReflectionException(e, "Failed to retrieve " + name); + } + catch (InvocationTargetException e) + { + throw new MBeanException((Exception) e.getCause(), + "The getter of " + name + + " threw an exception"); + } + return result; + } + + /** + * Obtains the values of each of the specified attributes + * of the management bean. The returned list includes + * those attributes that were retrieved and their + * corresponding values. + * + * @param names the names of the attributes to retrieve. + * @return a list of the retrieved attributes. + * @see #setAttributes(AttributeList) + */ + public AttributeList getAttributes(String[] names) + { + AttributeList list = new AttributeList(names.length); + for (int a = 0; a < names.length; ++a) + { + try + { + Object value = getAttribute(names[a]); + list.add(new Attribute(names[a], value)); + } + catch (AttributeNotFoundException e) + { + /* Ignored */ + } + catch (ReflectionException e) + { + /* Ignored */ + } + catch (MBeanException e) + { + /* Ignored */ + } + } + return list; + } + + /** + * Returns the cached {@link MBeanInfo} instance for this object. This is a + * customization hook, so that subclasses can choose the caching policy + * used. The default implementation caches the value in the instance + * itself, and returns this value on calls to this method. + * + * @return the cached {@link MBeanInfo} instance, or null + * if no value is cached. + * @see #cacheMBeanInfo(javax.management.MBeanInfo) + */ + protected MBeanInfo getCachedMBeanInfo() + { + return info; + } + + /** + * Returns the class name that will be used in the {@link MBeanInfo} + * instance. This is a customization hook, so that subclasses can + * provide a custom class name. By default, this returns the class + * name from the supplied {@link MBeanInfo} instance. + * + * @param info the {@link MBeanInfo} instance constructed via + * reflection. + * @return the class name to use in the instance. + */ + protected String getClassName(MBeanInfo info) + { + return info.getClassName(); + } + + /** + * Returns information on the constructors that will be used in + * the {@link MBeanInfo} instance. This is a customization hook, + * so that subclasses can provide their own information on the + * bean's constructors, if necessary. By default, this method + * returns null unless the implementation supplied + * is either null or this. This default + * implementation prevents the use of + * {@link MBeanServer#createMBean} in cases where the bean is + * not created as a subclass of {@link StandardMBean}. + * + * @param constructors the constructor information created via + * reflection. + * @param impl the implementation, or null if this + * should be ignored. + * @return the constructor information to use. + */ + protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[] + constructors, Object impl) + { + if (impl == null || impl == this) + return constructors; + return null; + } + + /** + * Returns the description of the attribute that will be used in + * the supplied {@link MBeanAttributeInfo} instance. This is a + * customization hook, so that subclasses can provide a custom + * description. By default, this calls + * {@link #getDescription(MBeanFeatureInfo)} with the supplied + * {@link MBeanAttributeInfo} instance. + * + * @param info the {@link MBeanAttributeInfo} instance constructed + * via reflection. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanAttributeInfo info) + { + return getDescription((MBeanFeatureInfo) info); + } + + /** + * Returns the description of the constructor that will be used in + * the supplied {@link MBeanConstructorInfo} instance. This is a + * customization hook, so that subclasses can provide a custom + * description. By default, this calls + * {@link #getDescription(MBeanFeatureInfo)} with the supplied + * {@link MBeanConstructorInfo} instance. + * + * @param info the {@link MBeanConstructorInfo} instance constructed + * via reflection. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanConstructorInfo info) + { + return getDescription((MBeanFeatureInfo) info); + } + + /** + * Returns the description of the nth parameter of the constructor + * that will be used in the supplied {@link MBeanParameterInfo} + * instance. This is a customization hook, so that subclasses + * can provide a custom description. By default, this calls + * param.getDescription(). + * + * @param info the {@link MBeanConstructorInfo} instance constructed + * via reflection. + * @param param the {@link MBeanParameterInfo} instance constructed + * via reflection. + * @param n the number of the parameter, in order to link it to the + * information on the constructor. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanConstructorInfo info, + MBeanParameterInfo param, int n) + { + return param.getDescription(); + } + + /** + * Returns the description of the supplied feature that + * will be used in the supplied {@link MBeanFeatureInfo} + * instance. This is a customization hook, so that subclasses + * can provide a custom description. By default, this calls + * info.getDescription(). This method is also called + * by default for the more specific description methods for attributes, + * constructors and operations. + * + * @param info the {@link MBeanFeatureInfo} instance constructed + * via reflection. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanFeatureInfo info) + { + return info.getDescription(); + } + + /** + * Returns the description of the bean that will be used in the + * supplied {@link MBeanInfo} instance. This is a customization + * hook, so that subclasses can provide a custom description. By + * default, this calls info.getDescription(). + * + * @param info the {@link MBeanInfo} instance constructed + * via reflection. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanInfo info) + { + return info.getDescription(); + } + + /** + * Returns the description of the operation that will be used in + * the supplied {@link MBeanOperationInfo} instance. This is a + * customization hook, so that subclasses can provide a custom + * description. By default, this calls + * {@link #getDescription(MBeanFeatureInfo)} with the supplied + * {@link MBeanOperationInfo} instance. + * + * @param info the {@link MBeanOperationInfo} instance constructed + * via reflection. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanOperationInfo info) + { + return getDescription((MBeanFeatureInfo) info); + } + + /** + * Returns the description of the nth parameter of the operation + * that will be used in the supplied {@link MBeanParameterInfo} + * instance. This is a customization hook, so that subclasses + * can provide a custom description. By default, this calls + * param.getDescription(). + * + * @param info the {@link MBeanOperationInfo} instance constructed + * via reflection. + * @param param the {@link MBeanParameterInfo} instance constructed + * via reflection. + * @param n the number of the parameter, in order to link it to the + * information on the operation. + * @return the description to use in the instance. + */ + protected String getDescription(MBeanOperationInfo info, + MBeanParameterInfo param, int n) + { + return param.getDescription(); + } + + /** + * Returns the impact of the operation that will be used in the + * supplied {@link MBeanOperationInfo} instance. This is a + * customization hook, so that subclasses can provide a custom + * impact flag. By default, this returns + * info.getImpact(). + * + * @param info the {@link MBeanOperationInfo} instance constructed + * via reflection. + * @return the impact flag to use in the instance. + */ + protected int getImpact(MBeanOperationInfo info) + { + return info.getImpact(); + } + + /** + * Returns the instance that implements this bean. + * + * @return the implementation. + */ + public Object getImplementation() + { + return impl; + } + + /** + * Returns the class of the instance that implements this bean. + * + * @return the implementation class. + */ + public Class getImplementationClass() + { + return impl.getClass(); + } + + /** + *

+ * Returns an information object which lists the attributes + * and actions associated with the management bean. This + * implementation proceeds as follows: + *

+ *
    + *
  1. {@link #getCachedMBeanInfo()} is called to obtain + * the cached instance. If this returns a non-null value, + * this value is returned.
  2. + *
  3. If there is no cached value, then the method proceeds + * to create one. During this process, the customization hooks + * detailed in this class are called to allow the values used + * to be overrided: + *
      + *
    • For each attribute, + * {@link #getDescription(MBeanAttributeInfo)} is called.
    • + *
    • For each constructor, + * {@link #getDescription(MBeanConstructorInfo)} is called, + * along with {@link #getDescription(MBeanConstructorInfo, + * MBeanParameterInfo, int)} and + * {@link #getParameterName(MBeanConstructorInfo, + * MBeanParameterInfo, int)} for each parameter.
    • + *
    • The constructors may be replaced as a whole by + * a call to + * {@link #getConstructors(MBeanConstructorInfo[], Object)}.
    • + *
    • For each operation, + * {@link #getDescription(MBeanOperationInfo)} and + * {@link #getImpact(MBeanOperationInfo)} are called, + * along with {@link #getDescription(MBeanOperationInfo, + * MBeanParameterInfo, int)} and + * {@link #getParameterName(MBeanOperationInfo, + * MBeanParameterInfo, int)} for each parameter.
    • + *
    • {@link #getClassName(MBeanInfo)} and + * {@link #getDescription(MBeanInfo)} are called to customise + * the basic information about the class.
    • + *
    + *
  4. + *
  5. Finally, {@link #cacheMBeanInfo(MBeanInfo)} is called + * with the created instance before it is returned.
  6. + *
+ * + * @return a description of the management bean, including + * all exposed attributes and actions. + */ + public MBeanInfo getMBeanInfo() + { + MBeanInfo info = getCachedMBeanInfo(); + if (info != null) + return info; + Method[] methods = iface.getMethods(); + Map attributes = new HashMap(); + List operations = new ArrayList(); + for (int a = 0; a < methods.length; ++a) + { + String name = methods[a].getName(); + if (((name.startsWith("get") && + methods[a].getReturnType() != Void.TYPE) || + (name.startsWith("is") && + methods[a].getReturnType() == Boolean.TYPE)) && + methods[a].getParameterTypes().length == 0) + { + Method[] amethods; + String attrib; + if (name.startsWith("is")) + attrib = name.substring(2,3).toLowerCase() + + name.substring(3); + else + attrib = name.substring(3,4).toLowerCase() + + name.substring(4); + if (attributes.containsKey(attrib)) + amethods = (Method[]) attributes.get(attrib); + else + { + amethods = new Method[2]; + attributes.put(attrib, amethods); + } + amethods[0] = methods[a]; + } + else if (name.startsWith("set") && + methods[a].getReturnType() == Void.TYPE && + methods[a].getParameterTypes().length == 1) + { + Method[] amethods; + String attrib = name.substring(3,4).toLowerCase() + + name.substring(4); + if (attributes.containsKey(attrib)) + amethods = (Method[]) attributes.get(attrib); + else + { + amethods = new Method[2]; + attributes.put(attrib, amethods); + } + amethods[1] = methods[a]; + } + else + operations.add(new MBeanOperationInfo("", methods[a])); + } + List attribs = new ArrayList(attributes.size()); + Iterator it = attributes.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry entry = (Map.Entry) it.next(); + Method[] amethods = (Method[]) entry.getValue(); + try + { + attribs.add(new MBeanAttributeInfo((String) entry.getKey(), "", + amethods[0], amethods[1])); + } + catch (IntrospectionException e) + { + /* Shouldn't happen; both shouldn't be null */ + throw new IllegalStateException("The two methods passed to " + + "the MBeanAttributeInfo " + + "constructor for " + entry + + "were null.", e); + } + } + MBeanAttributeInfo[] ainfo = new MBeanAttributeInfo[attribs.size()]; + for (int a = 0; a < ainfo.length; ++a) + { + MBeanAttributeInfo oldInfo = (MBeanAttributeInfo) attribs.get(a); + String desc = getDescription(oldInfo); + ainfo[a] = new MBeanAttributeInfo(oldInfo.getName(), + oldInfo.getType(), desc, + oldInfo.isReadable(), + oldInfo.isWritable(), + oldInfo.isIs()); + } + Constructor[] cons = impl.getClass().getConstructors(); + MBeanConstructorInfo[] cinfo = new MBeanConstructorInfo[cons.length]; + for (int a = 0; a < cinfo.length; ++a) + { + MBeanConstructorInfo oldInfo = new MBeanConstructorInfo("", cons[a]); + String desc = getDescription(oldInfo); + MBeanParameterInfo[] params = oldInfo.getSignature(); + MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length]; + for (int b = 0; b < pinfo.length; ++b) + { + String pdesc = getDescription(oldInfo, params[b], b); + String pname = getParameterName(oldInfo, params[b], b); + pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(), + pdesc); + } + cinfo[a] = new MBeanConstructorInfo(oldInfo.getName(), desc, + pinfo); + } + cinfo = getConstructors(cinfo, impl); + MBeanOperationInfo[] oinfo = new MBeanOperationInfo[operations.size()]; + for (int a = 0; a < oinfo.length; ++a) + { + MBeanOperationInfo oldInfo = (MBeanOperationInfo) operations.get(a); + String desc = getDescription(oldInfo); + int impact = getImpact(oldInfo); + MBeanParameterInfo[] params = oldInfo.getSignature(); + MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length]; + for (int b = 0; b < pinfo.length; ++b) + { + String pdesc = getDescription(oldInfo, params[b], b); + String pname = getParameterName(oldInfo, params[b], b); + pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(), + pdesc); + } + oinfo[a] = new MBeanOperationInfo(oldInfo.getName(), desc, pinfo, + oldInfo.getReturnType(), impact); + } + info = new MBeanInfo(impl.getClass().getName(), "", ainfo, cinfo, + oinfo, null); + String cname = getClassName(info); + String desc = getDescription(info); + info = new MBeanInfo(cname, desc, ainfo, cinfo, oinfo, null); + cacheMBeanInfo(info); + return info; + } + + /** + * Returns the interface for this management bean. + * + * @return the management interface. + */ + public Class getMBeanInterface() + { + return iface; + } + + /** + * Returns the name of the nth parameter of the constructor + * that will be used in the supplied {@link MBeanParameterInfo} + * instance. This is a customization hook, so that subclasses + * can provide a custom name. By default, this calls + * param.getName(). + * + * @param info the {@link MBeanConstructorInfo} instance constructed + * via reflection. + * @param param the {@link MBeanParameterInfo} instance constructed + * via reflection. + * @param n the number of the parameter, in order to link it to the + * information on the constructor. + * @return the name to use in the instance. + */ + protected String getParameterName(MBeanConstructorInfo info, + MBeanParameterInfo param, int n) + { + return param.getName(); + } + + /** + * Returns the name of the nth parameter of the operation + * that will be used in the supplied {@link MBeanParameterInfo} + * instance. This is a customization hook, so that subclasses + * can provide a custom name. By default, this calls + * param.getName(). + * + * @param info the {@link MBeanOperationInfo} instance constructed + * via reflection. + * @param param the {@link MBeanParameterInfo} instance constructed + * via reflection. + * @param n the number of the parameter, in order to link it to the + * information on the operation. + * @return the name to use in the instance. + */ + protected String getParameterName(MBeanOperationInfo info, + MBeanParameterInfo param, int n) + { + return param.getName(); + } + + /** + * Invokes the specified action on the management bean using + * the supplied parameters. The signature of the action is + * specified by a {@link String} array, which lists the classes + * corresponding to each parameter. The class loader used to + * load these classes is the same as that used for loading the + * management bean itself. + * + * @param name the name of the action to invoke. + * @param params the parameters used to call the action. + * @param signature the signature of the action. + * @return the return value of the action. + * @throws MBeanException if the action throws an exception. The + * thrown exception is the cause of this + * exception. + * @throws ReflectionException if an exception occurred in trying + * to use the reflection interface + * to invoke the action. The + * thrown exception is the cause of + * this exception. + */ + public Object invoke(String name, Object[] params, String[] signature) + throws MBeanException, ReflectionException + { + Class[] sigTypes = new Class[signature.length]; + ClassLoader loader = getClass().getClassLoader(); + for (int a = 0; a < signature.length; ++a) + try + { + sigTypes[a] = Class.forName(signature[a], true, loader); + } + catch (ClassNotFoundException e) + { + throw new ReflectionException(e, "The class, " + signature[a] + + ", in the method signature " + + "could not be loaded."); + } + Method method; + try + { + method = iface.getMethod(name, sigTypes); + } + catch (NoSuchMethodException e) + { + throw new ReflectionException(e, "The method, " + name + + ", could not be found."); + } + Object result; + try + { + result = method.invoke(impl, params); + } + catch (IllegalAccessException e) + { + throw new ReflectionException(e, "Failed to call " + name); + } + catch (IllegalArgumentException e) + { + throw new ReflectionException(e, "Failed to call " + name); + } + catch (InvocationTargetException e) + { + throw new MBeanException((Exception) e.getCause(), "The method " + + name + " threw an exception"); + } + return result; + } + + /** + * Sets the value of the specified attribute of the + * management bean. The management bean should perform + * a lookup for the named attribute, and sets its value + * using the associated setter method, if possible. + * + * @param attribute the attribute to set. + * @throws AttributeNotFoundException if the attribute does not + * correspond to an attribute + * of the bean. + * @throws InvalidAttributeValueException if the value is invalid + * for this particular + * attribute of the bean. + * @throws MBeanException if setting the attribute causes + * the bean to throw an exception (which + * becomes the cause of this exception). + * @throws ReflectionException if an exception occurred in trying + * to use the reflection interface + * to lookup the attribute. The + * thrown exception is the cause of + * this exception. + * @see #getAttribute(String) + */ + public void setAttribute(Attribute attribute) + throws AttributeNotFoundException, InvalidAttributeValueException, + MBeanException, ReflectionException + { + Method setter; + String name = attribute.getName(); + try + { + setter = iface.getMethod("set" + + name.substring(0, 1).toUpperCase() + + name.substring(1), null); + } + catch (NoSuchMethodException e) + { + throw ((AttributeNotFoundException) + new AttributeNotFoundException("The attribute, " + name + + ", was not found.").initCause(e)); + } + try + { + setter.invoke(impl, new Object[] { attribute.getValue() }); + } + catch (IllegalAccessException e) + { + throw new ReflectionException(e, "Failed to set " + name); + } + catch (IllegalArgumentException e) + { + throw ((InvalidAttributeValueException) + new InvalidAttributeValueException(attribute.getValue() + + " is an invalid value for " + + name).initCause(e)); + } + catch (InvocationTargetException e) + { + throw new MBeanException((Exception) e.getCause(), "The getter of " + + name + " threw an exception"); + } + } + + /** + * Sets the value of each of the specified attributes + * to that supplied by the {@link Attribute} object. + * The returned list contains the attributes that were + * set and their new values. + * + * @param attributes the attributes to set. + * @return a list of the changed attributes. + * @see #getAttributes(AttributeList) + */ + public AttributeList setAttributes(AttributeList attributes) + { + AttributeList list = new AttributeList(attributes.size()); + Iterator it = attributes.iterator(); + while (it.hasNext()) + { + try + { + Attribute attrib = (Attribute) it.next(); + setAttribute(attrib); + list.add(attrib); + } + catch (AttributeNotFoundException e) + { + /* Ignored */ + } + catch (InvalidAttributeValueException e) + { + /* Ignored */ + } + catch (ReflectionException e) + { + /* Ignored */ + } + catch (MBeanException e) + { + /* Ignored */ + } + } + return list; + } + + /** + * Replaces the implementation of the interface used by this + * instance with the one specified. The new implementation + * must be non-null and implement the interface specified on + * construction of this instance. + * + * @throws IllegalArgumentException if impl is null. + * @throws NotCompliantMBeanException if impl doesn't implement + * the interface or a method appears + * in the interface that doesn't comply + * with the naming conventions. + */ + public void setImplementation(Object impl) + throws NotCompliantMBeanException + { + if (impl == null) + throw new IllegalArgumentException("The specified implementation is null."); + if (!(iface.isInstance(impl))) + throw new NotCompliantMBeanException("The instance, " + impl + + ", is not an instance of " + iface); + this.impl = impl; + } + +} -- cgit v1.2.1