1 /* BeanImpl.java - A common superclass for bean implementations.
2 Copyright (C) 2006 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.java.lang.management;
40 import java.lang.management.ManagementPermission;
42 import java.lang.reflect.Array;
43 import java.lang.reflect.Method;
44 import java.lang.reflect.InvocationTargetException;
45 import java.lang.reflect.TypeVariable;
47 import java.util.ArrayList;
48 import java.util.Iterator;
49 import java.util.List;
53 import javax.management.AttributeNotFoundException;
54 import javax.management.MBeanAttributeInfo;
55 import javax.management.MBeanConstructorInfo;
56 import javax.management.MBeanException;
57 import javax.management.MBeanInfo;
58 import javax.management.MBeanOperationInfo;
59 import javax.management.MBeanParameterInfo;
60 import javax.management.MBeanInfo;
61 import javax.management.NotCompliantMBeanException;
62 import javax.management.ReflectionException;
63 import javax.management.StandardMBean;
65 import javax.management.openmbean.ArrayType;
66 import javax.management.openmbean.CompositeData;
67 import javax.management.openmbean.CompositeDataSupport;
68 import javax.management.openmbean.CompositeType;
69 import javax.management.openmbean.OpenDataException;
70 import javax.management.openmbean.OpenMBeanAttributeInfo;
71 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
72 import javax.management.openmbean.OpenMBeanConstructorInfo;
73 import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
74 import javax.management.openmbean.OpenMBeanInfo;
75 import javax.management.openmbean.OpenMBeanInfoSupport;
76 import javax.management.openmbean.OpenMBeanOperationInfo;
77 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
78 import javax.management.openmbean.OpenMBeanParameterInfo;
79 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
80 import javax.management.openmbean.OpenType;
81 import javax.management.openmbean.SimpleType;
82 import javax.management.openmbean.TabularData;
83 import javax.management.openmbean.TabularDataSupport;
84 import javax.management.openmbean.TabularType;
87 * A common superclass for bean implementations.
89 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
97 * Cached open bean information.
99 private OpenMBeanInfo openInfo;
102 * Constructs a new <code>BeanImpl</code>.
104 * @param iface the bean interface being implemented.
105 * @throws NotCompliantMBeanException if this class doesn't implement
106 * the interface or a method appears
107 * in the interface that doesn't comply
108 * with the naming conventions.
110 protected BeanImpl(Class iface)
111 throws NotCompliantMBeanException
116 protected void cacheMBeanInfo(MBeanInfo info)
122 MBeanAttributeInfo[] oldA = info.getAttributes();
123 OpenMBeanAttributeInfo[] attribs =
124 new OpenMBeanAttributeInfoSupport[oldA.length];
125 for (int a = 0; a < oldA.length; ++a)
127 OpenMBeanParameterInfo param = translate(oldA[a].getType());
128 if (param.getMinValue() == null)
131 if (param.getLegalValues() == null)
134 lv = param.getLegalValues().toArray();
135 attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
136 oldA[a].getDescription(),
138 oldA[a].isReadable(),
139 oldA[a].isWritable(),
141 param.getDefaultValue(),
145 attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
146 oldA[a].getDescription(),
148 oldA[a].isReadable(),
149 oldA[a].isWritable(),
151 param.getDefaultValue(),
153 param.getMaxValue());
155 MBeanConstructorInfo[] oldC = info.getConstructors();
156 OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length];
157 for (int a = 0; a < oldC.length; ++a)
159 new OpenMBeanConstructorInfoSupport(oldC[a].getName(),
160 oldC[a].getDescription(),
161 translateSignature(oldC[a].getSignature()));
162 MBeanOperationInfo[] oldO = info.getOperations();
163 OpenMBeanOperationInfo[] ops = new OpenMBeanOperationInfoSupport[oldO.length];
164 for (int a = 0; a < oldO.length; ++a)
166 new OpenMBeanOperationInfoSupport(oldO[a].getName(),
167 oldO[a].getDescription(),
168 translateSignature(oldO[a].getSignature()),
169 translate(oldO[a].getReturnType()).getOpenType(),
170 oldO[a].getImpact());
171 openInfo = new OpenMBeanInfoSupport(info.getClassName(), info.getDescription(),
172 attribs, cons, ops, info.getNotifications());
174 catch (OpenDataException e)
176 throw (InternalError) (new InternalError("A problem occurred creating the open type " +
177 "descriptors.").initCause(e));
181 protected void checkMonitorPermissions()
183 SecurityManager sm = System.getSecurityManager();
185 sm.checkPermission(new ManagementPermission("monitor"));
188 protected void checkControlPermissions()
190 SecurityManager sm = System.getSecurityManager();
192 sm.checkPermission(new ManagementPermission("control"));
195 public Object getAttribute(String attribute)
196 throws AttributeNotFoundException, MBeanException,
199 Object value = super.getAttribute(attribute);
200 if (value instanceof Enum)
201 return ((Enum) value).name();
202 Class vClass = value.getClass();
203 if (vClass.isArray())
205 String cName = vClass.getName();
206 String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES;
207 for (int a = 0; a < allowedTypes.length; ++a)
208 if (cName.equals(allowedTypes[a]))
210 if (value instanceof List)
212 List l = (List) value;
214 TypeVariable[] vars = vClass.getTypeParameters();
215 for (int a = 0; a < vars.length; ++a)
216 if (vars[a].getName().equals("E"))
217 e = (Class) vars[a].getGenericDeclaration();
220 Object[] array = (Object[]) Array.newInstance(e, l.size());
221 return l.toArray(array);
223 OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo();
224 OpenMBeanAttributeInfo[] attribs =
225 (OpenMBeanAttributeInfo[]) info.getAttributes();
226 OpenType type = null;
227 for (int a = 0; a < attribs.length; ++a)
228 if (attribs[a].getName().equals("attribute"))
229 type = attribs[a].getOpenType();
230 if (value instanceof Map)
232 TabularType ttype = (TabularType) type;
233 TabularData data = new TabularDataSupport(ttype);
234 Iterator it = ((Map) value).entrySet().iterator();
237 Map.Entry entry = (Map.Entry) it.next();
240 data.put(new CompositeDataSupport(ttype.getRowType(),
250 catch (OpenDataException e)
252 throw (InternalError) (new InternalError("A problem occurred " +
253 "converting the map " +
254 "to a composite data " +
255 "structure.").initCause(e));
260 CompositeType cType = (CompositeType) type;
261 Set names = cType.keySet();
262 Iterator it = names.iterator();
263 List values = new ArrayList(names.size());
266 String field = (String) it.next();
267 Method getter = null;
270 getter = vClass.getMethod("get" + field, null);
272 catch (NoSuchMethodException e)
274 /* Ignored; the type tells us it's there. */
278 values.add(getter.invoke(value, null));
280 catch (IllegalAccessException e)
282 throw new ReflectionException(e, "Failed to retrieve " + field);
284 catch (IllegalArgumentException e)
286 throw new ReflectionException(e, "Failed to retrieve " + field);
288 catch (InvocationTargetException e)
290 throw new MBeanException((Exception) e.getCause(),
291 "The getter of " + field +
292 " threw an exception");
297 return new CompositeDataSupport(cType,
299 names.toArray(new String[names.size()]),
302 catch (OpenDataException e)
304 throw (InternalError) (new InternalError("A problem occurred " +
305 "converting the value " +
306 "to a composite data " +
307 "structure.").initCause(e));
311 protected MBeanInfo getCachedMBeanInfo()
313 return (MBeanInfo) openInfo;
316 public MBeanInfo getMBeanInfo()
318 super.getMBeanInfo();
319 return getCachedMBeanInfo();
322 private OpenType getTypeFromClass(Class c)
323 throws OpenDataException
325 return translate(c.getName()).getOpenType();
328 private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS)
329 throws OpenDataException
331 OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length];
332 for (int a = 0; a < oldS.length; ++a)
334 OpenMBeanParameterInfo param = translate(oldS[a].getType());
335 if (param.getMinValue() == null)
338 if (param.getLegalValues() == null)
341 lv = param.getLegalValues().toArray();
342 sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
343 oldS[a].getDescription(),
345 param.getDefaultValue(),
349 sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
350 oldS[a].getDescription(),
352 param.getDefaultValue(),
354 param.getMaxValue());
359 private OpenMBeanParameterInfo translate(String type)
360 throws OpenDataException
362 if (type.equals("boolean") || type.equals(Boolean.class.getName()))
363 return new OpenMBeanParameterInfoSupport("TransParam",
364 "Translated parameter",
371 if (type.equals("byte") || type.equals(Byte.class.getName()))
372 return new OpenMBeanParameterInfoSupport("TransParam",
373 "Translated parameter",
376 Byte.valueOf(Byte.MIN_VALUE),
377 Byte.valueOf(Byte.MAX_VALUE));
378 if (type.equals("char") || type.equals(Character.class.getName()))
379 return new OpenMBeanParameterInfoSupport("TransParam",
380 "Translated parameter",
381 SimpleType.CHARACTER,
383 Character.valueOf(Character.MIN_VALUE),
384 Character.valueOf(Character.MAX_VALUE));
385 if (type.equals("double") || type.equals(Double.class.getName()))
386 return new OpenMBeanParameterInfoSupport("TransParam",
387 "Translated parameter",
390 Double.valueOf(Double.MIN_VALUE),
391 Double.valueOf(Double.MAX_VALUE));
392 if (type.equals("float") || type.equals(Float.class.getName()))
393 return new OpenMBeanParameterInfoSupport("TransParam",
394 "Translated parameter",
397 Float.valueOf(Float.MIN_VALUE),
398 Float.valueOf(Float.MAX_VALUE));
399 if (type.equals("int") || type.equals(Integer.class.getName()))
400 return new OpenMBeanParameterInfoSupport("TransParam",
401 "Translated parameter",
404 Integer.valueOf(Integer.MIN_VALUE),
405 Integer.valueOf(Integer.MAX_VALUE));
406 if (type.equals("long") || type.equals(Long.class.getName()))
407 return new OpenMBeanParameterInfoSupport("TransParam",
408 "Translated parameter",
411 Long.valueOf(Long.MIN_VALUE),
412 Long.valueOf(Long.MAX_VALUE));
413 if (type.equals("short") || type.equals(Short.class.getName()))
414 return new OpenMBeanParameterInfoSupport("TransParam",
415 "Translated parameter",
418 Short.valueOf(Short.MIN_VALUE),
419 Short.valueOf(Short.MAX_VALUE));
420 if (type.equals(String.class.getName()))
421 return new OpenMBeanParameterInfoSupport("TransParam",
422 "Translated parameter",
424 if (type.equals("void"))
425 return new OpenMBeanParameterInfoSupport("TransParam",
426 "Translated parameter",
428 if (type.startsWith("java.util.Map"))
430 int lparam = type.indexOf("<");
431 int comma = type.indexOf(",", lparam);
432 int rparam = type.indexOf(">", comma);
433 String key = type.substring(lparam + 1, comma).trim();
434 OpenType k = translate(key).getOpenType();
435 OpenType v = translate(type.substring(comma + 1, rparam).trim()).getOpenType();
436 CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(),
437 new String[] { "key", "value" },
438 new String[] { "Map key", "Map value"},
439 new OpenType[] { k, v});
440 TabularType ttype = new TabularType(key, key, ctype,
441 new String[] { "key" });
442 return new OpenMBeanParameterInfoSupport("TransParam",
443 "Translated parameter",
446 if (type.startsWith("java.util.List"))
448 int lparam = type.indexOf("<");
449 int rparam = type.indexOf(">");
450 OpenType e = translate(type.substring(lparam + 1, rparam).trim()).getOpenType();
451 return new OpenMBeanParameterInfoSupport("TransParam",
452 "Translated parameter",
459 c = Class.forName(type);
461 catch (ClassNotFoundException e)
463 throw (InternalError)
464 (new InternalError("The class for a type used in a management bean " +
465 "could not be loaded.").initCause(e));
469 Object[] values = c.getEnumConstants();
470 String[] names = new String[values.length];
471 for (int a = 0; a < values.length; ++a)
472 names[a] = values[a].toString();
473 return new OpenMBeanParameterInfoSupport("TransParam",
474 "Translated parameter",
481 c.getMethod("from", new Class[] { CompositeData.class });
482 Method[] methods = c.getMethods();
483 List names = new ArrayList();
484 List types = new ArrayList();
485 for (int a = 0; a < methods.length; ++a)
487 String name = methods[a].getName();
488 if (name.startsWith("get"))
490 names.add(name.substring(3));
491 types.add(getTypeFromClass(methods[a].getReturnType()));
494 String[] fields = (String[]) names.toArray();
495 CompositeType ctype = new CompositeType(c.getName(), c.getName(),
497 (OpenType[]) types.toArray());
498 return new OpenMBeanParameterInfoSupport("TransParam",
499 "Translated parameter",
502 catch (NoSuchMethodException e)
504 /* Ignored; we expect this if this isn't a from(CompositeData) class */
509 for (depth = 0; c.getName().charAt(depth) == '['; ++depth);
510 OpenType ot = getTypeFromClass(c.getComponentType());
511 return new OpenMBeanParameterInfoSupport("TransParam",
512 "Translated parameter",
513 new ArrayType(depth, ot)
516 throw new InternalError("The type used does not have an open type translation.");