OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / lang / management / BeanImpl.java
1 /* BeanImpl.java - A common superclass for bean implementations.
2    Copyright (C) 2006 Free Software Foundation
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02110-1301 USA.
20
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
24 combination.
25
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. */
37
38 package gnu.java.lang.management;
39
40 import java.lang.management.ManagementPermission;
41
42 import java.lang.reflect.Array;
43 import java.lang.reflect.Method;
44 import java.lang.reflect.InvocationTargetException;
45 import java.lang.reflect.TypeVariable;
46
47 import java.util.ArrayList;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Set;
52
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;
64
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;
85
86 /**
87  * A common superclass for bean implementations.
88  *
89  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
90  * @since 1.5
91  */
92 public class BeanImpl
93   extends StandardMBean
94 {
95
96   /**
97    * Cached open bean information.
98    */
99   private OpenMBeanInfo openInfo;
100
101   /**
102    * Constructs a new <code>BeanImpl</code>.
103    *
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.
109    */
110   protected BeanImpl(Class iface)
111     throws NotCompliantMBeanException
112   {
113     super(iface);
114   }
115
116   protected void cacheMBeanInfo(MBeanInfo info)
117   {
118     if (info == null)
119       return;
120     try
121       {
122         MBeanAttributeInfo[] oldA = info.getAttributes();
123         OpenMBeanAttributeInfo[] attribs =
124           new OpenMBeanAttributeInfoSupport[oldA.length];
125         for (int a = 0; a < oldA.length; ++a)
126           {
127             OpenMBeanParameterInfo param = translate(oldA[a].getType());
128             if (param.getMinValue() == null)
129               {
130                 Object[] lv;
131                 if (param.getLegalValues() == null)
132                   lv = null;
133                 else
134                   lv = param.getLegalValues().toArray();
135                 attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
136                                                                oldA[a].getDescription(),
137                                                                param.getOpenType(),
138                                                                oldA[a].isReadable(),
139                                                                oldA[a].isWritable(),
140                                                                oldA[a].isIs(),
141                                                                param.getDefaultValue(),
142                                                                lv);
143               }
144             else
145               attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
146                                                              oldA[a].getDescription(),
147                                                              param.getOpenType(),
148                                                              oldA[a].isReadable(),
149                                                              oldA[a].isWritable(),
150                                                              oldA[a].isIs(),
151                                                              param.getDefaultValue(),
152                                                              param.getMinValue(),
153                                                              param.getMaxValue());
154           }
155         MBeanConstructorInfo[] oldC = info.getConstructors();
156         OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length];
157         for (int a = 0; a < oldC.length; ++a)
158           cons[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)
165           ops[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());
173       }
174     catch (OpenDataException e)
175       {
176         throw (InternalError) (new InternalError("A problem occurred creating the open type " +
177                                                  "descriptors.").initCause(e));
178       }
179   }
180
181   protected void checkMonitorPermissions()
182   {
183     SecurityManager sm = System.getSecurityManager();
184     if (sm != null)
185       sm.checkPermission(new ManagementPermission("monitor"));
186   }
187
188   protected void checkControlPermissions()
189   {
190     SecurityManager sm = System.getSecurityManager();
191     if (sm != null)
192       sm.checkPermission(new ManagementPermission("control"));
193   }
194
195   public Object getAttribute(String attribute)
196     throws AttributeNotFoundException, MBeanException,
197            ReflectionException
198   {
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())
204       return value;
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]))
209         return value;
210     if (value instanceof List)
211       {
212         List l = (List) value;
213         Class e = null;
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();
218         if (e == null)
219           e = Object.class;
220         Object[] array = (Object[]) Array.newInstance(e, l.size());
221         return l.toArray(array);
222       }
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)
231       {
232         TabularType ttype = (TabularType) type;
233         TabularData data = new TabularDataSupport(ttype);
234         Iterator it = ((Map) value).entrySet().iterator();
235         while (it.hasNext())
236           {
237             Map.Entry entry = (Map.Entry) it.next();
238             try 
239               {
240                 data.put(new CompositeDataSupport(ttype.getRowType(),
241                                                   new String[] { 
242                                                     "key", 
243                                                     "value" 
244                                                   },
245                                                   new Object[] { 
246                                                     entry.getKey(),
247                                                     entry.getValue()
248                                                   }));
249               }
250             catch (OpenDataException e)
251               {
252                 throw (InternalError) (new InternalError("A problem occurred " +
253                                                          "converting the map " +
254                                                          "to a composite data " +
255                                                          "structure.").initCause(e));
256               }
257           }
258         return data;
259       }
260     CompositeType cType = (CompositeType) type;
261     Set names = cType.keySet();
262     Iterator it = names.iterator();
263     List values = new ArrayList(names.size());
264     while (it.hasNext())
265       {
266         String field = (String) it.next();
267         Method getter = null;
268         try 
269           {
270             getter = vClass.getMethod("get" + field, null);
271           }
272         catch (NoSuchMethodException e)
273           {
274             /* Ignored; the type tells us it's there. */
275           }
276         try
277           {
278             values.add(getter.invoke(value, null));
279           }
280         catch (IllegalAccessException e)
281           {
282             throw new ReflectionException(e, "Failed to retrieve " + field);
283           }
284         catch (IllegalArgumentException e)
285           {
286             throw new ReflectionException(e, "Failed to retrieve " + field);
287           }
288         catch (InvocationTargetException e)
289           {
290             throw new MBeanException((Exception) e.getCause(),
291                                      "The getter of " + field +
292                                      " threw an exception");
293           }
294       }
295     try
296       {
297         return new CompositeDataSupport(cType, 
298                                         (String[]) 
299                                         names.toArray(new String[names.size()]),
300                                         values.toArray());
301       }
302     catch (OpenDataException e)
303       {
304         throw (InternalError) (new InternalError("A problem occurred " +
305                                                  "converting the value " +
306                                                  "to a composite data " +
307                                                  "structure.").initCause(e));
308       }
309   }
310   
311   protected MBeanInfo getCachedMBeanInfo()
312   {
313     return (MBeanInfo) openInfo;
314   }
315
316   public MBeanInfo getMBeanInfo()
317   {
318     super.getMBeanInfo();
319     return getCachedMBeanInfo();
320   }
321
322   private OpenType getTypeFromClass(Class c)
323     throws OpenDataException
324   {
325     return translate(c.getName()).getOpenType();
326   }
327
328   private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS)
329     throws OpenDataException
330   {
331     OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length];
332     for (int a = 0; a < oldS.length; ++a)
333       {
334         OpenMBeanParameterInfo param = translate(oldS[a].getType());
335         if (param.getMinValue() == null)
336           {
337             Object[] lv;
338             if (param.getLegalValues() == null)
339               lv = null;
340             else
341               lv = param.getLegalValues().toArray();
342             sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
343                                                        oldS[a].getDescription(),
344                                                        param.getOpenType(),
345                                                        param.getDefaultValue(),
346                                                        lv);
347           }
348         else
349           sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
350                                                      oldS[a].getDescription(),
351                                                      param.getOpenType(),
352                                                      param.getDefaultValue(),
353                                                      param.getMinValue(),
354                                                      param.getMaxValue());
355       }
356     return sig;
357   }
358
359   private OpenMBeanParameterInfo translate(String type)
360     throws OpenDataException
361   {
362     if (type.equals("boolean") || type.equals(Boolean.class.getName()))
363       return new OpenMBeanParameterInfoSupport("TransParam",
364                                                "Translated parameter",
365                                                SimpleType.BOOLEAN,
366                                                null,
367                                                new Object[] {
368                                                  Boolean.TRUE,
369                                                  Boolean.FALSE
370                                                });
371     if (type.equals("byte") || type.equals(Byte.class.getName()))
372       return new OpenMBeanParameterInfoSupport("TransParam",
373                                                "Translated parameter",
374                                                SimpleType.BYTE,
375                                                null,
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,
382                                                null,
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",
388                                                SimpleType.DOUBLE,
389                                                null,
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",
395                                                SimpleType.FLOAT,
396                                                null,
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",
402                                                SimpleType.INTEGER,
403                                                null,
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",
409                                                SimpleType.LONG,
410                                                null,
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",
416                                                SimpleType.SHORT,
417                                                null,
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",
423                                                SimpleType.STRING);
424     if (type.equals("void"))
425       return new OpenMBeanParameterInfoSupport("TransParam",
426                                                "Translated parameter",
427                                                SimpleType.VOID);
428     if (type.startsWith("java.util.Map"))
429       {
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",
444                                                  ttype);
445       }
446     if (type.startsWith("java.util.List"))
447       {
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",
453                                                  new ArrayType(1, e)
454                                                  );
455       } 
456     Class c;
457     try
458       {
459         c = Class.forName(type);
460       }
461     catch (ClassNotFoundException e)
462       {
463         throw (InternalError)
464           (new InternalError("The class for a type used in a management bean " +
465                              "could not be loaded.").initCause(e));
466       }
467     if (c.isEnum())
468       {
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",
475                                                  SimpleType.STRING,
476                                                  null,
477                                                  (Object[]) names);
478       }
479     try
480       {
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)
486           {
487             String name = methods[a].getName();
488             if (name.startsWith("get"))
489               {
490                 names.add(name.substring(3));
491                 types.add(getTypeFromClass(methods[a].getReturnType()));
492               }
493           }
494         String[] fields = (String[]) names.toArray();
495         CompositeType ctype = new CompositeType(c.getName(), c.getName(),
496                                                 fields, fields,
497                                                 (OpenType[]) types.toArray());
498         return new OpenMBeanParameterInfoSupport("TransParam",
499                                                  "Translated parameter",
500                                                  ctype);
501       }
502     catch (NoSuchMethodException e)
503       {
504         /* Ignored; we expect this if this isn't a from(CompositeData) class */
505       }
506     if (c.isArray())
507       {
508         int depth;
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)
514                                                  );
515       }
516     throw new InternalError("The type used does not have an open type translation.");
517   }
518
519 }