KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > metadata > StandardMetaData


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.metadata;
23
24 import java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30
31 import javax.management.IntrospectionException JavaDoc;
32 import javax.management.MBeanAttributeInfo JavaDoc;
33 import javax.management.MBeanConstructorInfo JavaDoc;
34 import javax.management.MBeanInfo JavaDoc;
35 import javax.management.MBeanNotificationInfo JavaDoc;
36 import javax.management.MBeanOperationInfo JavaDoc;
37 import javax.management.NotCompliantMBeanException JavaDoc;
38 import javax.management.NotificationBroadcaster JavaDoc;
39
40 /**
41  * This metadata builder implementation builds a MBean info based on the
42  * naming rules of the Standard MBeans. The MBean server uses this builder
43  * to generate the metadata for Standard MBeans. <p>
44  *
45  * In cooperation with the
46  * {@link MBeanInfoConversion#toModelMBeanInfo MBeanInfoConversion} class you
47  * can use this builder as a migration tool from Standard to Model MBeans, or
48  * for cases where you want the management interface be based on a compile-time
49  * type safe interface. It is also possible to subclass this builder
50  * implementation to extend it to support more sophisticated introspection rules
51  * such as adding descriptors to management interface elements.
52  *
53  * @author <a HREF="mailto:juha@jboss.org">Juha Lindfors</a>.
54  * @author <a HREF="mailto:trevor@protocool.com">Trevor Squires</a>.
55  * @author <a HREF="mailto:thomas.diesler@jboss.com">Thomas Diesler</a>.
56  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
57  */

58 public class StandardMetaData extends AbstractBuilder
59 {
60
61    // Attributes ----------------------------------------------------
62

63    /**
64     * The MBean object instance.
65     * Can be <tt>null</tt>.
66     */

67    private Object JavaDoc mbeanInstance = null;
68    
69    /**
70     * The class of the MBean instance.
71     */

72    private Class JavaDoc mbeanClass = null;
73    
74    /**
75     * The interface used as a basis for constructing the MBean metadata.
76     */

77    private Class JavaDoc mbeanInterface = null;
78
79
80    // Static --------------------------------------------------------
81

82    /**
83     * Locates an interface for a class that matches the Standard MBean naming
84     * convention.
85     *
86     * @param mbeanClass the class to investigate
87     *
88     * @return the Standard MBean interface class or <tt>null</tt> if not found
89     */

90    public static Class JavaDoc findStandardInterface(Class JavaDoc mbeanClass)
91    {
92       Class JavaDoc concrete = mbeanClass;
93       Class JavaDoc stdInterface = null;
94       while (null != concrete)
95       {
96          stdInterface = findStandardInterface(concrete, concrete.getInterfaces());
97          if (null != stdInterface)
98          {
99             return stdInterface;
100          }
101          concrete = concrete.getSuperclass();
102       }
103       return null;
104    }
105
106    private static Class JavaDoc findStandardInterface(Class JavaDoc concrete, Class JavaDoc[] interfaces)
107    {
108       String JavaDoc stdName = concrete.getName() + "MBean";
109       Class JavaDoc retval = null;
110
111       // look to see if this class implements MBean std interface
112
for (int i = 0; i < interfaces.length; ++i)
113       {
114          if (interfaces[i].getName().equals(stdName))
115          {
116             retval = interfaces[i];
117             break;
118          }
119       }
120
121       return retval;
122    }
123
124    
125    // Constructors --------------------------------------------------
126

127    /**
128     * Initializes the Standard metadata builder. The JMX metadata is based
129     * on the class of the given resource instance.
130     *
131     * @param mbeanInstance MBean instance
132     */

133    public StandardMetaData(Object JavaDoc mbeanInstance) throws NotCompliantMBeanException JavaDoc
134    {
135       this(mbeanInstance.getClass());
136       this.mbeanInstance = mbeanInstance;
137    }
138
139    /**
140     * Initializes the Standard metadata builder. The JMX metadata is based
141     * on the given class.
142     *
143     * @param mbeanClass resource class that implements an interface
144     * adhering to the Standard MBean naming conventions
145     */

146    public StandardMetaData(Class JavaDoc mbeanClass) throws NotCompliantMBeanException JavaDoc
147    {
148       this.mbeanClass = mbeanClass;
149       this.mbeanInterface = StandardMetaData.findStandardInterface(mbeanClass);
150       if (this.mbeanInterface == null)
151          throw new NotCompliantMBeanException JavaDoc("Cannot obtain management interface for: " + mbeanClass);
152    }
153
154    /**
155     * Initializes the Standard metadata builder. The JMX metadata is based
156     * on the passed mbean interface.
157     *
158     * @param mbInstance MBean instance
159     * @param mbInterface the management interface
160     */

161    public StandardMetaData(Object JavaDoc mbInstance, Class JavaDoc mbInterface) throws NotCompliantMBeanException JavaDoc
162    {
163       this.mbeanInstance = mbInstance;
164       this.mbeanClass = mbInstance.getClass();
165       this.mbeanInterface = mbInterface;
166
167       // search for it
168
if (this.mbeanInterface == null)
169          this.mbeanInterface = StandardMetaData.findStandardInterface(mbeanClass);
170
171       if (this.mbeanInterface == null)
172          throw new NotCompliantMBeanException JavaDoc("Cannot obtain management interface for: " + mbeanClass);
173       if (this.mbeanInterface.isInterface() == false)
174          throw new NotCompliantMBeanException JavaDoc("Management interface is not an interface: " + mbeanInterface);
175    }
176
177    /**
178     * Retrieve the management interface
179     */

180    public Class JavaDoc getMBeanInterface()
181    {
182       return mbeanInterface;
183    }
184    
185    // MetaDataBuilder implementation --------------------------------
186

187    public MBeanInfo JavaDoc build() throws NotCompliantMBeanException JavaDoc
188    {
189       try
190       {
191          // First check the mbean instance implements the interface
192
if (mbeanInterface == null)
193             throw new NotCompliantMBeanException JavaDoc("The mbean does not implement a management interface");
194          if (mbeanInstance != null && mbeanInterface.isInstance(mbeanInstance) == false)
195             throw new NotCompliantMBeanException JavaDoc("The mbean does not implement its management interface " +
196                                                  mbeanInterface.getName());
197
198          // First build the constructors
199
Constructor JavaDoc[] constructors = mbeanClass.getConstructors();
200          MBeanConstructorInfo JavaDoc[] constructorInfo = new MBeanConstructorInfo JavaDoc[constructors.length];
201          for (int i = 0; i < constructors.length; ++i)
202          {
203             constructorInfo[i] = new MBeanConstructorInfo JavaDoc("MBean Constructor.", constructors[i]);
204          }
205
206          // Next we have to figure out how the methods in the mbean class map
207
// to attributes and operations
208
Method JavaDoc[] methods = mbeanInterface.getMethods();
209          HashMap JavaDoc getters = new HashMap JavaDoc();
210          HashMap JavaDoc setters = new HashMap JavaDoc();
211
212          HashMap JavaDoc operInfo = new HashMap JavaDoc();
213          List JavaDoc attrInfo = new ArrayList JavaDoc();
214
215          for (int i = 0; i < methods.length; ++i)
216          {
217             String JavaDoc methodName = methods[i].getName();
218             Class JavaDoc[] signature = methods[i].getParameterTypes();
219             Class JavaDoc returnType = methods[i].getReturnType();
220
221             if (methodName.startsWith("set") && methodName.length() > 3
222                     && signature.length == 1 && returnType == Void.TYPE)
223             {
224                String JavaDoc key = methodName.substring(3, methodName.length());
225                Method JavaDoc setter = (Method JavaDoc) setters.get(key);
226                if (setter != null && setter.getParameterTypes()[0].equals(signature[0]) == false)
227                {
228                   throw new IntrospectionException JavaDoc("overloaded type for attribute set: " + key);
229                }
230                setters.put(key, methods[i]);
231             }
232             else if (methodName.startsWith("get") && methodName.length() > 3
233                          && signature.length == 0 && returnType != Void.TYPE)
234             {
235                String JavaDoc key = methodName.substring(3, methodName.length());
236                Method JavaDoc getter = (Method JavaDoc) getters.get(key);
237                if (getter != null && getter.getName().startsWith("is"))
238                {
239                   throw new IntrospectionException JavaDoc("mixed use of get/is for attribute " + key);
240                }
241                getters.put(key, methods[i]);
242             }
243             else if (methodName.startsWith("is") && methodName.length() > 2
244                         && signature.length == 0 && isBooleanReturn(returnType))
245             {
246                String JavaDoc key = methodName.substring(2, methodName.length());
247                Method JavaDoc getter = (Method JavaDoc) getters.get(key);
248                if (getter != null && getter.getName().startsWith("get"))
249                {
250                   throw new IntrospectionException JavaDoc("mixed use of get/is for attribute " + key);
251                }
252                getters.put(key, methods[i]);
253             }
254             else
255             {
256                MBeanOperationInfo JavaDoc info = new MBeanOperationInfo JavaDoc("MBean Operation.", methods[i]);
257                operInfo.put(getSignatureString(methods[i]), info);
258             }
259          }
260
261          Object JavaDoc[] keys = getters.keySet().toArray();
262          for (int i = 0; i < keys.length; ++i)
263          {
264             String JavaDoc attrName = (String JavaDoc) keys[i];
265             Method JavaDoc getter = (Method JavaDoc) getters.remove(attrName);
266             Method JavaDoc setter = (Method JavaDoc) setters.remove(attrName);
267             MBeanAttributeInfo JavaDoc info = new MBeanAttributeInfo JavaDoc(attrName, "MBean Attribute.", getter, setter);
268             attrInfo.add(info);
269          }
270
271          Iterator JavaDoc it = setters.keySet().iterator();
272          while (it.hasNext())
273          {
274             String JavaDoc attrName = (String JavaDoc) it.next();
275             Method JavaDoc setter = (Method JavaDoc) setters.get(attrName);
276             MBeanAttributeInfo JavaDoc info = new MBeanAttributeInfo JavaDoc(attrName, "MBean Attribute.", null, setter);
277             attrInfo.add(info);
278          }
279
280          // save away the attribute and operation info objects
281
MBeanAttributeInfo JavaDoc[] attributeInfo = (MBeanAttributeInfo JavaDoc[]) attrInfo.toArray(new MBeanAttributeInfo JavaDoc[0]);
282          MBeanOperationInfo JavaDoc[] operationInfo = (MBeanOperationInfo JavaDoc[]) operInfo.values().toArray(new MBeanOperationInfo JavaDoc[0]);
283
284          // if the builder was initialized with the resource instance, check if
285
// it is a notification broadcaster, and add the appropriate notifications
286
// to the interface.
287
MBeanNotificationInfo JavaDoc[] notifications = null;
288          if (mbeanInstance instanceof NotificationBroadcaster JavaDoc)
289          {
290             notifications = ((NotificationBroadcaster JavaDoc) mbeanInstance).getNotificationInfo();
291          }
292          else
293          {
294             notifications = new MBeanNotificationInfo JavaDoc[0];
295          }
296
297          return new MBeanInfo JavaDoc(mbeanClass.getName(), "Management Bean.",
298                               attributeInfo, constructorInfo, operationInfo, notifications);
299
300       }
301       catch (IntrospectionException JavaDoc e)
302       {
303          throw new NotCompliantMBeanException JavaDoc(e.getMessage());
304       }
305    }
306
307    /**
308     * JMX standard specifies that only "boolean isX()" style methods
309     * represent attributes. "Boolean isX()" methods map to operations.
310     */

311    private boolean isBooleanReturn(Class JavaDoc returnType)
312    {
313       return returnType == Boolean.TYPE;
314    }
315
316    protected String JavaDoc getSignatureString(Method JavaDoc method)
317    {
318       String JavaDoc name = method.getName();
319       Class JavaDoc[] signature = method.getParameterTypes();
320       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(512);
321       buffer.append(name);
322       buffer.append("(");
323       if (signature != null)
324       {
325          for (int i = 0; i < signature.length; i++)
326          {
327             buffer.append(signature[i].getName());
328             if (i < signature.length-1)
329                buffer.append(",");
330          }
331       }
332       buffer.append(")");
333       return buffer.toString();
334    }
335 }
336
337
Popular Tags