KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2006, 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.Method JavaDoc;
25 import java.lang.reflect.Type JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import javax.management.Attribute JavaDoc;
30 import javax.management.AttributeList JavaDoc;
31 import javax.management.AttributeNotFoundException JavaDoc;
32 import javax.management.DynamicMBean JavaDoc;
33 import javax.management.InvalidAttributeValueException JavaDoc;
34 import javax.management.JMException JavaDoc;
35 import javax.management.MBeanAttributeInfo JavaDoc;
36 import javax.management.MBeanException JavaDoc;
37 import javax.management.MBeanInfo JavaDoc;
38 import javax.management.MBeanRegistration JavaDoc;
39 import javax.management.MBeanServer JavaDoc;
40 import javax.management.NotCompliantMBeanException JavaDoc;
41 import javax.management.NotificationBroadcasterSupport JavaDoc;
42 import javax.management.NotificationEmitter JavaDoc;
43 import javax.management.ObjectName JavaDoc;
44 import javax.management.ReflectionException JavaDoc;
45 import javax.management.openmbean.OpenMBeanAttributeInfo JavaDoc;
46 import javax.management.openmbean.OpenMBeanInfo JavaDoc;
47
48 import org.jboss.logging.Logger;
49 import org.jboss.mx.server.ExceptionHandler;
50
51 /**
52  * MXBeanDelegate.
53  *
54  * FIXME: Reflection madness
55  * @author <a HREF="adrian@jboss.com">Adrian Brock</a>
56  * @version $Revision: 1.1 $
57  */

58 public class MXBeanDelegate extends NotificationBroadcasterSupport JavaDoc implements DynamicMBean JavaDoc, MBeanRegistration JavaDoc, NotificationEmitter JavaDoc
59 {
60    /** The logger */
61    private static final Logger log = Logger.getLogger(MXBeanDelegate.class);
62
63    /** The implementation object */
64    private Object JavaDoc implementation;
65
66    /** The management interface */
67    private Class JavaDoc mbeanInterface;
68
69    /** The cached mbeaninfo */
70    private OpenMBeanInfo JavaDoc cachedMBeanInfo;
71    
72    /** The attribute mapping */
73    private Map JavaDoc<String JavaDoc, OpenMBeanAttributeInfo JavaDoc> attributeMapping;
74    
75    /** The getters */
76    private Map JavaDoc<String JavaDoc, Method JavaDoc> getters;
77    
78    /** The setters */
79    private Map JavaDoc<String JavaDoc, Method JavaDoc> setters;
80    
81    /** The operatinns */
82    private Map JavaDoc<String JavaDoc, Method JavaDoc> operations;
83
84    /**
85     * Construct a DynamicMBean from the given implementation object
86     * and the passed management interface class.
87     *
88     * @param implementation the object implementing the mbean
89     * @param mbeanInterface the management interface of the mbean
90     * @exception IllegalArgumentException for a null implementation
91     * @exception NotCompliantMBeanException if the management interface
92     * does not follow the JMX design patterns or the implementation
93     * does not implement the interface
94     */

95    public MXBeanDelegate(Object JavaDoc implementation, Class JavaDoc mbeanInterface) throws NotCompliantMBeanException JavaDoc
96    {
97       this.implementation = implementation;
98       this.mbeanInterface = mbeanInterface;
99    }
100
101    /**
102     * Construct a DynamicMBean from this object
103     * and the passed management interface class.<p>
104     *
105     * Used in subclassing
106     *
107     * @param mbeanInterface the management interface of the mbean
108     * @exception NotCompliantMBeanException if the management interface
109     * does not follow the JMX design patterns or this
110     * does not implement the interface
111     */

112    protected MXBeanDelegate(Class JavaDoc mbeanInterface) throws NotCompliantMBeanException JavaDoc
113    {
114       this.implementation = this;
115       this.mbeanInterface = mbeanInterface;
116    }
117
118    /**
119     * Retrieve the implementation object
120     *
121     * @return the implementation
122     */

123    public Object JavaDoc getImplementation()
124    {
125       return implementation;
126    }
127
128    /**
129     * Replace the implementation object
130     *
131     * @todo make this work after the mbean is registered
132     * @param implementation the new implementation
133     * @exception IllegalArgumentException for a null parameter
134     * @exception NotCompliantMBeanException if the new implementation
135     * does not implement the interface supplied at
136     * construction
137     */

138    public void setImplementation(Object JavaDoc implementation) throws NotCompliantMBeanException JavaDoc
139    {
140       if (implementation == null)
141          throw new IllegalArgumentException JavaDoc("Null implementation");
142       this.implementation = implementation;
143    }
144
145    /**
146     * Retrieve the implementation class
147     *
148     * @return the class of the implementation
149     */

150    public Class JavaDoc getImplementationClass()
151    {
152       return implementation.getClass();
153    }
154
155    /**
156     * Retrieve the management interface
157     *
158     * @return the management interface
159     */

160    public final Class JavaDoc getMBeanInterface()
161    {
162       return mbeanInterface;
163    }
164
165    public Object JavaDoc getAttribute(String JavaDoc attribute) throws AttributeNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
166    {
167       try
168       {
169          OpenMBeanAttributeInfo JavaDoc attributeInfo = attributeMapping.get(attribute);
170          if (attributeInfo == null)
171             throw new AttributeNotFoundException JavaDoc(attribute);
172          MBeanAttributeInfo JavaDoc mbeanAttributeInfo = (MBeanAttributeInfo JavaDoc) attributeInfo;
173          if (mbeanAttributeInfo.isReadable() == false)
174             throw new AttributeNotFoundException JavaDoc("Attribute is not readable: " + attribute);
175          
176          Method JavaDoc method = getters.get(attribute);
177          if (method == null)
178             throw new NoSuchMethodException JavaDoc("No method to get attribute: " + attribute);
179          
180          Object JavaDoc result = method.invoke(implementation, new Object JavaDoc[0]);
181          
182          return MXBeanUtils.construct(attributeInfo.getOpenType(), result, "Get attribute: " + attribute);
183       }
184       catch (Exception JavaDoc e)
185       {
186          JMException JavaDoc result = ExceptionHandler.handleException(e);
187          if (result instanceof AttributeNotFoundException JavaDoc)
188             throw (AttributeNotFoundException JavaDoc)result;
189          if (result instanceof MBeanException JavaDoc)
190             throw (MBeanException JavaDoc)result;
191          if (result instanceof ReflectionException JavaDoc)
192             throw (ReflectionException JavaDoc)result;
193          throw new MBeanException JavaDoc(e, "Cannot get attribute: " + attribute);
194       }
195    }
196
197    public void setAttribute(Attribute JavaDoc attribute) throws AttributeNotFoundException JavaDoc, InvalidAttributeValueException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
198    {
199       try
200       {
201          String JavaDoc attributeName = attribute.getName();
202          OpenMBeanAttributeInfo JavaDoc attributeInfo = attributeMapping.get(attributeName);
203          if (attributeInfo == null)
204             throw new AttributeNotFoundException JavaDoc(attributeName);
205          MBeanAttributeInfo JavaDoc mbeanAttributeInfo = (MBeanAttributeInfo JavaDoc) attributeInfo;
206          if (mbeanAttributeInfo.isWritable() == false)
207             throw new AttributeNotFoundException JavaDoc("Attribute is not writable: " + attributeName);
208          
209          Method JavaDoc method = setters.get(attributeName);
210          if (method == null)
211             throw new NoSuchMethodException JavaDoc("No method to set attribute: " + attribute);
212
213          Object JavaDoc value = MXBeanUtils.reconstruct(method.getGenericParameterTypes()[0], attribute.getValue(), method);
214          
215          method.invoke(implementation, new Object JavaDoc[] { value });
216       }
217       catch (Exception JavaDoc e)
218       {
219          JMException JavaDoc result = ExceptionHandler.handleException(e);
220          if (result instanceof AttributeNotFoundException JavaDoc)
221             throw (AttributeNotFoundException JavaDoc)result;
222          if (result instanceof InvalidAttributeValueException JavaDoc)
223             throw (InvalidAttributeValueException JavaDoc)result;
224          if (result instanceof MBeanException JavaDoc)
225             throw (MBeanException JavaDoc)result;
226          if (result instanceof ReflectionException JavaDoc)
227             throw (ReflectionException JavaDoc)result;
228          throw new MBeanException JavaDoc(e, "Cannot set attribute: " + attribute);
229       }
230    }
231
232    public AttributeList JavaDoc getAttributes(String JavaDoc[] attributes)
233    {
234       try
235       {
236          AttributeList JavaDoc attrList = new AttributeList JavaDoc(attributes.length);
237          for (int i = 0; i < attributes.length; i++)
238          {
239             String JavaDoc name = attributes[i];
240             Object JavaDoc value = getAttribute(name);
241             attrList.add(new Attribute JavaDoc(name, value));
242          }
243          return attrList;
244       }
245       catch (Exception JavaDoc e)
246       {
247          JMException JavaDoc result = ExceptionHandler.handleException(e);
248          // Why is this not throwing the same exceptions as getAttribute(String)
249
throw new RuntimeException JavaDoc("Cannot get attributes", result);
250       }
251    }
252
253    public AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes)
254    {
255       AttributeList JavaDoc result = new AttributeList JavaDoc(attributes.size());
256       for (int i = 0; i < attributes.size(); ++i)
257       {
258          Attribute JavaDoc attr = (Attribute JavaDoc) attributes.get(i);
259          String JavaDoc name = attr.getName();
260          try
261          {
262             setAttribute(attr);
263             result.add(new Attribute JavaDoc(name, attr.getValue()));
264          }
265          catch (Throwable JavaDoc t)
266          {
267             JMException JavaDoc e = ExceptionHandler.handleException(t);
268             result.add(new Attribute JavaDoc(name, e));
269          }
270       }
271       return result;
272    }
273
274    public Object JavaDoc invoke(String JavaDoc actionName, Object JavaDoc[] params, String JavaDoc[] signature) throws MBeanException JavaDoc, ReflectionException JavaDoc
275    {
276       try
277       {
278          String JavaDoc signatureString = getSignatureString(actionName, signature);
279          Method JavaDoc method = operations.get(signatureString);
280          if (method == null)
281             throw new NoSuchMethodException JavaDoc("Cannot find method for operation: " + signatureString);
282
283          Object JavaDoc[] parameters = params;
284          if (params.length > 0)
285          {
286             parameters = new Object JavaDoc[params.length];
287             Type JavaDoc[] parameterTypes = method.getGenericParameterTypes();
288             for (int i = 0; i < parameters.length; ++i)
289                parameters[i] = MXBeanUtils.reconstruct(parameterTypes[i], params[i], method);
290          }
291          
292          Object JavaDoc result = method.invoke(implementation, parameters);
293          
294          if (result == null)
295             return null;
296          Type JavaDoc returnType = method.getGenericReturnType();
297          return MXBeanUtils.construct(returnType, result, method);
298       }
299       catch (Exception JavaDoc e)
300       {
301          JMException JavaDoc result = ExceptionHandler.handleException(e);
302          if (result instanceof MBeanException JavaDoc)
303             throw (MBeanException JavaDoc)result;
304          if (result instanceof ReflectionException JavaDoc)
305             throw (ReflectionException JavaDoc)result;
306          throw new MBeanException JavaDoc(e, "Cannot invoke: " + actionName);
307       }
308    }
309
310    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name) throws Exception JavaDoc
311    {
312       return name;
313    }
314
315    public void postRegister(Boolean JavaDoc registrationDone)
316    {
317    }
318
319    public void preDeregister() throws Exception JavaDoc
320    {
321    }
322
323    public void postDeregister()
324    {
325    }
326
327    public MBeanInfo JavaDoc getMBeanInfo()
328    {
329       OpenMBeanInfo JavaDoc info = getCachedMBeanInfo();
330       if (info == null)
331       {
332          try
333          {
334             info = buildMBeanInfo();
335             cacheMBeanInfo(info);
336          }
337          catch (NotCompliantMBeanException JavaDoc e)
338          {
339             log.error("Unexcepted exception", e);
340             throw new IllegalStateException JavaDoc("Unexcepted exception " + e.toString());
341          }
342
343       }
344       return (MBeanInfo JavaDoc) info;
345    }
346
347    /**
348     * Retrieve the cached mbean info
349     *
350     * @return the cached mbean info
351     */

352    public OpenMBeanInfo JavaDoc getCachedMBeanInfo()
353    {
354       return cachedMBeanInfo;
355    }
356
357    /**
358     * Sets the cached mbean info
359     *
360     * @param info the mbeaninfo to cache, can be null to erase the cache
361     */

362    public void cacheMBeanInfo(OpenMBeanInfo JavaDoc info)
363    {
364       cachedMBeanInfo = info;
365       Map JavaDoc<String JavaDoc, OpenMBeanAttributeInfo JavaDoc> attributeMapping = new HashMap JavaDoc<String JavaDoc, OpenMBeanAttributeInfo JavaDoc>();
366       MBeanAttributeInfo JavaDoc[] attributes = info.getAttributes();
367       for (int i = 0; i < attributes.length; ++i)
368       {
369          OpenMBeanAttributeInfo JavaDoc attribute = (OpenMBeanAttributeInfo JavaDoc) attributes[i];
370          attributeMapping.put(attribute.getName(), attribute);
371       }
372       this.attributeMapping = attributeMapping;
373
374       try
375       {
376          HashMap JavaDoc<String JavaDoc, Method JavaDoc> getters = new HashMap JavaDoc<String JavaDoc, Method JavaDoc>();
377          HashMap JavaDoc<String JavaDoc, Method JavaDoc> setters = new HashMap JavaDoc<String JavaDoc, Method JavaDoc>();
378
379          HashMap JavaDoc<String JavaDoc, Method JavaDoc> operations = new HashMap JavaDoc<String JavaDoc, Method JavaDoc>();
380
381          Method JavaDoc[] methods = implementation.getClass().getMethods();
382          for (Method JavaDoc method : methods)
383          {
384             String JavaDoc methodName = method.getName();
385             Type JavaDoc[] signature = method.getGenericParameterTypes();
386             Type JavaDoc returnType = method.getGenericReturnType();
387
388             if (methodName.startsWith("set") &&
389                 methodName.length() > 3 &&
390                 signature.length == 1 &&
391                 returnType == Void.TYPE)
392             {
393                String JavaDoc key = methodName.substring(3, methodName.length());
394                Method JavaDoc setter = setters.get(key);
395                if (setter != null && setter.getGenericParameterTypes()[0].equals(signature[0]) == false)
396                   throw new RuntimeException JavaDoc("overloaded type for attribute set: " + key);
397                setters.put(key, method);
398             }
399             else if (methodName.startsWith("get") &&
400                      methodName.length() > 3 &&
401                      signature.length == 0 &&
402                      returnType != Void.TYPE)
403             {
404                String JavaDoc key = methodName.substring(3, methodName.length());
405                Method JavaDoc getter = getters.get(key);
406                if (getter != null && getter.getName().startsWith("is"))
407                   throw new RuntimeException JavaDoc("mixed use of get/is for attribute " + key);
408                getters.put(key, method);
409             }
410             else if (methodName.startsWith("is") &&
411                      methodName.length() > 2 &&
412                      signature.length == 0 &&
413                      returnType == Boolean.TYPE)
414             {
415                String JavaDoc key = methodName.substring(2, methodName.length());
416                Method JavaDoc getter = getters.get(key);
417                if (getter != null && getter.getName().startsWith("get"))
418                   throw new RuntimeException JavaDoc("mixed use of get/is for attribute " + key);
419                getters.put(key, method);
420             }
421             else
422             {
423                operations.put(getSignatureString(method), method);
424             }
425          }
426          this.getters = getters;
427          this.setters = setters;
428          this.operations = operations;
429       }
430       catch (RuntimeException JavaDoc e)
431       {
432          log.error("Error: ", e);
433          throw e;
434       }
435       catch (Error JavaDoc e)
436       {
437          log.error("Error: ", e);
438          throw e;
439       }
440    }
441
442    /**
443     * Builds a default MBeanInfo for this MBean, using the Management Interface specified for this MBean.
444     *
445     * While building the MBeanInfo, this method calls the customization hooks that make it possible for subclasses to
446     * supply their custom descriptions, parameter names, etc...
447     *
448     * @return the mbean info
449     * @throws NotCompliantMBeanException when not a valid mbean
450     */

451    public OpenMBeanInfo JavaDoc buildMBeanInfo() throws NotCompliantMBeanException JavaDoc
452    {
453       if (implementation == null)
454          throw new IllegalArgumentException JavaDoc("Null implementation");
455
456       MXBeanMetaData metadata = new MXBeanMetaData(implementation, mbeanInterface);
457       return (OpenMBeanInfo JavaDoc) metadata.build();
458    }
459
460    /**
461     * Get a signature string for a method
462     *
463     * @param method the method
464     * @return the signature
465     */

466    private String JavaDoc getSignatureString(Method JavaDoc method)
467    {
468       String JavaDoc name = method.getName();
469       Class JavaDoc[] signature = method.getParameterTypes();
470       StringBuilder JavaDoc buffer = new StringBuilder JavaDoc(512);
471       buffer.append(name);
472       buffer.append("(");
473       if (signature != null)
474       {
475          for (int i = 0; i < signature.length; i++)
476          {
477             buffer.append(signature[i].getName());
478             if (i < signature.length-1)
479                buffer.append(",");
480          }
481       }
482       buffer.append(")");
483       return buffer.toString();
484    }
485
486    /**
487     * Get a signature string for a method
488     *
489     * @param operation the operation
490     * @param signature the signature
491     * @return the signature
492     */

493    private String JavaDoc getSignatureString(String JavaDoc operation, String JavaDoc[] signature)
494    {
495       StringBuilder JavaDoc buffer = new StringBuilder JavaDoc(512);
496       buffer.append(operation);
497       buffer.append("(");
498       if (signature != null)
499       {
500          for (int i = 0; i < signature.length; i++)
501          {
502             buffer.append(signature[i]);
503             if (i < signature.length-1)
504                buffer.append(",");
505          }
506       }
507       buffer.append(")");
508       return buffer.toString();
509    }
510 }
511
Popular Tags