| /* 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 <code>this</code> as the instance. This should |
| * be used to create an instance via subclassing. |
| * |
| * @param iface the interface this bean implements, or <code>null</code> |
| * 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 <code>null</code> |
| * if the interface should be determined using the naming |
| * convention (class X has interface XMBean). |
| * @throws IllegalArgumentException if <code>impl</code> is <code>null</code>. |
| * @throws NotCompliantMBeanException if <code>impl</code> 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 <code>null</code> |
| * if there is no new value to cache. When the value is not |
| * <code>null</code>, 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 <code>null</code> |
| * 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 <code>null</code> unless the implementation supplied |
| * is either <code>null</code> or <code>this</code>. 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 <code>null</code> 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 |
| * <code>param.getDescription()</code>. |
| * |
| * @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 |
| * <code>info.getDescription()</code>. 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 <code>info.getDescription()</code>. |
| * |
| * @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 |
| * <code>param.getDescription()</code>. |
| * |
| * @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 |
| * <code>info.getImpact()</code>. |
| * |
| * @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(); |
| } |
| |
| /** |
| * <p> |
| * Returns an information object which lists the attributes |
| * and actions associated with the management bean. This |
| * implementation proceeds as follows: |
| * </p> |
| * <ol> |
| * <li>{@link #getCachedMBeanInfo()} is called to obtain |
| * the cached instance. If this returns a non-null value, |
| * this value is returned.</li> |
| * <li>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: |
| * <ul> |
| * <li>For each attribute, |
| * {@link #getDescription(MBeanAttributeInfo)} is called.</li> |
| * <li>For each constructor, |
| * {@link #getDescription(MBeanConstructorInfo)} is called, |
| * along with {@link #getDescription(MBeanConstructorInfo, |
| * MBeanParameterInfo, int)} and |
| * {@link #getParameterName(MBeanConstructorInfo, |
| * MBeanParameterInfo, int)} for each parameter.</li> |
| * <li>The constructors may be replaced as a whole by |
| * a call to |
| * {@link #getConstructors(MBeanConstructorInfo[], Object)}.</li> |
| * <li>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.</li> |
| * <li>{@link #getClassName(MBeanInfo)} and |
| * {@link #getDescription(MBeanInfo)} are called to customise |
| * the basic information about the class.</li> |
| * </ul> |
| * </li> |
| * <li>Finally, {@link #cacheMBeanInfo(MBeanInfo)} is called |
| * with the created instance before it is returned.</li> |
| * </ol> |
| * |
| * @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 |
| * <code>param.getName()</code>. |
| * |
| * @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 |
| * <code>param.getName()</code>. |
| * |
| * @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 <code>impl</code> is <code>null</code>. |
| * @throws NotCompliantMBeanException if <code>impl</code> 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; |
| } |
| |
| } |