KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jmx > export > assembler > MetadataMBeanInfoAssembler


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.jmx.export.assembler;
18
19 import java.beans.PropertyDescriptor JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21
22 import javax.management.Descriptor JavaDoc;
23 import javax.management.MBeanParameterInfo JavaDoc;
24 import javax.management.modelmbean.ModelMBeanNotificationInfo JavaDoc;
25
26 import org.springframework.aop.support.AopUtils;
27 import org.springframework.beans.BeanUtils;
28 import org.springframework.beans.factory.InitializingBean;
29 import org.springframework.jmx.export.metadata.InvalidMetadataException;
30 import org.springframework.jmx.export.metadata.JmxAttributeSource;
31 import org.springframework.jmx.export.metadata.JmxMetadataUtils;
32 import org.springframework.jmx.export.metadata.ManagedAttribute;
33 import org.springframework.jmx.export.metadata.ManagedNotification;
34 import org.springframework.jmx.export.metadata.ManagedOperation;
35 import org.springframework.jmx.export.metadata.ManagedOperationParameter;
36 import org.springframework.jmx.export.metadata.ManagedResource;
37 import org.springframework.util.StringUtils;
38
39 /**
40  * Implementation of <code>MBeanInfoAssembler</code> that reads the
41  * management interface information from source level metadata.
42  *
43  * <p>Uses the <code>JmxAttributeSource</code> strategy interface, so that
44  * metadata can be read using any supported implementation. Out of the box,
45  * two strategies are included:
46  * <ul>
47  * <li><code>AttributesJmxAttributeSource</code>, for Commons Attributes
48  * <li><code>AnnotationJmxAttributeSource</code>, for JDK 1.5+ annotations
49  * </ul>
50  *
51  * @author Rob Harrop
52  * @author Juergen Hoeller
53  * @since 1.2
54  * @see #setAttributeSource
55  * @see org.springframework.jmx.export.metadata.AttributesJmxAttributeSource
56  * @see org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
57  */

58 public class MetadataMBeanInfoAssembler extends AbstractReflectiveMBeanInfoAssembler
59         implements AutodetectCapableMBeanInfoAssembler, InitializingBean {
60
61     private JmxAttributeSource attributeSource;
62
63
64     /**
65      * Set the <code>JmxAttributeSource</code> implementation to use for
66      * reading the metadata from the bean class.
67      * @see org.springframework.jmx.export.metadata.AttributesJmxAttributeSource
68      * @see org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
69      */

70     public void setAttributeSource(JmxAttributeSource attributeSource) {
71         this.attributeSource = attributeSource;
72     }
73
74     public void afterPropertiesSet() {
75         if (this.attributeSource == null) {
76             throw new IllegalArgumentException JavaDoc("'attributeSource' is required");
77         }
78     }
79
80
81     /**
82      * Throws an IllegalArgumentException if it encounters a JDK dynamic proxy.
83      * Metadata can only be read from target classes and CGLIB proxies!
84      */

85     protected void checkManagedBean(Object JavaDoc managedBean) throws IllegalArgumentException JavaDoc {
86         if (AopUtils.isJdkDynamicProxy(managedBean)) {
87             throw new IllegalArgumentException JavaDoc(
88                     "MetadataMBeanInfoAssembler does not support JDK dynamic proxies - " +
89                     "export the target beans directly or use CGLIB proxies instead");
90         }
91     }
92
93     /**
94      * Used for autodetection of beans. Checks to see if the bean's class has a
95      * <code>ManagedResource</code> attribute. If so it will add it list of included beans.
96      * @param beanClass the class of the bean
97      * @param beanName the name of the bean in the bean factory
98      */

99     public boolean includeBean(Class JavaDoc beanClass, String JavaDoc beanName) {
100         return (this.attributeSource.getManagedResource(getClassToExpose(beanClass)) != null);
101     }
102
103     /**
104      * Vote on the inclusion of an attribute accessor.
105      * @param method the accessor method
106      * @param beanKey the key associated with the MBean in the beans map
107      * @return whether the method has the appropriate metadata
108      */

109     protected boolean includeReadAttribute(Method JavaDoc method, String JavaDoc beanKey) {
110         return hasManagedAttribute(method);
111     }
112
113     /**
114      * Votes on the inclusion of an attribute mutator.
115      * @param method the mutator method
116      * @param beanKey the key associated with the MBean in the beans map
117      * @return whether the method has the appropriate metadata
118      */

119     protected boolean includeWriteAttribute(Method JavaDoc method, String JavaDoc beanKey) {
120         return hasManagedAttribute(method);
121     }
122
123     /**
124      * Votes on the inclusion of an operation.
125      * @param method the operation method
126      * @param beanKey the key associated with the MBean in the beans map
127      * @return whether the method has the appropriate metadata
128      */

129     protected boolean includeOperation(Method JavaDoc method, String JavaDoc beanKey) {
130         PropertyDescriptor JavaDoc pd = BeanUtils.findPropertyForMethod(method);
131         if (pd != null) {
132             return hasManagedAttribute(method);
133         }
134         else {
135             return hasManagedOperation(method);
136         }
137     }
138
139     /**
140      * Checks to see if the given Method has the <code>ManagedAttribute</code> attribute.
141      */

142     private boolean hasManagedAttribute(Method JavaDoc method) {
143         return (this.attributeSource.getManagedAttribute(method) != null);
144     }
145
146     /**
147      * Checks to see if the given Method has the <code>ManagedOperation</code> attribute.
148      * @param method the method to check
149      */

150     private boolean hasManagedOperation(Method JavaDoc method) {
151         return (this.attributeSource.getManagedOperation(method) != null);
152     }
153
154
155     /**
156      * Reads managed resource description from the source level metadata.
157      * Returns an empty <code>String</code> if no description can be found.
158      */

159     protected String JavaDoc getDescription(Object JavaDoc managedBean, String JavaDoc beanKey) {
160         ManagedResource mr = this.attributeSource.getManagedResource(getClassToExpose(managedBean));
161         return (mr != null ? mr.getDescription() : "");
162     }
163
164     /**
165      * Creates a description for the attribute corresponding to this property
166      * descriptor. Attempts to create the description using metadata from either
167      * the getter or setter attributes, otherwise uses the property name.
168      */

169     protected String JavaDoc getAttributeDescription(PropertyDescriptor JavaDoc propertyDescriptor, String JavaDoc beanKey) {
170         Method JavaDoc readMethod = propertyDescriptor.getReadMethod();
171         Method JavaDoc writeMethod = propertyDescriptor.getWriteMethod();
172
173         ManagedAttribute getter =
174                 (readMethod != null) ? this.attributeSource.getManagedAttribute(readMethod) : null;
175         ManagedAttribute setter =
176                 (writeMethod != null) ? this.attributeSource.getManagedAttribute(writeMethod) : null;
177
178         if (getter != null && StringUtils.hasText(getter.getDescription())) {
179             return getter.getDescription();
180         }
181         else if (setter != null && StringUtils.hasText(setter.getDescription())) {
182             return setter.getDescription();
183         }
184         return propertyDescriptor.getDisplayName();
185     }
186
187     /**
188      * Retrieves the description for the supplied <code>Method</code> from the
189      * metadata. Uses the method name is no description is present in the metadata.
190      */

191     protected String JavaDoc getOperationDescription(Method JavaDoc method, String JavaDoc beanKey) {
192         PropertyDescriptor JavaDoc pd = BeanUtils.findPropertyForMethod(method);
193         if (pd != null) {
194             ManagedAttribute ma = this.attributeSource.getManagedAttribute(method);
195             if (ma != null && StringUtils.hasText(ma.getDescription())) {
196                 return ma.getDescription();
197             }
198             return method.getName();
199         }
200         else {
201             ManagedOperation mo = this.attributeSource.getManagedOperation(method);
202             if (mo != null && StringUtils.hasText(mo.getDescription())) {
203                 return mo.getDescription();
204             }
205             return method.getName();
206         }
207     }
208
209     /**
210      * Reads <code>MBeanParameterInfo</code> from the <code>ManagedOperationParameter</code>
211      * attributes attached to a method. Returns an empty array of <code>MBeanParameterInfo</code>
212      * if no attributes are found.
213      */

214     protected MBeanParameterInfo JavaDoc[] getOperationParameters(Method JavaDoc method, String JavaDoc beanKey) {
215         ManagedOperationParameter[] params = this.attributeSource.getManagedOperationParameters(method);
216         if (params == null || params.length == 0) {
217             return new MBeanParameterInfo JavaDoc[0];
218         }
219
220         MBeanParameterInfo JavaDoc[] parameterInfo = new MBeanParameterInfo JavaDoc[params.length];
221         Class JavaDoc[] methodParameters = method.getParameterTypes();
222
223         for (int i = 0; i < params.length; i++) {
224             ManagedOperationParameter param = params[i];
225             parameterInfo[i] =
226                     new MBeanParameterInfo JavaDoc(param.getName(), methodParameters[i].getName(), param.getDescription());
227         }
228
229         return parameterInfo;
230     }
231
232     /**
233      * Reads the {@link ManagedNotification} metadata from the <code>Class</code> of the managed resource
234      * and generates and returns the corresponding {@link ModelMBeanNotificationInfo} metadata.
235      */

236     protected ModelMBeanNotificationInfo JavaDoc[] getNotificationInfo(Object JavaDoc managedBean, String JavaDoc beanKey) {
237         ManagedNotification[] notificationAttributes =
238                 this.attributeSource.getManagedNotifications(getClassToExpose(managedBean));
239         ModelMBeanNotificationInfo JavaDoc[] notificationInfos =
240                 new ModelMBeanNotificationInfo JavaDoc[notificationAttributes.length];
241
242         for (int i = 0; i < notificationAttributes.length; i++) {
243             ManagedNotification attribute = notificationAttributes[i];
244             notificationInfos[i] = JmxMetadataUtils.convertToModelMBeanNotificationInfo(attribute);
245         }
246
247         return notificationInfos;
248     }
249
250     /**
251      * Adds descriptor fields from the <code>ManagedResource</code> attribute
252      * to the MBean descriptor. Specifically, adds the <code>currencyTimeLimit</code>,
253      * <code>persistPolicy</code>, <code>persistPeriod</code>, <code>persistLocation</code>
254      * and <code>persistName</code> descriptor fields if they are present in the metadata.
255      */

256     protected void populateMBeanDescriptor(Descriptor JavaDoc desc, Object JavaDoc managedBean, String JavaDoc beanKey) {
257         ManagedResource mr = this.attributeSource.getManagedResource(getClassToExpose(managedBean));
258         if (mr == null) {
259             throw new InvalidMetadataException(
260                     "No ManagedResource attribute found for class: " + getClassToExpose(managedBean));
261         }
262
263         applyCurrencyTimeLimit(desc, mr.getCurrencyTimeLimit());
264
265         // Do not use Boolean.toString(boolean) here, to preserve JDK 1.3 compatibility!
266
if (mr.isLog()) {
267             desc.setField(FIELD_LOG, "true");
268         }
269         if (StringUtils.hasLength(mr.getLogFile())) {
270             desc.setField(FIELD_LOG_FILE, mr.getLogFile());
271         }
272
273         if (StringUtils.hasLength(mr.getPersistPolicy())) {
274             desc.setField(FIELD_PERSIST_POLICY, mr.getPersistPolicy());
275         }
276         if (mr.getPersistPeriod() >= 0) {
277             desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(mr.getPersistPeriod()));
278         }
279         if (StringUtils.hasLength(mr.getPersistName())) {
280             desc.setField(FIELD_PERSIST_NAME, mr.getPersistName());
281         }
282         if (StringUtils.hasLength(mr.getPersistLocation())) {
283             desc.setField(FIELD_PERSIST_LOCATION, mr.getPersistLocation());
284         }
285     }
286
287     /**
288      * Adds descriptor fields from the <code>ManagedAttribute</code> attribute
289      * to the attribute descriptor. Specifically, adds the <code>currencyTimeLimit</code>,
290      * <code>default</code>, <code>persistPolicy</code> and <code>persistPeriod</code>
291      * descriptor fields if they are present in the metadata.
292      */

293     protected void populateAttributeDescriptor(Descriptor JavaDoc desc, Method JavaDoc getter, Method JavaDoc setter, String JavaDoc beanKey) {
294         ManagedAttribute gma =
295                 (getter == null) ? ManagedAttribute.EMPTY : this.attributeSource.getManagedAttribute(getter);
296         ManagedAttribute sma =
297                 (setter == null) ? ManagedAttribute.EMPTY : this.attributeSource.getManagedAttribute(setter);
298
299         applyCurrencyTimeLimit(desc, resolveIntDescriptor(gma.getCurrencyTimeLimit(), sma.getCurrencyTimeLimit()));
300
301         Object JavaDoc defaultValue = resolveObjectDescriptor(gma.getDefaultValue(), sma.getDefaultValue());
302         desc.setField(FIELD_DEFAULT, defaultValue);
303
304         String JavaDoc persistPolicy = resolveStringDescriptor(gma.getPersistPolicy(), sma.getPersistPolicy());
305         if (StringUtils.hasLength(persistPolicy)) {
306             desc.setField(FIELD_PERSIST_POLICY, persistPolicy);
307         }
308         int persistPeriod = resolveIntDescriptor(gma.getPersistPeriod(), sma.getPersistPeriod());
309         if (persistPeriod >= 0) {
310             desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(persistPeriod));
311         }
312     }
313
314     /**
315      * Adds descriptor fields from the <code>ManagedAttribute</code> attribute
316      * to the attribute descriptor. Specifically, adds the <code>currencyTimeLimit</code>
317      * descriptor field if it is present in the metadata.
318      */

319     protected void populateOperationDescriptor(Descriptor JavaDoc desc, Method JavaDoc method, String JavaDoc beanKey) {
320         ManagedOperation mo = this.attributeSource.getManagedOperation(method);
321         if (mo != null) {
322             applyCurrencyTimeLimit(desc, mo.getCurrencyTimeLimit());
323         }
324     }
325
326     /**
327      * Determines which of two <code>int</code> values should be used as the value
328      * for an attribute descriptor. In general, only the getter or the setter will
329      * be have a non-negative value so we use that value. In the event that both values
330      * are non-negative, we use the greater of the two. This method can be used to
331      * resolve any <code>int</code> valued descriptor where there are two possible values.
332      * @param getter the int value associated with the getter for this attribute
333      * @param setter the int associated with the setter for this attribute
334      */

335     private int resolveIntDescriptor(int getter, int setter) {
336         return (getter >= setter ? getter : setter);
337     }
338
339     /**
340      * Locates the value of a descriptor based on values attached
341      * to both the getter and setter methods. If both have values
342      * supplied then the value attached to the getter is preferred.
343      * @param getter the Object value associated with the get method
344      * @param setter the Object value associated with the set method
345      * @return the appropriate Object to use as the value for the descriptor
346      */

347     private Object JavaDoc resolveObjectDescriptor(Object JavaDoc getter, Object JavaDoc setter) {
348         return (getter != null ? getter : setter);
349     }
350
351     /**
352      * Locates the value of a descriptor based on values attached
353      * to both the getter and setter methods. If both have values
354      * supplied then the value attached to the getter is preferred.
355      * The supplied default value is used to check to see if the value
356      * associated with the getter has changed from the default.
357      * @param getter the String value associated with the get method
358      * @param setter the String value associated with the set method
359      * @return the appropriate String to use as the value for the descriptor
360      */

361     private String JavaDoc resolveStringDescriptor(String JavaDoc getter, String JavaDoc setter) {
362         return (StringUtils.hasLength(getter) ? getter : setter);
363     }
364
365 }
366
Popular Tags