| /* BeanImpl.java - A common superclass for bean implementations. |
| Copyright (C) 2006 Free Software Foundation |
| |
| 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 gnu.java.lang.management; |
| |
| import gnu.javax.management.Translator; |
| |
| import java.lang.management.ManagementPermission; |
| |
| import java.lang.reflect.Array; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.management.AttributeNotFoundException; |
| import javax.management.MBeanAttributeInfo; |
| import javax.management.MBeanConstructorInfo; |
| import javax.management.MBeanException; |
| import javax.management.MBeanInfo; |
| import javax.management.MBeanOperationInfo; |
| import javax.management.MBeanParameterInfo; |
| import javax.management.NotCompliantMBeanException; |
| import javax.management.ReflectionException; |
| import javax.management.StandardMBean; |
| |
| import javax.management.openmbean.ArrayType; |
| import javax.management.openmbean.CompositeDataSupport; |
| import javax.management.openmbean.CompositeType; |
| import javax.management.openmbean.OpenDataException; |
| import javax.management.openmbean.OpenMBeanAttributeInfo; |
| import javax.management.openmbean.OpenMBeanAttributeInfoSupport; |
| import javax.management.openmbean.OpenMBeanConstructorInfo; |
| import javax.management.openmbean.OpenMBeanConstructorInfoSupport; |
| import javax.management.openmbean.OpenMBeanInfo; |
| import javax.management.openmbean.OpenMBeanInfoSupport; |
| import javax.management.openmbean.OpenMBeanOperationInfo; |
| import javax.management.openmbean.OpenMBeanOperationInfoSupport; |
| import javax.management.openmbean.OpenMBeanParameterInfo; |
| import javax.management.openmbean.OpenMBeanParameterInfoSupport; |
| import javax.management.openmbean.OpenType; |
| import javax.management.openmbean.TabularData; |
| import javax.management.openmbean.TabularDataSupport; |
| import javax.management.openmbean.TabularType; |
| |
| /** |
| * A common superclass for bean implementations. |
| * |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) |
| * @since 1.5 |
| */ |
| public class BeanImpl |
| extends StandardMBean |
| { |
| |
| /** |
| * Cached open bean information. |
| */ |
| private OpenMBeanInfo openInfo; |
| |
| /** |
| * Constructs a new <code>BeanImpl</code>. |
| * |
| * @param iface the bean interface being implemented. |
| * @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 BeanImpl(Class iface) |
| throws NotCompliantMBeanException |
| { |
| super(iface); |
| } |
| |
| protected void cacheMBeanInfo(MBeanInfo info) |
| { |
| if (info == null) |
| return; |
| try |
| { |
| MBeanAttributeInfo[] oldA = info.getAttributes(); |
| OpenMBeanAttributeInfo[] attribs = |
| new OpenMBeanAttributeInfoSupport[oldA.length]; |
| for (int a = 0; a < oldA.length; ++a) |
| { |
| OpenMBeanParameterInfo param = Translator.translate(oldA[a].getType()); |
| if (param.getMinValue() == null) |
| { |
| Object[] lv; |
| if (param.getLegalValues() == null) |
| lv = null; |
| else |
| lv = param.getLegalValues().toArray(); |
| attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(), |
| oldA[a].getDescription(), |
| ((OpenType<Object>) |
| param.getOpenType()), |
| oldA[a].isReadable(), |
| oldA[a].isWritable(), |
| oldA[a].isIs(), |
| param.getDefaultValue(), |
| lv); |
| } |
| else |
| attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(), |
| oldA[a].getDescription(), |
| ((OpenType<Object>) |
| param.getOpenType()), |
| oldA[a].isReadable(), |
| oldA[a].isWritable(), |
| oldA[a].isIs(), |
| param.getDefaultValue(), |
| ((Comparable<Object>) |
| param.getMinValue()), |
| ((Comparable<Object>) |
| param.getMaxValue())); |
| } |
| MBeanConstructorInfo[] oldC = info.getConstructors(); |
| OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length]; |
| for (int a = 0; a < oldC.length; ++a) |
| cons[a] = |
| new OpenMBeanConstructorInfoSupport(oldC[a].getName(), |
| oldC[a].getDescription(), |
| translateSignature(oldC[a].getSignature())); |
| MBeanOperationInfo[] oldO = info.getOperations(); |
| OpenMBeanOperationInfo[] ops = new OpenMBeanOperationInfoSupport[oldO.length]; |
| for (int a = 0; a < oldO.length; ++a) |
| ops[a] = |
| new OpenMBeanOperationInfoSupport(oldO[a].getName(), |
| oldO[a].getDescription(), |
| translateSignature(oldO[a].getSignature()), |
| Translator.translate(oldO[a].getReturnType()).getOpenType(), |
| oldO[a].getImpact()); |
| openInfo = new OpenMBeanInfoSupport(info.getClassName(), info.getDescription(), |
| attribs, cons, ops, info.getNotifications()); |
| } |
| catch (OpenDataException e) |
| { |
| throw (InternalError) (new InternalError("A problem occurred creating the open type " + |
| "descriptors.").initCause(e)); |
| } |
| } |
| |
| protected void checkMonitorPermissions() |
| { |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| sm.checkPermission(new ManagementPermission("monitor")); |
| } |
| |
| protected void checkControlPermissions() |
| { |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| sm.checkPermission(new ManagementPermission("control")); |
| } |
| |
| public Object getAttribute(String attribute) |
| throws AttributeNotFoundException, MBeanException, |
| ReflectionException |
| { |
| Object value = super.getAttribute(attribute); |
| if (value instanceof Enum) |
| return ((Enum) value).name(); |
| Class vClass = value.getClass(); |
| if (vClass.isArray()) |
| vClass = vClass.getComponentType(); |
| String cName = vClass.getName(); |
| String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES; |
| for (int a = 0; a < allowedTypes.length; ++a) |
| if (cName.equals(allowedTypes[a])) |
| return value; |
| OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo(); |
| MBeanAttributeInfo[] attribs = |
| (MBeanAttributeInfo[]) info.getAttributes(); |
| OpenType type = null; |
| for (int a = 0; a < attribs.length; ++a) |
| if (attribs[a].getName().equals(attribute)) |
| type = ((OpenMBeanAttributeInfo) attribs[a]).getOpenType(); |
| if (value instanceof List) |
| { |
| try |
| { |
| Class e = |
| Class.forName(((ArrayType) type).getElementOpenType().getClassName()); |
| List l = (List) value; |
| Object[] array = (Object[]) Array.newInstance(e, l.size()); |
| return l.toArray(array); |
| } |
| catch (ClassNotFoundException e) |
| { |
| throw (InternalError) (new InternalError("The class of the list " + |
| "element type could not " + |
| "be created").initCause(e)); |
| } |
| } |
| if (value instanceof Map) |
| { |
| TabularType ttype = (TabularType) type; |
| TabularData data = new TabularDataSupport(ttype); |
| Iterator it = ((Map) value).entrySet().iterator(); |
| while (it.hasNext()) |
| { |
| Map.Entry entry = (Map.Entry) it.next(); |
| try |
| { |
| data.put(new CompositeDataSupport(ttype.getRowType(), |
| new String[] { |
| "key", |
| "value" |
| }, |
| new Object[] { |
| entry.getKey(), |
| entry.getValue() |
| })); |
| } |
| catch (OpenDataException e) |
| { |
| throw (InternalError) (new InternalError("A problem occurred " + |
| "converting the map " + |
| "to a composite data " + |
| "structure.").initCause(e)); |
| } |
| } |
| return data; |
| } |
| CompositeType cType = (CompositeType) type; |
| Set names = cType.keySet(); |
| Iterator it = names.iterator(); |
| List values = new ArrayList(names.size()); |
| while (it.hasNext()) |
| { |
| String field = (String) it.next(); |
| Method getter = null; |
| try |
| { |
| getter = vClass.getMethod("get" + field); |
| } |
| catch (NoSuchMethodException e) |
| { |
| /* Ignored; the type tells us it's there. */ |
| } |
| try |
| { |
| values.add(getter.invoke(value)); |
| } |
| catch (IllegalAccessException e) |
| { |
| throw new ReflectionException(e, "Failed to retrieve " + field); |
| } |
| catch (IllegalArgumentException e) |
| { |
| throw new ReflectionException(e, "Failed to retrieve " + field); |
| } |
| catch (InvocationTargetException e) |
| { |
| throw new MBeanException((Exception) e.getCause(), |
| "The getter of " + field + |
| " threw an exception"); |
| } |
| } |
| try |
| { |
| return new CompositeDataSupport(cType, |
| (String[]) |
| names.toArray(new String[names.size()]), |
| values.toArray()); |
| } |
| catch (OpenDataException e) |
| { |
| throw (InternalError) (new InternalError("A problem occurred " + |
| "converting the value " + |
| "to a composite data " + |
| "structure.").initCause(e)); |
| } |
| } |
| |
| protected MBeanInfo getCachedMBeanInfo() |
| { |
| return (MBeanInfo) openInfo; |
| } |
| |
| /** |
| * Override this method so as to prevent the description of a constructor's |
| * parameter being @code{null}. Open MBeans can not have @code{null} descriptions, |
| * but one will occur as the names of parameters aren't stored for reflection. |
| * |
| * @param constructor the constructor whose parameter needs describing. |
| * @param parameter the parameter to be described. |
| * @param sequenceNo the number of the parameter to describe. |
| * @return a description of the constructor's parameter. |
| */ |
| protected String getDescription(MBeanConstructorInfo constructor, |
| MBeanParameterInfo parameter, |
| int sequenceNo) |
| { |
| String desc = parameter.getDescription(); |
| if (desc == null) |
| return "param" + sequenceNo; |
| else |
| return desc; |
| } |
| |
| /** |
| * Override this method so as to prevent the description of an operation's |
| * parameter being @code{null}. Open MBeans can not have @code{null} descriptions, |
| * but one will occur as the names of parameters aren't stored for reflection. |
| * |
| * @param operation the operation whose parameter needs describing. |
| * @param parameter the parameter to be described. |
| * @param sequenceNo the number of the parameter to describe. |
| * @return a description of the operation's parameter. |
| */ |
| protected String getDescription(MBeanOperationInfo operation, |
| MBeanParameterInfo parameter, |
| int sequenceNo) |
| { |
| String desc = parameter.getDescription(); |
| if (desc == null) |
| return "param" + sequenceNo; |
| else |
| return desc; |
| } |
| |
| /** |
| * Override this method so as to prevent the name of a constructor's |
| * parameter being @code{null}. Open MBeans can not have @code{null} names, |
| * but one will occur as the names of parameters aren't stored for reflection. |
| * |
| * @param constructor the constructor whose parameter needs a name. |
| * @param parameter the parameter to be named. |
| * @param sequenceNo the number of the parameter to name. |
| * @return a description of the constructor's parameter. |
| */ |
| protected String getParameterName(MBeanConstructorInfo constructor, |
| MBeanParameterInfo parameter, |
| int sequenceNo) |
| { |
| String name = parameter.getName(); |
| if (name == null) |
| return "param" + sequenceNo; |
| else |
| return name; |
| } |
| |
| /** |
| * Override this method so as to prevent the name of an operation's |
| * parameter being @code{null}. Open MBeans can not have @code{null} names, |
| * but one will occur as the names of parameters aren't stored for reflection. |
| * |
| * @param operation the operation whose parameter needs a name. |
| * @param parameter the parameter to be named. |
| * @param sequenceNo the number of the parameter to name. |
| * @return a description of the operation's parameter. |
| */ |
| protected String getParameterName(MBeanOperationInfo operation, |
| MBeanParameterInfo parameter, |
| int sequenceNo) |
| { |
| String name = parameter.getName(); |
| if (name == null) |
| return "param" + sequenceNo; |
| else |
| return name; |
| } |
| |
| public MBeanInfo getMBeanInfo() |
| { |
| super.getMBeanInfo(); |
| return getCachedMBeanInfo(); |
| } |
| |
| private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS) |
| throws OpenDataException |
| { |
| OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length]; |
| for (int a = 0; a < oldS.length; ++a) |
| { |
| OpenMBeanParameterInfo param = Translator.translate(oldS[a].getType()); |
| if (param.getMinValue() == null) |
| { |
| Object[] lv; |
| if (param.getLegalValues() == null) |
| lv = null; |
| else |
| lv = param.getLegalValues().toArray(); |
| sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(), |
| oldS[a].getDescription(), |
| ((OpenType<Object>) |
| param.getOpenType()), |
| param.getDefaultValue(), |
| lv); |
| } |
| else |
| sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(), |
| oldS[a].getDescription(), |
| ((OpenType<Object>) |
| param.getOpenType()), |
| param.getDefaultValue(), |
| ((Comparable<Object>) |
| param.getMinValue()), |
| ((Comparable<Object>) |
| param.getMaxValue())); |
| } |
| return sig; |
| } |
| |
| |
| } |