1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package groovy.util;
47
48 import groovy.lang.GroovyObjectSupport;
49 import groovy.lang.GroovyRuntimeException;
50
51 import java.util.HashMap;
52 import java.util.Map;
53 import java.util.Collection;
54 import java.util.ArrayList;
55 import java.util.List;
56 import java.util.Iterator;
57 import java.io.IOException;
58
59 import javax.management.Attribute;
60 import javax.management.JMException;
61 import javax.management.MBeanException;
62 import javax.management.MBeanInfo;
63 import javax.management.MBeanOperationInfo;
64 import javax.management.MBeanParameterInfo;
65 import javax.management.ObjectName;
66 import javax.management.MBeanServerConnection;
67 import javax.management.MBeanAttributeInfo;
68
69
70 /***
71 * A GroovyObject facade for an underlying MBean which acts like a normal
72 * groovy object but which is actually implemented via
73 * an underlying JMX MBean.
74 * Properties and normal method invocations
75 * delegate to the MBeanServer to the actual MBean.
76 *
77 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
78 * @author Steve Button
79 * @version $Revision: 1.6 $
80 */
81 public class GroovyMBean extends GroovyObjectSupport {
82
83 private MBeanServerConnection server;
84 private ObjectName name;
85 private MBeanInfo beanInfo;
86 private Map operations = new HashMap();
87
88
89 public GroovyMBean(MBeanServerConnection server, ObjectName name) throws JMException, IOException {
90 this.server = server;
91 this.name = name;
92 this.beanInfo = server.getMBeanInfo(name);
93
94
95 MBeanOperationInfo[] operationInfos = beanInfo.getOperations();
96 for (int i = 0; i < operationInfos.length; i++) {
97 MBeanOperationInfo info = operationInfos[i];
98 String signature[] = createSignature(info);
99
100
101
102 String operationKey = createOperationKey(info.getName(), signature.length);
103 operations.put(operationKey, signature);
104 }
105
106 }
107
108 public MBeanServerConnection server() {
109 return server;
110 }
111
112 public ObjectName name() {
113 return name;
114 }
115
116 public MBeanInfo info() {
117 return beanInfo;
118 }
119
120 public Object getProperty(String property) {
121 try {
122 return server.getAttribute(name, property);
123 }
124 catch (MBeanException e) {
125 throw new GroovyRuntimeException("Could not access property: " + property + ". Reason: " + e, e.getTargetException());
126 }
127 catch (Exception e) {
128 throw new GroovyRuntimeException("Could not access property: " + property + ". Reason: " + e, e);
129 }
130 }
131
132 public void setProperty(String property, Object value) {
133 try {
134 server.setAttribute(name, new Attribute(property, value));
135 }
136 catch (MBeanException e) {
137 throw new GroovyRuntimeException("Could not set property: " + property + ". Reason: " + e, e.getTargetException());
138 }
139 catch (Exception e) {
140 throw new GroovyRuntimeException("Could not set property: " + property + ". Reason: " + e, e);
141 }
142 }
143
144 public Object invokeMethod(String method, Object arguments) {
145
146
147 Object[] argArray = null;
148 if (arguments instanceof Object[]) {
149 argArray = (Object[]) arguments;
150 } else {
151 argArray = new Object[]{arguments};
152 }
153
154 String operationKey = createOperationKey(method, argArray.length);
155 String[] signature = (String[]) operations.get(operationKey);
156
157 if (signature != null) {
158 try {
159 return server.invoke(name, method, argArray, signature);
160 }
161 catch (MBeanException e) {
162 throw new GroovyRuntimeException("Could not invoke method: " + method + ". Reason: " + e, e.getTargetException());
163 }
164 catch (Exception e) {
165 throw new GroovyRuntimeException("Could not invoke method: " + method + ". Reason: " + e, e);
166 }
167 } else {
168 return super.invokeMethod(method, arguments);
169 }
170 }
171
172 protected String[] createSignature(MBeanOperationInfo info) {
173 MBeanParameterInfo[] params = info.getSignature();
174 String[] answer = new String[params.length];
175 for (int i = 0; i < params.length; i++) {
176 answer[i] = params[i].getType();
177 }
178 return answer;
179 }
180
181 /***
182 * Construct a simple key based on the method name and the number of parameters
183 *
184 * @param operation - the mbean operation name
185 * @param params - the number of parameters the operation supports
186 * @return simple unique identifier for a method
187 */
188 protected String createOperationKey(String operation, int params) {
189
190 return operation + "_" + params;
191 }
192
193 /***
194 * List of the names of each of the attributes on the MBean
195 *
196 * @return list of attribute names
197 */
198 public Collection listAttributeNames() {
199 ArrayList list = new ArrayList();
200 try {
201 MBeanAttributeInfo[] attrs = beanInfo.getAttributes();
202 for (int i = 0; i < attrs.length; i++) {
203 MBeanAttributeInfo attr = attrs[i];
204 list.add(attr.getName());
205 }
206 }
207 catch (Throwable t) {
208 }
209 finally {
210 }
211 return list;
212 }
213
214 /***
215 * The values of each of the attributes on the MBean
216 *
217 * @return list of values of each attribute
218 */
219 public List listAttributeValues() {
220 ArrayList list = new ArrayList();
221 Collection names = listAttributeNames();
222 for (Iterator iterator = names.iterator(); iterator.hasNext();) {
223 String name = (String) iterator.next();
224 try {
225 Object val = this.getProperty(name);
226 if (val != null) {
227 list.add(name + " : " + val.toString());
228 }
229 }
230 catch (RuntimeException e) {
231
232
233
234 }
235 }
236 return list;
237 }
238
239
240 /***
241 * List of string representations of all of the attributes on the MBean.
242 *
243 * @return list of descriptions of each attribute on the mbean
244 */
245 public Collection listAttributeDescriptions() {
246 ArrayList list = new ArrayList();
247 try {
248 MBeanAttributeInfo[] attrs = beanInfo.getAttributes();
249 for (int i = 0; i < attrs.length; i++) {
250 MBeanAttributeInfo attr = attrs[i];
251 list.add(describeAttribute(attr));
252 }
253 }
254 catch (Throwable t) {
255 }
256 finally {
257 }
258 return list;
259 }
260
261 /***
262 * Description of the specified attribute name.
263 *
264 * @param attr - the attribute
265 * @return String the description
266 */
267 protected String describeAttribute(MBeanAttributeInfo attr) {
268 StringBuffer buf = new StringBuffer();
269 buf.append("(");
270 if (attr.isReadable()) {
271 buf.append("r");
272 }
273 if (attr.isWritable()) {
274 buf.append("w");
275 }
276 buf.append(") ")
277 .append(attr.getType())
278 .append(" ")
279 .append(attr.getName());
280 return buf.toString();
281 }
282
283 /***
284 * Description of the specified attribute name.
285 *
286 * @param attributeName - stringified name of the attribute
287 * @return the description
288 */
289 public String describeAttribute(String attributeName) {
290 String ret = "Attribute not found";
291 try {
292 MBeanAttributeInfo[] attributes = beanInfo.getAttributes();
293 for (int i = 0; i < attributes.length; i++) {
294 MBeanAttributeInfo attribute = attributes[i];
295 if (attribute.getName().equals(attributeName)) {
296 return describeAttribute(attribute);
297 }
298 }
299 }
300 catch (Throwable t) {
301 }
302 return ret;
303 }
304
305 /***
306 * Names of all the operations available on the MBean.
307 *
308 * @return all the operations on the MBean
309 */
310 public Collection listOperationNames() {
311 ArrayList list = new ArrayList();
312 try {
313 MBeanOperationInfo[] operations = beanInfo.getOperations();
314 for (int i = 0; i < operations.length; i++) {
315 MBeanOperationInfo operation = operations[i];
316 list.add(operation.getName());
317 }
318 }
319 catch (Throwable t) {
320 }
321 return list;
322 }
323
324
325 /***
326 * Description of all of the operations available on the MBean.
327 *
328 * @return full description of each operation on the MBean
329 */
330 public Collection listOperationDescriptions() {
331 ArrayList list = new ArrayList();
332 try {
333 MBeanOperationInfo[] operations = beanInfo.getOperations();
334 for (int i = 0; i < operations.length; i++) {
335 MBeanOperationInfo operation = operations[i];
336 list.add(describeOperation(operation));
337 }
338 }
339 catch (Throwable t) {
340 }
341 return list;
342 }
343
344 /***
345 * Get the dessciptions of the named operation. This returns a Collection since
346 * operations can be overloaded and one operationName can have multiple forms.
347 *
348 * @param operationName
349 * @return Collection of operation description
350 */
351 public List describeOperation(String operationName) {
352 ArrayList list = new ArrayList();
353 try {
354 MBeanOperationInfo[] operations = beanInfo.getOperations();
355 for (int i = 0; i < operations.length; i++) {
356 MBeanOperationInfo operation = operations[i];
357 if (operation.getName().equals(operationName)) {
358 list.add(describeOperation(operation));
359 }
360 }
361 }
362 catch (Throwable t) {
363 }
364 return list;
365 }
366
367 /***
368 * Dessciption of the named operation.
369 *
370 * @param operation
371 * @return description
372 */
373 protected String describeOperation(MBeanOperationInfo operation) {
374 StringBuffer buf = new StringBuffer();
375 buf.append(operation.getReturnType())
376 .append(" ")
377 .append(operation.getName())
378 .append("(");
379
380 MBeanParameterInfo[] params = operation.getSignature();
381 for (int j = 0; j < params.length; j++) {
382 MBeanParameterInfo param = params[j];
383 if (j != 0) {
384 buf.append(", ");
385 }
386 buf.append(param.getType())
387 .append(" ")
388 .append(param.getName());
389 }
390 buf.append(")");
391 return buf.toString();
392 }
393
394
395 /***
396 * Return an end user readable representation of the underlying MBean
397 * @return the user readable description
398 */
399 public String toString() {
400 StringBuffer buf = new StringBuffer();
401 buf.append("MBean Name:")
402 .append("\n ")
403 .append(name.getCanonicalName())
404 .append("\n ");
405 if (!listAttributeDescriptions().isEmpty()) {
406 buf.append("\nAttributes:");
407 for (Iterator iterator = listAttributeDescriptions().iterator(); iterator.hasNext();) {
408 buf.append("\n ")
409 .append((String) iterator.next());
410 }
411 }
412 if (!listOperationDescriptions().isEmpty()) {
413 buf.append("\nOperations:");
414 for (Iterator iterator = listOperationDescriptions().iterator(); iterator.hasNext();) {
415 buf.append("\n ")
416 .append((String) iterator.next());
417 }
418 }
419 return buf.toString();
420 }
421 }