KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > mxbean > MXBeanMetaData


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.mxbean;
23
24 import java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Type JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.List JavaDoc;
31
32 import javax.management.IntrospectionException JavaDoc;
33 import javax.management.MBeanInfo JavaDoc;
34 import javax.management.MBeanNotificationInfo JavaDoc;
35 import javax.management.MBeanOperationInfo JavaDoc;
36 import javax.management.NotCompliantMBeanException JavaDoc;
37 import javax.management.NotificationBroadcaster JavaDoc;
38 import javax.management.openmbean.OpenMBeanAttributeInfo JavaDoc;
39 import javax.management.openmbean.OpenMBeanAttributeInfoSupport JavaDoc;
40 import javax.management.openmbean.OpenMBeanConstructorInfo JavaDoc;
41 import javax.management.openmbean.OpenMBeanConstructorInfoSupport JavaDoc;
42 import javax.management.openmbean.OpenMBeanInfoSupport JavaDoc;
43 import javax.management.openmbean.OpenMBeanOperationInfo JavaDoc;
44 import javax.management.openmbean.OpenMBeanOperationInfoSupport JavaDoc;
45 import javax.management.openmbean.OpenMBeanParameterInfo JavaDoc;
46 import javax.management.openmbean.OpenMBeanParameterInfoSupport JavaDoc;
47 import javax.management.openmbean.OpenType JavaDoc;
48
49 import org.jboss.mx.metadata.AbstractBuilder;
50
51 /**
52  * MXBeanMetaData
53  *
54  * @author <a HREF="mailto:juha@jboss.org">Juha Lindfors</a>.
55  * @author <a HREF="mailto:trevor@protocool.com">Trevor Squires</a>.
56  * @author <a HREF="mailto:thomas.diesler@jboss.com">Thomas Diesler</a>.
57  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
58  */

59 public class MXBeanMetaData extends AbstractBuilder
60 {
61    /** The MBean */
62    private Object JavaDoc mbeanInstance;
63    
64    /** The class */
65    private Class JavaDoc<?> mbeanClass;
66    
67    /** The interface */
68    private Class JavaDoc<?> mbeanInterface;
69
70    /**
71     * Find the MXBean interface for a class
72     *
73     * @param mbeanClass the mbean class
74     * @return the interface
75     */

76    public static Class JavaDoc<?> findMXBeanInterface(Class JavaDoc<?> mbeanClass)
77    {
78       Class JavaDoc<?> concrete = mbeanClass;
79       while (null != concrete)
80       {
81          Class JavaDoc result = findMXBeanInterface(concrete, concrete.getInterfaces());
82          if (null != result)
83             return result;
84          concrete = concrete.getSuperclass();
85       }
86       return null;
87    }
88
89    /**
90     * Find the MXBean interface for a class
91     *
92     * @param concrete the mbean class
93     * @param interfaces the interfaces to consider
94     * @return the interface
95     */

96    private static Class JavaDoc<?> findMXBeanInterface(Class JavaDoc<?> concrete, Class JavaDoc<?>[] interfaces)
97    {
98       String JavaDoc mxName = concrete.getName() + "MXBean";
99       String JavaDoc stdName = concrete.getName() + "MBean";
100
101       for (Class JavaDoc<?> intf : interfaces)
102       {
103          String JavaDoc name = intf.getName();
104          if (mxName.equals(name) || stdName.equals(name))
105             return intf;
106          
107          MXBean mxBean = intf.getAnnotation(MXBean.class);
108          if (mxBean != null && mxBean.value())
109             return intf;
110       }
111       return null;
112    }
113
114    /**
115     * Create a new MXBeanMetaData.
116     *
117     * @param mbeanInstance the mbean instance
118     * @throws NotCompliantMBeanException for any error
119     */

120    public MXBeanMetaData(Object JavaDoc mbeanInstance) throws NotCompliantMBeanException JavaDoc
121    {
122       this(mbeanInstance.getClass());
123       this.mbeanInstance = mbeanInstance;
124    }
125
126    /**
127     * Create a new MXBeanMetaData.
128     *
129     * @param mbeanClass the class
130     * @throws NotCompliantMBeanException for any error
131     */

132    public MXBeanMetaData(Class JavaDoc<?> mbeanClass) throws NotCompliantMBeanException JavaDoc
133    {
134       this.mbeanClass = mbeanClass;
135       this.mbeanInterface = findMXBeanInterface(mbeanClass);
136       if (this.mbeanInterface == null)
137          throw new NotCompliantMBeanException JavaDoc("Cannot obtain MXBean interface for: " + mbeanClass);
138    }
139
140    /**
141     * Create a new MXBeanMetaData.
142     *
143     * @param mbeanInstance the mbean instance
144     * @param mbeanInterface the mbean interface
145     * @throws NotCompliantMBeanException for any error
146     */

147    public MXBeanMetaData(Object JavaDoc mbeanInstance, Class JavaDoc<?> mbeanInterface) throws NotCompliantMBeanException JavaDoc
148    {
149       this.mbeanInstance = mbeanInstance;
150       this.mbeanClass = mbeanInstance.getClass();
151       this.mbeanInterface = mbeanInterface;
152       if (this.mbeanInterface == null)
153          this.mbeanInterface = MXBeanMetaData.findMXBeanInterface(mbeanClass);
154       if (this.mbeanInterface == null)
155          throw new NotCompliantMBeanException JavaDoc("Cannot obtain mxbean interface for: " + mbeanClass);
156       if (this.mbeanInterface.isInterface() == false)
157          throw new NotCompliantMBeanException JavaDoc("Management interface is not an interface: " + mbeanInterface);
158    }
159
160    /**
161     * Retrieve the management interface
162     *
163     * @return the interface
164     */

165    public Class JavaDoc<?> getMBeanInterface()
166    {
167       return mbeanInterface;
168    }
169    
170    public MBeanInfo JavaDoc build() throws NotCompliantMBeanException JavaDoc
171    {
172       try
173       {
174          // First check the mbean instance implements the interface
175
if (mbeanInterface == null)
176             throw new NotCompliantMBeanException JavaDoc("The mbean does not implement a management interface");
177          if (mbeanInstance != null && mbeanInterface.isInstance(mbeanInstance) == false)
178             throw new NotCompliantMBeanException JavaDoc("The mbean does not implement its management interface " + mbeanInterface.getName());
179
180          OpenMBeanConstructorInfo JavaDoc[] constructorInfo = buildConstructors();
181
182          HashMap JavaDoc<String JavaDoc, Method JavaDoc> getters = new HashMap JavaDoc<String JavaDoc, Method JavaDoc>();
183          HashMap JavaDoc<String JavaDoc, Method JavaDoc> setters = new HashMap JavaDoc<String JavaDoc, Method JavaDoc>();
184
185          HashMap JavaDoc<String JavaDoc, OpenMBeanOperationInfo JavaDoc> operInfo = new HashMap JavaDoc<String JavaDoc, OpenMBeanOperationInfo JavaDoc>();
186          List JavaDoc<OpenMBeanAttributeInfo JavaDoc> attrInfo = new ArrayList JavaDoc<OpenMBeanAttributeInfo JavaDoc>();
187
188          Method JavaDoc[] methods = mbeanInterface.getMethods();
189          for (Method JavaDoc method : methods)
190          {
191             String JavaDoc methodName = method.getName();
192             Type JavaDoc[] signature = method.getGenericParameterTypes();
193             Type JavaDoc returnType = method.getGenericReturnType();
194
195             if (methodName.startsWith("set") &&
196                 methodName.length() > 3 &&
197                 signature.length == 1 &&
198                 returnType == Void.TYPE)
199             {
200                String JavaDoc key = methodName.substring(3, methodName.length());
201                Method JavaDoc setter = setters.get(key);
202                if (setter != null && setter.getGenericParameterTypes()[0].equals(signature[0]) == false)
203                   throw new IntrospectionException JavaDoc("overloaded type for attribute set: " + key);
204                setters.put(key, method);
205             }
206             else if (methodName.startsWith("get") &&
207                      methodName.length() > 3 &&
208                      signature.length == 0 &&
209                      returnType != Void.TYPE)
210             {
211                String JavaDoc key = methodName.substring(3, methodName.length());
212                Method JavaDoc getter = getters.get(key);
213                if (getter != null && getter.getName().startsWith("is"))
214                   throw new IntrospectionException JavaDoc("mixed use of get/is for attribute " + key);
215                getters.put(key, method);
216             }
217             else if (methodName.startsWith("is") &&
218                      methodName.length() > 2 &&
219                      signature.length == 0 &&
220                      isBooleanReturn(returnType))
221             {
222                String JavaDoc key = methodName.substring(2, methodName.length());
223                Method JavaDoc getter = getters.get(key);
224                if (getter != null && getter.getName().startsWith("get"))
225                   throw new IntrospectionException JavaDoc("mixed use of get/is for attribute " + key);
226                getters.put(key, method);
227             }
228             else
229             {
230                OpenMBeanOperationInfo JavaDoc info = buildOperation(method);
231                operInfo.put(getSignatureString(method), info);
232             }
233          }
234
235          String JavaDoc[] keys = getters.keySet().toArray(new String JavaDoc[getters.size()]);
236          for (String JavaDoc key : keys)
237          {
238             Method JavaDoc getter = getters.remove(key);
239             Method JavaDoc setter = setters.remove(key);
240             OpenMBeanAttributeInfo JavaDoc info = buildAttribute(key, getter, setter);
241             attrInfo.add(info);
242          }
243
244          for (String JavaDoc key : setters.keySet())
245          {
246             Method JavaDoc setter = setters.remove(key);
247             OpenMBeanAttributeInfo JavaDoc info = buildAttribute(key, null, setter);
248             attrInfo.add(info);
249          }
250
251          OpenMBeanAttributeInfo JavaDoc[] attributeInfo = attrInfo.toArray(new OpenMBeanAttributeInfo JavaDoc[attrInfo.size()]);
252          Collection JavaDoc<OpenMBeanOperationInfo JavaDoc> operations = operInfo.values();
253          OpenMBeanOperationInfo JavaDoc[] operationInfo = operations.toArray(new OpenMBeanOperationInfo JavaDoc[operations.size()]);
254
255          MBeanNotificationInfo JavaDoc[] notifications = null;
256          if (mbeanInstance instanceof NotificationBroadcaster JavaDoc)
257             notifications = ((NotificationBroadcaster JavaDoc) mbeanInstance).getNotificationInfo();
258          else
259             notifications = new MBeanNotificationInfo JavaDoc[0];
260
261          return buildMBeanInfo(attributeInfo, constructorInfo, operationInfo, notifications);
262
263       }
264       catch (Throwable JavaDoc t)
265       {
266          NotCompliantMBeanException JavaDoc e = new NotCompliantMBeanException JavaDoc("Error generating OpenMBeanInfo.");
267          e.initCause(t);
268          throw e;
269       }
270    }
271
272    /**
273     * Build the constructors
274     *
275     * @return the info
276     * @throws Exception for any error
277     */

278    private OpenMBeanConstructorInfo JavaDoc[] buildConstructors() throws Exception JavaDoc
279    {
280       Constructor JavaDoc<?>[] constructors = mbeanClass.getConstructors();
281       OpenMBeanConstructorInfo JavaDoc[] constructorInfo = new OpenMBeanConstructorInfo JavaDoc[constructors.length];
282       for (int i = 0; i < constructors.length; ++i)
283          constructorInfo[i] = buildConstructor(constructors[i]);
284       return constructorInfo;
285    }
286    
287    /**
288     * Build a constructor
289     *
290     * @param constructor the constructor
291     * @return the info
292     * @throws Exception for any error
293     */

294    private OpenMBeanConstructorInfo JavaDoc buildConstructor(Constructor JavaDoc<?> constructor) throws Exception JavaDoc
295    {
296       Type JavaDoc[] parameterTypes = constructor.getGenericParameterTypes();
297       OpenMBeanParameterInfo JavaDoc[] parameterInfo = new OpenMBeanParameterInfo JavaDoc[parameterTypes.length];
298       for (int i = 0; i < parameterTypes.length; ++i)
299          parameterInfo[i] = buildParameter(i, parameterTypes[i]);
300       return new OpenMBeanConstructorInfoSupport JavaDoc("MBean Constructor.", "MBean Constructor.", parameterInfo);
301    }
302
303    /**
304     * Build a parameter
305     *
306     * @param i the index of the parameter
307     * @param parameterType the parameter type
308     * @return the info
309     * @throws Exception for any error
310     */

311    private OpenMBeanParameterInfo JavaDoc buildParameter(int i, Type JavaDoc parameterType) throws Exception JavaDoc
312    {
313       OpenType JavaDoc openType = MXBeanUtils.getOpenType(parameterType);
314       return new OpenMBeanParameterInfoSupport JavaDoc("arg" + i, "MBean Parameter.", openType);
315    }
316
317    /**
318     * Build an attribute
319     *
320     * @param attrName the attribute name
321     * @param getter the getter
322     * @param setter the setter
323     * @return the info
324     * @throws Exception for any error
325     */

326    private OpenMBeanAttributeInfo JavaDoc buildAttribute(String JavaDoc attrName, Method JavaDoc getter, Method JavaDoc setter) throws Exception JavaDoc
327    {
328       boolean isReadable = (getter != null);
329       boolean isWritable = (setter != null);
330       boolean isIs = false;
331       
332       OpenType JavaDoc openType = null;
333       if (getter != null)
334       {
335          openType = MXBeanUtils.getOpenType(getter.getGenericReturnType());
336          if (getter.getName().startsWith("is"))
337             isIs = true;
338       }
339       else
340       {
341          openType = MXBeanUtils.getOpenType(setter.getGenericParameterTypes()[0]);
342       }
343       
344       return new OpenMBeanAttributeInfoSupport JavaDoc(attrName, attrName, openType, isReadable, isWritable, isIs);
345    }
346    
347    /**
348     * Build the operation info
349     *
350     * @param method the method
351     * @return the info
352     * @throws Exception for any error
353     */

354    private OpenMBeanOperationInfo JavaDoc buildOperation(Method JavaDoc method) throws Exception JavaDoc
355    {
356       Type JavaDoc[] parameterTypes = method.getGenericParameterTypes();
357       OpenMBeanParameterInfo JavaDoc[] parameterInfo = new OpenMBeanParameterInfo JavaDoc[parameterTypes.length];
358       for (int i = 0; i < parameterTypes.length; ++i)
359          parameterInfo[i] = buildParameter(i, parameterTypes[i]);
360       OpenType JavaDoc openType = MXBeanUtils.getOpenType(method.getGenericReturnType());
361       return new OpenMBeanOperationInfoSupport JavaDoc(method.getName(), method.getName(), parameterInfo, openType, MBeanOperationInfo.ACTION);
362    }
363    
364    /**
365     * Build the mbean info
366     *
367     * @param attributes the attributes
368     * @param constructors the constructors
369     * @param operations the operations
370     * @param notifications the notifications
371     * @return the info
372     * @throws Exception for any error
373     */

374    private OpenMBeanInfoSupport JavaDoc buildMBeanInfo(OpenMBeanAttributeInfo JavaDoc[] attributes, OpenMBeanConstructorInfo JavaDoc[] constructors, OpenMBeanOperationInfo JavaDoc[] operations, MBeanNotificationInfo JavaDoc[] notifications) throws Exception JavaDoc
375    {
376       return new OpenMBeanInfoSupport JavaDoc(mbeanClass.getName(), mbeanClass.getName(), attributes, constructors, operations, notifications);
377    }
378    
379    /**
380     * JMX standard specifies that only "boolean isX()" style methods
381     * represent attributes. "Boolean isX()" methods map to operations.
382     *
383     * @param returnType the return type
384     * @return true when boolean
385     */

386    private boolean isBooleanReturn(Type JavaDoc returnType)
387    {
388       return returnType == Boolean.TYPE;
389    }
390
391    /**
392     * Get a signature string for a method
393     *
394     * @param method the method
395     * @return the signature
396     */

397    private String JavaDoc getSignatureString(Method JavaDoc method)
398    {
399       String JavaDoc name = method.getName();
400       Class JavaDoc[] signature = method.getParameterTypes();
401       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(512);
402       buffer.append(name);
403       buffer.append("(");
404       if (signature != null)
405       {
406          for (int i = 0; i < signature.length; i++)
407          {
408             buffer.append(signature[i].getName());
409             if (i < signature.length-1)
410                buffer.append(",");
411          }
412       }
413       buffer.append(")");
414       return buffer.toString();
415    }
416 }
417
418
Popular Tags