1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084 |
- /* 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)
- {
- for (Class<?> nextIface : getClass().getInterfaces())
- {
- if (JMX.isMXBeanInterface(nextIface))
- {
- iface = nextIface;
- break;
- }
- }
- if (iface == null)
- 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 <T> StandardMBean(T impl, Class<T> iface)
- throws NotCompliantMBeanException
- {
- if (impl == null)
- throw new IllegalArgumentException("The specified implementation is null.");
- if (iface == null)
- {
- Class<?> implClass = impl.getClass();
- String className = implClass.getName();
- try
- {
- this.iface = Class.forName(className + "MBean", true,
- implClass.getClassLoader());
- }
- catch (ClassNotFoundException e)
- {
- for (Class<?> nextIface : implClass.getInterfaces())
- {
- if (JMX.isMXBeanInterface(nextIface))
- {
- this.iface = nextIface;
- break;
- }
- }
- if (this.iface == null)
- throw (NotCompliantMBeanException)
- (new NotCompliantMBeanException("An interface for the class " +
- className +
- " was not found.").initCause(e));
- }
- }
- else
- this.iface = iface;
- if (!(this.iface.isInstance(impl)))
- throw new NotCompliantMBeanException("The instance, " + impl +
- ", is not an instance of " + iface);
- this.impl = impl;
- }
- /**
- * 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);
- }
- catch (NoSuchMethodException e)
- {
- try
- {
- getter = iface.getMethod("is" + name);
- }
- catch (NoSuchMethodException ex)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(ex));
- }
- }
- Object result;
- try
- {
- result = getter.invoke(impl);
- }
- 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<String,Method[]> attributes = new HashMap<String,Method[]>();
- List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
- 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);
- else
- attrib = name.substring(3);
- 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);
- 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].getName(),
- methods[a]));
- }
- List<MBeanAttributeInfo> attribs = new ArrayList<MBeanAttributeInfo>(attributes.size());
- for (Map.Entry<String,Method[]> entry : attributes.entrySet())
- {
- Method[] amethods = entry.getValue();
- try
- {
- attribs.add(new MBeanAttributeInfo(entry.getKey(),
- 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].getName(),
- 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(), impl.getClass().getName(),
- ainfo, cinfo, oinfo, null);
- String cname = getClassName(info);
- String desc = getDescription(info);
- MBeanNotificationInfo[] ninfo = null;
- if (impl instanceof NotificationBroadcaster)
- ninfo = ((NotificationBroadcaster) impl).getNotificationInfo();
- info = new MBeanInfo(cname, desc, ainfo, cinfo, oinfo, ninfo);
- cacheMBeanInfo(info);
- return info;
- }
- /**
- * Returns the interface for this management bean.
- *
- * @return the management interface.
- */
- public final 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
- {
- if (name.startsWith("get") || name.startsWith("is") ||
- name.startsWith("set"))
- throw new ReflectionException(new NoSuchMethodException(),
- "Invocation of an attribute " +
- "method is disallowed.");
- ClassLoader loader = getClass().getClassLoader();
- Class<?>[] sigTypes;
- if (signature != null)
- {
- sigTypes = new Class<?>[signature.length];
- 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.");
- }
- }
- else
- sigTypes = null;
- 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
- {
- String name = attribute.getName();
- String attName = name.substring(0, 1).toUpperCase() + name.substring(1);
- Object val = attribute.getValue();
- try
- {
- getMutator(attName, val.getClass()).invoke(impl, new Object[] { val });
- }
- 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(e, "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<Object> 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;
- }
- /**
- * Returns the mutator method for a particular attribute name
- * with a parameter type matching that of the given value.
- *
- * @param name the name of the attribute.
- * @param type the type of the parameter.
- * @return the appropriate mutator method.
- * @throws AttributeNotFoundException if a method can't be found.
- */
- private Method getMutator(String name, Class<?> type)
- throws AttributeNotFoundException
- {
- String mutator = "set" + name;
- Exception ex = null;
- try
- {
- return iface.getMethod(mutator, type);
- }
- catch (NoSuchMethodException e)
- {
- /* Ignored; we'll try harder instead */
- ex = e;
- }
- /* Special cases */
- if (type == Boolean.class)
- try
- {
- return iface.getMethod(mutator, Boolean.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Byte.class)
- try
- {
- return iface.getMethod(mutator, Byte.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Character.class)
- try
- {
- return iface.getMethod(mutator, Character.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Double.class)
- try
- {
- return iface.getMethod(mutator, Double.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Float.class)
- try
- {
- return iface.getMethod(mutator, Float.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Integer.class)
- try
- {
- return iface.getMethod(mutator, Integer.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Long.class)
- try
- {
- return iface.getMethod(mutator, Long.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- if (type == Short.class)
- try
- {
- return iface.getMethod(mutator, Short.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(e));
- }
- /* Superclasses and interfaces */
- for (Class<?> i : type.getInterfaces())
- try
- {
- return getMutator(name, i);
- }
- catch (AttributeNotFoundException e)
- {
- ex = e;
- }
- Class<?> sclass = type.getSuperclass();
- if (sclass != null && sclass != Object.class)
- try
- {
- return getMutator(name, sclass);
- }
- catch (AttributeNotFoundException e)
- {
- ex = e;
- }
- /* If we get this far, give up */
- throw ((AttributeNotFoundException)
- new AttributeNotFoundException("The attribute, " + name +
- ", was not found.").initCause(ex));
- }
- }
|