1 /* |
1 /* |
2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
36 import java.io.InvalidObjectException; |
36 import java.io.InvalidObjectException; |
37 import java.security.AccessController; |
37 import java.security.AccessController; |
38 import java.security.PrivilegedAction; |
38 import java.security.PrivilegedAction; |
39 import java.security.PrivilegedActionException; |
39 import java.security.PrivilegedActionException; |
40 import java.security.PrivilegedExceptionAction; |
40 import java.security.PrivilegedExceptionAction; |
41 import javax.management.*; |
|
42 import javax.management.openmbean.*; |
41 import javax.management.openmbean.*; |
43 import static javax.management.openmbean.SimpleType.*; |
42 import static javax.management.openmbean.SimpleType.*; |
44 import com.sun.management.VMOption; |
|
45 |
43 |
46 /** |
44 /** |
47 * A mapped mxbean type maps a Java type to an open type. |
45 * A mapped mxbean type maps a Java type to an open type. |
48 * Only the following Java types are mappable |
46 * Only the following Java types are mappable |
49 * (currently required by the platform MXBeans): |
47 * (currently required by the platform MXBeans): |
111 MappedMXBeanType mt = new BasicMXBeanType(c, ot); |
109 MappedMXBeanType mt = new BasicMXBeanType(c, ot); |
112 convertedTypes.put(c, mt); |
110 convertedTypes.put(c, mt); |
113 return mt; |
111 return mt; |
114 } |
112 } |
115 |
113 |
116 static synchronized MappedMXBeanType getMappedType(Type t) |
114 public static synchronized MappedMXBeanType getMappedType(Type t) |
117 throws OpenDataException { |
115 throws OpenDataException { |
118 MappedMXBeanType mt = convertedTypes.get(t); |
116 MappedMXBeanType mt = convertedTypes.get(t); |
119 if (mt == null) { |
117 if (mt == null) { |
120 mt = newMappedType(t); |
118 mt = newMappedType(t); |
121 } |
119 } |
150 MappedMXBeanType mt = getMappedType(t); |
148 MappedMXBeanType mt = getMappedType(t); |
151 return mt.toOpenTypeData(data); |
149 return mt.toOpenTypeData(data); |
152 } |
150 } |
153 |
151 |
154 // Return the mapped open type |
152 // Return the mapped open type |
155 OpenType<?> getOpenType() { |
153 public OpenType<?> getOpenType() { |
156 return openType; |
154 return openType; |
157 } |
155 } |
158 |
156 |
159 boolean isBasicType() { |
157 boolean isBasicType() { |
160 return isBasicType; |
158 return isBasicType; |
175 abstract Type getJavaType(); |
173 abstract Type getJavaType(); |
176 |
174 |
177 // return name of the class or the generic type |
175 // return name of the class or the generic type |
178 abstract String getName(); |
176 abstract String getName(); |
179 |
177 |
180 abstract Object toOpenTypeData(Object javaTypeData) |
178 public abstract Object toOpenTypeData(Object javaTypeData) |
181 throws OpenDataException; |
179 throws OpenDataException; |
182 |
180 |
183 abstract Object toJavaTypeData(Object openTypeData) |
181 public abstract Object toJavaTypeData(Object openTypeData) |
184 throws OpenDataException, InvalidObjectException; |
182 throws OpenDataException, InvalidObjectException; |
185 |
183 |
186 // Basic Types - Classes that do not require data conversion |
184 // Basic Types - Classes that do not require data conversion |
187 // including primitive types and all SimpleType |
185 // including primitive types and all SimpleType |
188 // |
186 // |
241 |
239 |
242 String getName() { |
240 String getName() { |
243 return enumClass.getName(); |
241 return enumClass.getName(); |
244 } |
242 } |
245 |
243 |
246 Object toOpenTypeData(Object data) throws OpenDataException { |
244 public Object toOpenTypeData(Object data) throws OpenDataException { |
247 return ((Enum) data).name(); |
245 return ((Enum) data).name(); |
248 } |
246 } |
249 |
247 |
250 Object toJavaTypeData(Object data) |
248 public Object toJavaTypeData(Object data) |
251 throws OpenDataException, InvalidObjectException { |
249 throws OpenDataException, InvalidObjectException { |
252 |
250 |
253 try { |
251 try { |
254 return Enum.valueOf(enumClass, (String) data); |
252 return Enum.valueOf(enumClass, (String) data); |
255 } catch (IllegalArgumentException e) { |
253 } catch (IllegalArgumentException e) { |
313 |
311 |
314 String getName() { |
312 String getName() { |
315 return arrayClass.getName(); |
313 return arrayClass.getName(); |
316 } |
314 } |
317 |
315 |
318 Object toOpenTypeData(Object data) throws OpenDataException { |
316 public Object toOpenTypeData(Object data) throws OpenDataException { |
319 // If the base element type is a basic type |
317 // If the base element type is a basic type |
320 // return the data as no conversion is needed. |
318 // return the data as no conversion is needed. |
321 // Primitive types are not converted to wrappers. |
319 // Primitive types are not converted to wrappers. |
322 if (baseElementType.isBasicType()) { |
320 if (baseElementType.isBasicType()) { |
323 return data; |
321 return data; |
338 } |
336 } |
339 return openArray; |
337 return openArray; |
340 } |
338 } |
341 |
339 |
342 |
340 |
343 Object toJavaTypeData(Object data) |
341 public Object toJavaTypeData(Object data) |
344 throws OpenDataException, InvalidObjectException { |
342 throws OpenDataException, InvalidObjectException { |
345 |
343 |
346 // If the base element type is a basic type |
344 // If the base element type is a basic type |
347 // return the data as no conversion is needed. |
345 // return the data as no conversion is needed. |
348 if (baseElementType.isBasicType()) { |
346 if (baseElementType.isBasicType()) { |
468 openArray[i++] = paramType.toOpenTypeData(o); |
466 openArray[i++] = paramType.toOpenTypeData(o); |
469 } |
467 } |
470 return openArray; |
468 return openArray; |
471 } |
469 } |
472 |
470 |
473 Object toJavaTypeData(Object data) |
471 public Object toJavaTypeData(Object data) |
474 throws OpenDataException, InvalidObjectException { |
472 throws OpenDataException, InvalidObjectException { |
475 |
473 |
476 final Object[] openArray = (Object[]) data; |
474 final Object[] openArray = (Object[]) data; |
477 List<Object> result = new ArrayList<>(openArray.length); |
475 List<Object> result = new ArrayList<>(openArray.length); |
478 for (Object o : openArray) { |
476 for (Object o : openArray) { |
536 |
534 |
537 String getName() { |
535 String getName() { |
538 return typeName; |
536 return typeName; |
539 } |
537 } |
540 |
538 |
541 Object toOpenTypeData(Object data) throws OpenDataException { |
539 public Object toOpenTypeData(Object data) throws OpenDataException { |
542 final Map<Object,Object> map = (Map<Object,Object>) data; |
540 final Map<Object,Object> map = (Map<Object,Object>) data; |
543 final TabularType tabularType = (TabularType) openType; |
541 final TabularType tabularType = (TabularType) openType; |
544 final TabularData table = new TabularDataSupport(tabularType); |
542 final TabularData table = new TabularDataSupport(tabularType); |
545 final CompositeType rowType = tabularType.getRowType(); |
543 final CompositeType rowType = tabularType.getRowType(); |
546 |
544 |
554 table.put(row); |
552 table.put(row); |
555 } |
553 } |
556 return table; |
554 return table; |
557 } |
555 } |
558 |
556 |
559 Object toJavaTypeData(Object data) |
557 public Object toJavaTypeData(Object data) |
560 throws OpenDataException, InvalidObjectException { |
558 throws OpenDataException, InvalidObjectException { |
561 |
559 |
562 final TabularData td = (TabularData) data; |
560 final TabularData td = (TabularData) data; |
563 |
561 |
564 Map<Object, Object> result = new HashMap<>(); |
562 Map<Object, Object> result = new HashMap<>(); |
603 // o If FooType is an array, the item type is an array and |
601 // o If FooType is an array, the item type is an array and |
604 // its element type is determined as described above. |
602 // its element type is determined as described above. |
605 // |
603 // |
606 static class CompositeDataMXBeanType extends MappedMXBeanType { |
604 static class CompositeDataMXBeanType extends MappedMXBeanType { |
607 final Class<?> javaClass; |
605 final Class<?> javaClass; |
608 final boolean isCompositeData; |
606 boolean isCompositeData = false; |
609 Method fromMethod = null; |
607 Method fromMethod = null; |
|
608 Method toMethod = null; |
610 |
609 |
611 CompositeDataMXBeanType(Class<?> c) throws OpenDataException { |
610 CompositeDataMXBeanType(Class<?> c) throws OpenDataException { |
612 this.javaClass = c; |
611 this.javaClass = c; |
613 this.mappedTypeClass = COMPOSITE_DATA_CLASS; |
612 this.mappedTypeClass = COMPOSITE_DATA_CLASS; |
614 |
613 |
622 } catch (PrivilegedActionException e) { |
621 } catch (PrivilegedActionException e) { |
623 // ignore NoSuchMethodException since we allow classes |
622 // ignore NoSuchMethodException since we allow classes |
624 // that has no from method to be embeded in another class. |
623 // that has no from method to be embeded in another class. |
625 } |
624 } |
626 |
625 |
|
626 // check if a static "toCompositeData" method exists |
|
627 try { |
|
628 toMethod = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { |
|
629 public Method run() throws NoSuchMethodException { |
|
630 Method m = javaClass.getDeclaredMethod("toCompositeData", javaClass); |
|
631 if (m != null |
|
632 && CompositeData.class.isAssignableFrom(m.getReturnType()) |
|
633 && Modifier.isStatic(m.getModifiers())) { |
|
634 m.setAccessible(true); |
|
635 return m; |
|
636 } else { |
|
637 return null; |
|
638 } |
|
639 } |
|
640 }); |
|
641 } catch (PrivilegedActionException e) { |
|
642 // ignore NoSuchMethodException since we allow classes |
|
643 // that has no from method to be embeded in another class. |
|
644 } |
|
645 |
627 if (COMPOSITE_DATA_CLASS.isAssignableFrom(c)) { |
646 if (COMPOSITE_DATA_CLASS.isAssignableFrom(c)) { |
628 // c implements CompositeData - set openType to null |
647 // c implements CompositeData - set openType to null |
629 // defer generating the CompositeType |
648 // defer generating the CompositeType |
630 // until the object is constructed |
649 // until the object is constructed |
631 this.isCompositeData = true; |
650 this.isCompositeData = true; |
634 this.isCompositeData = false; |
653 this.isCompositeData = false; |
635 |
654 |
636 // Make a CompositeData containing all the getters |
655 // Make a CompositeData containing all the getters |
637 final Method[] methods = |
656 final Method[] methods = |
638 AccessController.doPrivileged(new PrivilegedAction<Method[]>() { |
657 AccessController.doPrivileged(new PrivilegedAction<Method[]>() { |
639 public Method[] run() { |
658 public Method[] run() { |
640 return javaClass.getMethods(); |
659 return javaClass.getMethods(); |
641 } |
660 } |
642 }); |
661 }); |
643 final List<String> names = new ArrayList<>(); |
662 final List<String> names = new ArrayList<>(); |
644 final List<OpenType<?>> types = new ArrayList<>(); |
663 final List<OpenType<?>> types = new ArrayList<>(); |
645 |
664 |
646 /* Select public methods that look like "T getX()" or "boolean |
665 /* Select public methods that look like "T getX()" or "boolean |
647 isX()", where T is not void and X is not the empty |
666 isX()", where T is not void and X is not the empty |
648 string. Exclude "Class getClass()" inherited from Object. */ |
667 string. Exclude "Class getClass()" inherited from Object. */ |
649 for (int i = 0; i < methods.length; i++) { |
668 for (int i = 0; i < methods.length; i++) { |
650 final Method method = methods[i]; |
669 final Method method = methods[i]; |
651 final String name = method.getName(); |
670 final String name = method.getName(); |
652 final Type type = method.getGenericReturnType(); |
671 final Type type = method.getGenericReturnType(); |
653 final String rest; |
672 final String rest; |
674 types.add(toOpenType(type)); |
693 types.add(toOpenType(type)); |
675 } |
694 } |
676 |
695 |
677 final String[] nameArray = names.toArray(new String[0]); |
696 final String[] nameArray = names.toArray(new String[0]); |
678 openType = new CompositeType(c.getName(), |
697 openType = new CompositeType(c.getName(), |
679 c.getName(), |
698 c.getName(), |
680 nameArray, // field names |
699 nameArray, // field names |
681 nameArray, // field descriptions |
700 nameArray, // field descriptions |
682 types.toArray(new OpenType<?>[0])); |
701 types.toArray(new OpenType<?>[0])); |
683 } |
702 } |
684 } |
703 } |
685 |
704 |
686 Type getJavaType() { |
705 Type getJavaType() { |
687 return javaClass; |
706 return javaClass; |
689 |
708 |
690 String getName() { |
709 String getName() { |
691 return javaClass.getName(); |
710 return javaClass.getName(); |
692 } |
711 } |
693 |
712 |
694 Object toOpenTypeData(Object data) throws OpenDataException { |
713 public Object toOpenTypeData(Object data) throws OpenDataException { |
|
714 if (toMethod != null) { |
|
715 try { |
|
716 return toMethod.invoke(null, data); |
|
717 } catch (IllegalAccessException e) { |
|
718 // should never reach here |
|
719 throw new AssertionError(e); |
|
720 } catch (InvocationTargetException e) { |
|
721 final OpenDataException ode |
|
722 = new OpenDataException("Failed to invoke " |
|
723 + toMethod.getName() + " to convert " + javaClass.getName() |
|
724 + " to CompositeData"); |
|
725 ode.initCause(e); |
|
726 throw ode; |
|
727 } |
|
728 } |
|
729 |
695 if (data instanceof MemoryUsage) { |
730 if (data instanceof MemoryUsage) { |
696 return MemoryUsageCompositeData.toCompositeData((MemoryUsage) data); |
731 return MemoryUsageCompositeData.toCompositeData((MemoryUsage) data); |
697 } |
732 } |
698 |
733 |
699 if (data instanceof ThreadInfo) { |
734 if (data instanceof ThreadInfo) { |
708 } |
743 } |
709 |
744 |
710 if (data instanceof MemoryNotificationInfo) { |
745 if (data instanceof MemoryNotificationInfo) { |
711 return MemoryNotifInfoCompositeData. |
746 return MemoryNotifInfoCompositeData. |
712 toCompositeData((MemoryNotificationInfo) data); |
747 toCompositeData((MemoryNotificationInfo) data); |
713 } |
|
714 |
|
715 if (data instanceof VMOption) { |
|
716 return VMOptionCompositeData.toCompositeData((VMOption) data); |
|
717 } |
748 } |
718 |
749 |
719 if (isCompositeData) { |
750 if (isCompositeData) { |
720 // Classes that implement CompositeData |
751 // Classes that implement CompositeData |
721 // |
752 // |
730 |
761 |
731 throw new OpenDataException(javaClass.getName() + |
762 throw new OpenDataException(javaClass.getName() + |
732 " is not supported for platform MXBeans"); |
763 " is not supported for platform MXBeans"); |
733 } |
764 } |
734 |
765 |
735 Object toJavaTypeData(Object data) |
766 public Object toJavaTypeData(Object data) |
736 throws OpenDataException, InvalidObjectException { |
767 throws OpenDataException, InvalidObjectException { |
737 |
768 |
738 if (fromMethod == null) { |
769 if (fromMethod == null) { |
739 throw new AssertionError("Does not support data conversion"); |
770 throw new AssertionError("Does not support data conversion"); |
740 } |
771 } |