1
17
18
19 package org.apache.tomcat.util.modeler;
20
21
22 import java.lang.reflect.Method;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.concurrent.locks.ReadWriteLock;
26 import java.util.concurrent.locks.ReentrantReadWriteLock;
27
28 import javax.management.AttributeNotFoundException;
29 import javax.management.DynamicMBean;
30 import javax.management.InstanceNotFoundException;
31 import javax.management.MBeanAttributeInfo;
32 import javax.management.MBeanConstructorInfo;
33 import javax.management.MBeanException;
34 import javax.management.MBeanInfo;
35 import javax.management.MBeanNotificationInfo;
36 import javax.management.MBeanOperationInfo;
37 import javax.management.ReflectionException;
38 import javax.management.RuntimeOperationsException;
39 import javax.management.ServiceNotFoundException;
40
41 import org.apache.tomcat.util.buf.StringUtils;
42 import org.apache.tomcat.util.res.StringManager;
43
44
45
51 public class ManagedBean implements java.io.Serializable {
52
53 private static final long serialVersionUID = 1L;
54 private static final StringManager sm = StringManager.getManager(ManagedBean.class);
55
56 private static final String BASE_MBEAN = "org.apache.tomcat.util.modeler.BaseModelMBean";
57
58 static final Class<?>[] NO_ARGS_PARAM_SIG = new Class[0];
59
60
61 private final ReadWriteLock mBeanInfoLock = new ReentrantReadWriteLock();
62
66 private transient volatile MBeanInfo info = null;
67
68 private Map<String,AttributeInfo> attributes = new HashMap<>();
69
70 private Map<String,OperationInfo> operations = new HashMap<>();
71
72 protected String className = BASE_MBEAN;
73 protected String description = null;
74 protected String domain = null;
75 protected String group = null;
76 protected String name = null;
77
78 private NotificationInfo notifications[] = new NotificationInfo[0];
79 protected String type = null;
80
81
84 public ManagedBean() {
85 AttributeInfo ai=new AttributeInfo();
86 ai.setName("modelerType");
87 ai.setDescription("Type of the modeled resource. Can be set only once");
88 ai.setType("java.lang.String");
89 ai.setWriteable(false);
90 addAttribute(ai);
91 }
92
93
94
95
96
99 public AttributeInfo[] getAttributes() {
100 AttributeInfo result[] = new AttributeInfo[attributes.size()];
101 attributes.values().toArray(result);
102 return result;
103 }
104
105
106
113 public String getClassName() {
114 return this.className;
115 }
116
117 public void setClassName(String className) {
118 mBeanInfoLock.writeLock().lock();
119 try {
120 this.className = className;
121 this.info = null;
122 } finally {
123 mBeanInfoLock.writeLock().unlock();
124 }
125 }
126
127
128
131 public String getDescription() {
132 return this.description;
133 }
134
135 public void setDescription(String description) {
136 mBeanInfoLock.writeLock().lock();
137 try {
138 this.description = description;
139 this.info = null;
140 } finally {
141 mBeanInfoLock.writeLock().unlock();
142 }
143 }
144
145
146
150 public String getDomain() {
151 return this.domain;
152 }
153
154 public void setDomain(String domain) {
155 this.domain = domain;
156 }
157
158
159
162 public String getGroup() {
163 return this.group;
164 }
165
166 public void setGroup(String group) {
167 this.group = group;
168 }
169
170
171
175 public String getName() {
176 return this.name;
177 }
178
179 public void setName(String name) {
180 mBeanInfoLock.writeLock().lock();
181 try {
182 this.name = name;
183 this.info = null;
184 } finally {
185 mBeanInfoLock.writeLock().unlock();
186 }
187 }
188
189
190
193 public NotificationInfo[] getNotifications() {
194 return this.notifications;
195 }
196
197
198
201 public OperationInfo[] getOperations() {
202 OperationInfo[] result = new OperationInfo[operations.size()];
203 operations.values().toArray(result);
204 return result;
205 }
206
207
208
213 public String getType() {
214 return this.type;
215 }
216
217 public void setType(String type) {
218 mBeanInfoLock.writeLock().lock();
219 try {
220 this.type = type;
221 this.info = null;
222 } finally {
223 mBeanInfoLock.writeLock().unlock();
224 }
225 }
226
227
228
229
230
231
236 public void addAttribute(AttributeInfo attribute) {
237 attributes.put(attribute.getName(), attribute);
238 }
239
240
241
246 public void addNotification(NotificationInfo notification) {
247 mBeanInfoLock.writeLock().lock();
248 try {
249 NotificationInfo results[] =
250 new NotificationInfo[notifications.length + 1];
251 System.arraycopy(notifications, 0, results, 0,
252 notifications.length);
253 results[notifications.length] = notification;
254 notifications = results;
255 this.info = null;
256 } finally {
257 mBeanInfoLock.writeLock().unlock();
258 }
259 }
260
261
262
267 public void addOperation(OperationInfo operation) {
268 operations.put(createOperationKey(operation), operation);
269 }
270
271
272
289 public DynamicMBean createMBean(Object instance)
290 throws InstanceNotFoundException,
291 MBeanException, RuntimeOperationsException {
292
293 BaseModelMBean mbean = null;
294
295
296 if(getClassName().equals(BASE_MBEAN)) {
297
298 mbean = new BaseModelMBean();
299 } else {
300 Class<?> clazz = null;
301 Exception ex = null;
302 try {
303 clazz = Class.forName(getClassName());
304 } catch (Exception e) {
305 }
306
307 if( clazz==null ) {
308 try {
309 ClassLoader cl= Thread.currentThread().getContextClassLoader();
310 if ( cl != null)
311 clazz= cl.loadClass(getClassName());
312 } catch (Exception e) {
313 ex=e;
314 }
315 }
316
317 if( clazz==null) {
318 throw new MBeanException
319 (ex, sm.getString("managedMBean.cannotLoadClass", getClassName()));
320 }
321 try {
322
323 mbean = (BaseModelMBean) clazz.getConstructor().newInstance();
324 } catch (RuntimeOperationsException e) {
325 throw e;
326 } catch (Exception e) {
327 throw new MBeanException
328 (e, sm.getString("managedMBean.cannotInstantiateClass", getClassName()));
329 }
330 }
331
332 mbean.setManagedBean(this);
333
334
335 try {
336 if (instance != null)
337 mbean.setManagedResource(instance, "ObjectReference");
338 } catch (InstanceNotFoundException e) {
339 throw e;
340 }
341
342 return mbean;
343 }
344
345
346
351 MBeanInfo getMBeanInfo() {
352
353
354 mBeanInfoLock.readLock().lock();
355 try {
356 if (info != null) {
357 return info;
358 }
359 } finally {
360 mBeanInfoLock.readLock().unlock();
361 }
362
363 mBeanInfoLock.writeLock().lock();
364 try {
365 if (info == null) {
366
367 AttributeInfo attrs[] = getAttributes();
368 MBeanAttributeInfo attributes[] =
369 new MBeanAttributeInfo[attrs.length];
370 for (int i = 0; i < attrs.length; i++)
371 attributes[i] = attrs[i].createAttributeInfo();
372
373 OperationInfo opers[] = getOperations();
374 MBeanOperationInfo operations[] =
375 new MBeanOperationInfo[opers.length];
376 for (int i = 0; i < opers.length; i++)
377 operations[i] = opers[i].createOperationInfo();
378
379
380 NotificationInfo notifs[] = getNotifications();
381 MBeanNotificationInfo notifications[] =
382 new MBeanNotificationInfo[notifs.length];
383 for (int i = 0; i < notifs.length; i++)
384 notifications[i] = notifs[i].createNotificationInfo();
385
386
387
388 info = new MBeanInfo(getClassName(),
389 getDescription(),
390 attributes,
391 new MBeanConstructorInfo[] {},
392 operations,
393 notifications);
394 }
395
396 return info;
397 } finally {
398 mBeanInfoLock.writeLock().unlock();
399 }
400 }
401
402
403
406 @Override
407 public String toString() {
408
409 StringBuilder sb = new StringBuilder("ManagedBean[");
410 sb.append("name=");
411 sb.append(name);
412 sb.append(", className=");
413 sb.append(className);
414 sb.append(", description=");
415 sb.append(description);
416 if (group != null) {
417 sb.append(", group=");
418 sb.append(group);
419 }
420 sb.append(", type=");
421 sb.append(type);
422 sb.append("]");
423 return sb.toString();
424
425 }
426
427 Method getGetter(String aname, BaseModelMBean mbean, Object resource)
428 throws AttributeNotFoundException, ReflectionException {
429
430 Method m = null;
431
432 AttributeInfo attrInfo = attributes.get(aname);
433
434 if (attrInfo == null)
435 throw new AttributeNotFoundException(sm.getString("managedMBean.noAttribute", aname, resource));
436
437 String getMethod = attrInfo.getGetMethod();
438
439 Object object = null;
440 NoSuchMethodException exception = null;
441 try {
442 object = mbean;
443 m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);
444 } catch (NoSuchMethodException e) {
445 exception = e;
446 }
447 if (m == null && resource != null) {
448 try {
449 object = resource;
450 m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);
451 exception=null;
452 } catch (NoSuchMethodException e) {
453 exception = e;
454 }
455 }
456 if (exception != null) {
457 throw new ReflectionException(exception, sm.getString("managedMBean.noGet", getMethod, resource));
458 }
459
460 return m;
461 }
462
463 public Method getSetter(String aname, BaseModelMBean bean, Object resource)
464 throws AttributeNotFoundException, ReflectionException {
465
466 Method m = null;
467
468 AttributeInfo attrInfo = attributes.get(aname);
469 if (attrInfo == null) {
470 throw new AttributeNotFoundException(sm.getString("managedMBean.noAttribute", aname, resource));
471 }
472
473
474 String setMethod = attrInfo.getSetMethod();
475 String argType=attrInfo.getType();
476
477 Class<?> signature[] = new Class[] { BaseModelMBean.getAttributeClass( argType ) };
478
479 Object object = null;
480 NoSuchMethodException exception = null;
481 try {
482 object = bean;
483 m = object.getClass().getMethod(setMethod, signature);
484 } catch (NoSuchMethodException e) {
485 exception = e;
486 }
487 if (m == null && resource != null) {
488 try {
489 object = resource;
490 m = object.getClass().getMethod(setMethod, signature);
491 exception=null;
492 } catch (NoSuchMethodException e) {
493 exception = e;
494 }
495 }
496 if (exception != null) {
497 throw new ReflectionException(exception, sm.getString("managedMBean.noSet", setMethod, resource));
498 }
499
500 return m;
501 }
502
503 public Method getInvoke(String aname, Object[] params, String[] signature, BaseModelMBean bean, Object resource)
504 throws MBeanException, ReflectionException {
505
506 Method method = null;
507
508 if (params == null)
509 params = new Object[0];
510 if (signature == null)
511 signature = new String[0];
512 if (params.length != signature.length)
513 throw new RuntimeOperationsException(
514 new IllegalArgumentException(sm.getString("managedMBean.inconsistentArguments")),
515 sm.getString("managedMBean.inconsistentArguments"));
516
517
518
519 OperationInfo opInfo =
520 operations.get(createOperationKey(aname, signature));
521 if (opInfo == null)
522 throw new MBeanException(new ServiceNotFoundException(sm.getString("managedMBean.noOperation", aname)),
523 sm.getString("managedMBean.noOperation", aname));
524
525
526
527 Class<?> types[] = new Class[signature.length];
528 for (int i = 0; i < signature.length; i++) {
529 types[i] = BaseModelMBean.getAttributeClass(signature[i]);
530 }
531
532
533
534
535 Object object = null;
536 Exception exception = null;
537 try {
538 object = bean;
539 method = object.getClass().getMethod(aname, types);
540 } catch (NoSuchMethodException e) {
541 exception = e;
542 }
543 try {
544 if ((method == null) && (resource != null)) {
545 object = resource;
546 method = object.getClass().getMethod(aname, types);
547 }
548 } catch (NoSuchMethodException e) {
549 exception = e;
550 }
551 if (method == null) {
552 throw new ReflectionException(exception, sm.getString("managedMBean.noMethod", aname));
553 }
554
555 return method;
556 }
557
558
559 private String createOperationKey(OperationInfo operation) {
560 StringBuilder key = new StringBuilder(operation.getName());
561 key.append('(');
562 StringUtils.join(operation.getSignature(), ',', (x) -> x.getType(), key);
563 key.append(')');
564
565 return key.toString().intern();
566 }
567
568
569 private String createOperationKey(String methodName, String[] parameterTypes) {
570 StringBuilder key = new StringBuilder(methodName);
571 key.append('(');
572 StringUtils.join(parameterTypes, ',', key);
573 key.append(')');
574
575 return key.toString().intern();
576 }
577 }
578