001: /*
002: * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.management;
027:
028: import java.lang.management.MemoryUsage;
029: import java.lang.management.MemoryNotificationInfo;
030: import java.lang.management.MonitorInfo;
031: import java.lang.management.LockInfo;
032: import java.lang.management.ThreadInfo;
033: import java.lang.reflect.*;
034: import java.util.List;
035: import java.util.Map;
036: import java.util.*;
037: import java.io.InvalidObjectException;
038: import java.security.AccessController;
039: import java.security.PrivilegedAction;
040: import java.security.PrivilegedActionException;
041: import java.security.PrivilegedExceptionAction;
042: import javax.management.*;
043: import javax.management.openmbean.*;
044: import static javax.management.openmbean.SimpleType.*;
045: import com.sun.management.VMOption;
046:
047: /**
048: * A mapped mxbean type maps a Java type to an open type.
049: * Only the following Java types are mappable
050: * (currently required by the platform MXBeans):
051: * 1. Primitive types
052: * 2. Wrapper classes such java.lang.Integer, etc
053: * 3. Classes with only getter methods and with a static "from" method
054: * that takes a CompositeData argument.
055: * 4. E[] where E is a type of 1-4 (can be multi-dimensional array)
056: * 5. List<E> where E is a type of 1-3
057: * 6. Map<K, V> where K and V are a type of 1-4
058: *
059: * OpenDataException will be thrown if a Java type is not supported.
060: */
061: // Suppress unchecked cast warnings at line 442, 523 and 546
062: // Suppress unchecked calls at line 235, 284, 380 and 430.
063: @SuppressWarnings("unchecked")
064: public abstract class MappedMXBeanType {
065: private static final WeakHashMap<Type, MappedMXBeanType> convertedTypes = new WeakHashMap<Type, MappedMXBeanType>();
066:
067: boolean isBasicType = false;
068: OpenType openType = inProgress;
069: Class mappedTypeClass;
070:
071: static synchronized MappedMXBeanType newMappedType(Type javaType)
072: throws OpenDataException {
073:
074: MappedMXBeanType mt = null;
075: if (javaType instanceof Class) {
076: final Class c = (Class) javaType;
077: if (c.isEnum()) {
078: mt = new EnumMXBeanType(c);
079: } else if (c.isArray()) {
080: mt = new ArrayMXBeanType(c);
081: } else {
082: mt = new CompositeDataMXBeanType(c);
083: }
084: } else if (javaType instanceof ParameterizedType) {
085: final ParameterizedType pt = (ParameterizedType) javaType;
086: final Type rawType = pt.getRawType();
087: if (rawType instanceof Class) {
088: final Class rc = (Class) rawType;
089: if (rc == List.class) {
090: mt = new ListMXBeanType(pt);
091: } else if (rc == Map.class) {
092: mt = new MapMXBeanType(pt);
093: }
094: }
095: } else if (javaType instanceof GenericArrayType) {
096: final GenericArrayType t = (GenericArrayType) javaType;
097: mt = new GenericArrayMXBeanType(t);
098: }
099: // No open type mapped for the javaType
100: if (mt == null) {
101: throw new OpenDataException(javaType
102: + " is not a supported MXBean type.");
103: }
104: convertedTypes.put(javaType, mt);
105: return mt;
106: }
107:
108: // basic types do not require data mapping
109: static synchronized MappedMXBeanType newBasicType(Class c,
110: OpenType ot) throws OpenDataException {
111: MappedMXBeanType mt = new BasicMXBeanType(c, ot);
112: convertedTypes.put(c, mt);
113: return mt;
114: }
115:
116: static synchronized MappedMXBeanType getMappedType(Type t)
117: throws OpenDataException {
118: MappedMXBeanType mt = convertedTypes.get(t);
119: if (mt == null) {
120: mt = newMappedType(t);
121: }
122:
123: if (mt.getOpenType() instanceof InProgress) {
124: throw new OpenDataException("Recursive data structure");
125: }
126: return mt;
127: }
128:
129: // Convert a class to an OpenType
130: public static synchronized OpenType toOpenType(Type t)
131: throws OpenDataException {
132: MappedMXBeanType mt = getMappedType(t);
133: return mt.getOpenType();
134: }
135:
136: public static Object toJavaTypeData(Object openData, Type t)
137: throws OpenDataException, InvalidObjectException {
138: if (openData == null) {
139: return null;
140: }
141: MappedMXBeanType mt = getMappedType(t);
142: return mt.toJavaTypeData(openData);
143: }
144:
145: public static Object toOpenTypeData(Object data, Type t)
146: throws OpenDataException {
147: if (data == null) {
148: return null;
149: }
150: MappedMXBeanType mt = getMappedType(t);
151: return mt.toOpenTypeData(data);
152: }
153:
154: // Return the mapped open type
155: OpenType getOpenType() {
156: return openType;
157: }
158:
159: boolean isBasicType() {
160: return isBasicType;
161: }
162:
163: // Return the type name of the mapped open type
164: // For primitive types, the type name is the same as the javaType
165: // but the mapped open type is the wrapper class
166: String getTypeName() {
167: return getMappedTypeClass().getName();
168: }
169:
170: // Return the mapped open type
171: Class getMappedTypeClass() {
172: return mappedTypeClass;
173: }
174:
175: abstract Type getJavaType();
176:
177: // return name of the class or the generic type
178: abstract String getName();
179:
180: abstract Object toOpenTypeData(Object javaTypeData)
181: throws OpenDataException;
182:
183: abstract Object toJavaTypeData(Object openTypeData)
184: throws OpenDataException, InvalidObjectException;
185:
186: // Basic Types - Classes that do not require data conversion
187: // including primitive types and all SimpleType
188: //
189: // Mapped open type: SimpleType for corresponding basic type
190: //
191: // Data Mapping:
192: // T <-> T (no conversion)
193: //
194: static class BasicMXBeanType extends MappedMXBeanType {
195: final Class basicType;
196:
197: BasicMXBeanType(Class c, OpenType openType) {
198: this .basicType = c;
199: this .openType = openType;
200: this .mappedTypeClass = c;
201: this .isBasicType = true;
202: }
203:
204: Type getJavaType() {
205: return basicType;
206: }
207:
208: String getName() {
209: return basicType.getName();
210: }
211:
212: Object toOpenTypeData(Object data) throws OpenDataException {
213: return data;
214: }
215:
216: Object toJavaTypeData(Object data) throws OpenDataException,
217: InvalidObjectException {
218:
219: return data;
220: }
221: }
222:
223: // Enum subclasses
224: // Mapped open type - String
225: //
226: // Data Mapping:
227: // Enum <-> enum's name
228: //
229: static class EnumMXBeanType extends MappedMXBeanType {
230: final Class enumClass;
231:
232: EnumMXBeanType(Class c) {
233: this .enumClass = c;
234: this .openType = STRING;
235: this .mappedTypeClass = String.class;
236: }
237:
238: Type getJavaType() {
239: return enumClass;
240: }
241:
242: String getName() {
243: return enumClass.getName();
244: }
245:
246: Object toOpenTypeData(Object data) throws OpenDataException {
247: return ((Enum) data).name();
248: }
249:
250: Object toJavaTypeData(Object data) throws OpenDataException,
251: InvalidObjectException {
252:
253: try {
254: return Enum.valueOf(enumClass, (String) data);
255: } catch (IllegalArgumentException e) {
256: // missing enum constants
257: final InvalidObjectException ioe = new InvalidObjectException(
258: "Enum constant named " + (String) data
259: + " is missing");
260: ioe.initCause(e);
261: throw ioe;
262: }
263: }
264: }
265:
266: // Array E[]
267: // Mapped open type - Array with element of OpenType for E
268: //
269: // Data Mapping:
270: // E[] <-> openTypeData(E)[]
271: //
272: static class ArrayMXBeanType extends MappedMXBeanType {
273: final Class arrayClass;
274: protected MappedMXBeanType componentType;
275: protected MappedMXBeanType baseElementType;
276:
277: ArrayMXBeanType(Class c) throws OpenDataException {
278: this .arrayClass = c;
279: this .componentType = getMappedType(c.getComponentType());
280:
281: StringBuilder className = new StringBuilder();
282: Class et = c;
283: int dim;
284: for (dim = 0; et.isArray(); dim++) {
285: className.append('[');
286: et = et.getComponentType();
287: }
288: baseElementType = getMappedType(et);
289: if (et.isPrimitive()) {
290: className = new StringBuilder(c.getName());
291: } else {
292: className.append("L" + baseElementType.getTypeName()
293: + ";");
294: }
295: try {
296: mappedTypeClass = Class.forName(className.toString());
297: } catch (ClassNotFoundException e) {
298: final OpenDataException ode = new OpenDataException(
299: "Cannot obtain array class");
300: ode.initCause(e);
301: throw ode;
302: }
303:
304: openType = new ArrayType(dim, baseElementType.getOpenType());
305: }
306:
307: protected ArrayMXBeanType() {
308: arrayClass = null;
309: };
310:
311: Type getJavaType() {
312: return arrayClass;
313: }
314:
315: String getName() {
316: return arrayClass.getName();
317: }
318:
319: Object toOpenTypeData(Object data) throws OpenDataException {
320: // If the base element type is a basic type
321: // return the data as no conversion is needed.
322: // Primitive types are not converted to wrappers.
323: if (baseElementType.isBasicType()) {
324: return data;
325: }
326:
327: final Object[] array = (Object[]) data;
328: final Object[] openArray = (Object[]) Array.newInstance(
329: componentType.getMappedTypeClass(), array.length);
330: int i = 0;
331: for (Object o : array) {
332: if (o == null) {
333: openArray[i] = null;
334: } else {
335: openArray[i] = componentType.toOpenTypeData(o);
336: }
337: i++;
338: }
339: return openArray;
340: }
341:
342: Object toJavaTypeData(Object data) throws OpenDataException,
343: InvalidObjectException {
344:
345: // If the base element type is a basic type
346: // return the data as no conversion is needed.
347: if (baseElementType.isBasicType()) {
348: return data;
349: }
350:
351: final Object[] openArray = (Object[]) data;
352: final Object[] array = (Object[]) Array.newInstance(
353: (Class) componentType.getJavaType(),
354: openArray.length);
355: int i = 0;
356: for (Object o : openArray) {
357: if (o == null) {
358: array[i] = null;
359: } else {
360: array[i] = componentType.toJavaTypeData(o);
361: }
362: i++;
363: }
364: return array;
365: }
366:
367: }
368:
369: static class GenericArrayMXBeanType extends ArrayMXBeanType {
370: final GenericArrayType gtype;
371:
372: GenericArrayMXBeanType(GenericArrayType gat)
373: throws OpenDataException {
374: this .gtype = gat;
375: this .componentType = getMappedType(gat
376: .getGenericComponentType());
377:
378: StringBuilder className = new StringBuilder();
379: Type elementType = gat;
380: int dim;
381: for (dim = 0; elementType instanceof GenericArrayType; dim++) {
382: className.append('[');
383: GenericArrayType et = (GenericArrayType) elementType;
384: elementType = et.getGenericComponentType();
385: }
386: baseElementType = getMappedType(elementType);
387: if (elementType instanceof Class
388: && ((Class) elementType).isPrimitive()) {
389: className = new StringBuilder(gat.toString());
390: } else {
391: className.append("L" + baseElementType.getTypeName()
392: + ";");
393: }
394: try {
395: mappedTypeClass = Class.forName(className.toString());
396: } catch (ClassNotFoundException e) {
397: final OpenDataException ode = new OpenDataException(
398: "Cannot obtain array class");
399: ode.initCause(e);
400: throw ode;
401: }
402:
403: openType = new ArrayType(dim, baseElementType.getOpenType());
404: }
405:
406: Type getJavaType() {
407: return gtype;
408: }
409:
410: String getName() {
411: return gtype.toString();
412: }
413: }
414:
415: // List<E>
416: // Mapped open type - Array with element of OpenType for E
417: //
418: // Data Mapping:
419: // List<E> <-> openTypeData(E)[]
420: //
421: static class ListMXBeanType extends MappedMXBeanType {
422: final ParameterizedType javaType;
423: final MappedMXBeanType paramType;
424: final String typeName;
425:
426: ListMXBeanType(ParameterizedType pt) throws OpenDataException {
427: this .javaType = pt;
428:
429: final Type[] argTypes = pt.getActualTypeArguments();
430: assert (argTypes.length == 1);
431:
432: if (!(argTypes[0] instanceof Class)) {
433: throw new OpenDataException("Element Type for " + pt
434: + " not supported");
435: }
436: final Class et = (Class) argTypes[0];
437: if (et.isArray()) {
438: throw new OpenDataException("Element Type for " + pt
439: + " not supported");
440: }
441: paramType = getMappedType(et);
442: typeName = "List<" + paramType.getName() + ">";
443:
444: try {
445: mappedTypeClass = Class.forName("[L"
446: + paramType.getTypeName() + ";");
447: } catch (ClassNotFoundException e) {
448: final OpenDataException ode = new OpenDataException(
449: "Array class not found");
450: ode.initCause(e);
451: throw ode;
452: }
453: openType = new ArrayType(1, paramType.getOpenType());
454: }
455:
456: Type getJavaType() {
457: return javaType;
458: }
459:
460: String getName() {
461: return typeName;
462: }
463:
464: Object toOpenTypeData(Object data) throws OpenDataException {
465: final List<Object> list = (List<Object>) data;
466:
467: final Object[] openArray = (Object[]) Array.newInstance(
468: paramType.getMappedTypeClass(), list.size());
469: int i = 0;
470: for (Object o : list) {
471: openArray[i++] = paramType.toOpenTypeData(o);
472: }
473: return openArray;
474: }
475:
476: Object toJavaTypeData(Object data) throws OpenDataException,
477: InvalidObjectException {
478:
479: final Object[] openArray = (Object[]) data;
480: List<Object> result = new ArrayList<Object>(
481: openArray.length);
482: for (Object o : openArray) {
483: result.add(paramType.toJavaTypeData(o));
484: }
485: return result;
486: }
487: }
488:
489: private static final String KEY = "key";
490: private static final String VALUE = "value";
491: private static final String[] mapIndexNames = { KEY };
492: private static final String[] mapItemNames = { KEY, VALUE };
493:
494: // Map<K,V>
495: // Mapped open type - TabularType with row type:
496: // CompositeType:
497: // "key" of openDataType(K)
498: // "value" of openDataType(V)
499: // "key" is the index name
500: //
501: // Data Mapping:
502: // Map<K,V> <-> TabularData
503: //
504: static class MapMXBeanType extends MappedMXBeanType {
505: final ParameterizedType javaType;
506: final MappedMXBeanType keyType;
507: final MappedMXBeanType valueType;
508: final String typeName;
509:
510: MapMXBeanType(ParameterizedType pt) throws OpenDataException {
511: this .javaType = pt;
512:
513: final Type[] argTypes = pt.getActualTypeArguments();
514: assert (argTypes.length == 2);
515: this .keyType = getMappedType(argTypes[0]);
516: this .valueType = getMappedType(argTypes[1]);
517:
518: // FIXME: generate typeName for generic
519: typeName = "Map<" + keyType.getName() + ","
520: + valueType.getName() + ">";
521: final OpenType[] mapItemTypes = new OpenType[] {
522: keyType.getOpenType(), valueType.getOpenType(), };
523: final CompositeType rowType = new CompositeType(typeName,
524: typeName, mapItemNames, mapItemNames, mapItemTypes);
525:
526: openType = new TabularType(typeName, typeName, rowType,
527: mapIndexNames);
528: mappedTypeClass = javax.management.openmbean.TabularData.class;
529: }
530:
531: Type getJavaType() {
532: return javaType;
533: }
534:
535: String getName() {
536: return typeName;
537: }
538:
539: Object toOpenTypeData(Object data) throws OpenDataException {
540: final Map<Object, Object> map = (Map<Object, Object>) data;
541: final TabularType tabularType = (TabularType) openType;
542: final TabularData table = new TabularDataSupport(
543: tabularType);
544: final CompositeType rowType = tabularType.getRowType();
545:
546: for (Map.Entry entry : map.entrySet()) {
547: final Object key = keyType.toOpenTypeData(entry
548: .getKey());
549: final Object value = valueType.toOpenTypeData(entry
550: .getValue());
551: final CompositeData row = new CompositeDataSupport(
552: rowType, mapItemNames, new Object[] { key,
553: value });
554: table.put(row);
555: }
556: return table;
557: }
558:
559: Object toJavaTypeData(Object data) throws OpenDataException,
560: InvalidObjectException {
561:
562: final TabularData td = (TabularData) data;
563:
564: Map<Object, Object> result = new HashMap<Object, Object>();
565: for (CompositeData row : (Collection<CompositeData>) td
566: .values()) {
567: Object key = keyType.toJavaTypeData(row.get(KEY));
568: Object value = valueType.toJavaTypeData(row.get(VALUE));
569: result.put(key, value);
570: }
571: return result;
572: }
573: }
574:
575: private static final Class<?> COMPOSITE_DATA_CLASS = javax.management.openmbean.CompositeData.class;
576:
577: // Classes that have a static from method
578: // Mapped open type - CompositeData
579: //
580: // Data Mapping:
581: // Classes <-> CompositeData
582: //
583: // The name and type of items for a class are identified from
584: // the getter methods. For example, a class defines a method:
585: //
586: // public FooType getFoo();
587: //
588: // The composite data view for this class will contain one
589: // item entry for a "foo" attribute and the item type is
590: // one of the open types defined in the OpenType class that
591: // can be determined in the following manner:
592: // o If FooType is a primitive type, the item type a wrapper
593: // class for the corresponding primitive type (such as
594: // Integer, Long, Boolean, etc).
595: // o If FooType is of type CompositeData or TabularData,
596: // the item type is FooType.
597: // o If FooType is an Enum, the item type is a String and
598: // the value is the name of the enum constant.
599: // o If FooType is a class or an interface other than the above,
600: // the item type is CompositeData. The same convention
601: // can be recursively applied to the FooType class when
602: // constructing the composite data for the "foo" attribute.
603: // o If FooType is an array, the item type is an array and
604: // its element type is determined as described above.
605: //
606: static class CompositeDataMXBeanType extends MappedMXBeanType {
607: final Class<?> javaClass;
608: final boolean isCompositeData;
609: Method fromMethod = null;
610:
611: CompositeDataMXBeanType(Class c) throws OpenDataException {
612: this .javaClass = c;
613: this .mappedTypeClass = COMPOSITE_DATA_CLASS;
614:
615: // check if a static from method exists
616: try {
617: fromMethod = AccessController
618: .doPrivileged(new PrivilegedExceptionAction<Method>() {
619: public Method run()
620: throws NoSuchMethodException {
621: return javaClass.getMethod("from",
622: COMPOSITE_DATA_CLASS);
623: }
624: });
625: } catch (PrivilegedActionException e) {
626: // ignore NoSuchMethodException since we allow classes
627: // that has no from method to be embeded in another class.
628: }
629:
630: if (COMPOSITE_DATA_CLASS.isAssignableFrom(c)) {
631: // c implements CompositeData - set openType to null
632: // defer generating the CompositeType
633: // until the object is constructed
634: this .isCompositeData = true;
635: this .openType = null;
636: } else {
637: this .isCompositeData = false;
638:
639: // Make a CompositeData containing all the getters
640: final Method[] methods = AccessController
641: .doPrivileged(new PrivilegedAction<Method[]>() {
642: public Method[] run() {
643: return javaClass.getMethods();
644: }
645: });
646: final List<String> names = new ArrayList<String>();
647: final List<OpenType> types = new ArrayList<OpenType>();
648:
649: /* Select public methods that look like "T getX()" or "boolean
650: isX()", where T is not void and X is not the empty
651: string. Exclude "Class getClass()" inherited from Object. */
652: for (int i = 0; i < methods.length; i++) {
653: final Method method = methods[i];
654: final String name = method.getName();
655: final Type type = method.getGenericReturnType();
656: final String rest;
657: if (name.startsWith("get")) {
658: rest = name.substring(3);
659: } else if (name.startsWith("is")
660: && type instanceof Class
661: && ((Class) type) == boolean.class) {
662: rest = name.substring(2);
663: } else {
664: // ignore non-getter methods
665: continue;
666: }
667:
668: if (rest.equals("")
669: || method.getParameterTypes().length > 0
670: || type == void.class
671: || rest.equals("Class")) {
672:
673: // ignore non-getter methods
674: continue;
675: }
676: names.add(decapitalize(rest));
677: types.add(toOpenType(type));
678: }
679:
680: final String[] nameArray = names.toArray(new String[0]);
681: openType = new CompositeType(c.getName(), c.getName(),
682: nameArray, // field names
683: nameArray, // field descriptions
684: types.toArray(new OpenType[0]));
685: }
686: }
687:
688: Type getJavaType() {
689: return javaClass;
690: }
691:
692: String getName() {
693: return javaClass.getName();
694: }
695:
696: Object toOpenTypeData(Object data) throws OpenDataException {
697: if (data instanceof MemoryUsage) {
698: return MemoryUsageCompositeData
699: .toCompositeData((MemoryUsage) data);
700: }
701:
702: if (data instanceof ThreadInfo) {
703: return ThreadInfoCompositeData
704: .toCompositeData((ThreadInfo) data);
705: }
706:
707: if (data instanceof LockInfo) {
708: if (data instanceof java.lang.management.MonitorInfo) {
709: return MonitorInfoCompositeData
710: .toCompositeData((MonitorInfo) data);
711: }
712: return LockDataConverter
713: .toLockInfoCompositeData((LockInfo) data);
714: }
715:
716: if (data instanceof MemoryNotificationInfo) {
717: return MemoryNotifInfoCompositeData
718: .toCompositeData((MemoryNotificationInfo) data);
719: }
720:
721: if (data instanceof VMOption) {
722: return VMOptionCompositeData
723: .toCompositeData((VMOption) data);
724: }
725:
726: if (isCompositeData) {
727: // Classes that implement CompositeData
728: //
729: // construct a new CompositeDataSupport object
730: // so that no other classes are sent over the wire
731: CompositeData cd = (CompositeData) data;
732: CompositeType ct = cd.getCompositeType();
733: String[] itemNames = (String[]) ct.keySet().toArray(
734: new String[0]);
735: Object[] itemValues = cd.getAll(itemNames);
736: return new CompositeDataSupport(ct, itemNames,
737: itemValues);
738: }
739:
740: throw new OpenDataException(javaClass.getName()
741: + " is not supported for platform MXBeans");
742: }
743:
744: Object toJavaTypeData(Object data) throws OpenDataException,
745: InvalidObjectException {
746:
747: if (fromMethod == null) {
748: throw new InternalError(
749: "Does not support data conversion");
750: }
751:
752: try {
753: return fromMethod.invoke(null, data);
754: } catch (IllegalAccessException e) {
755: // should never reach here
756: throw Util.newAssertionError(e);
757: } catch (InvocationTargetException e) {
758: final OpenDataException ode = new OpenDataException(
759: "Failed to invoke " + fromMethod.getName()
760: + " to convert CompositeData " + " to "
761: + javaClass.getName());
762: ode.initCause(e);
763: throw ode;
764: }
765: }
766: }
767:
768: private static class InProgress extends OpenType {
769: private static final String description = "Marker to detect recursive type use -- internal use only!";
770:
771: InProgress() throws OpenDataException {
772: super ("java.lang.String", "java.lang.String", description);
773: }
774:
775: public String toString() {
776: return description;
777: }
778:
779: public int hashCode() {
780: return 0;
781: }
782:
783: public boolean equals(Object o) {
784: return false;
785: }
786:
787: public boolean isValue(Object o) {
788: return false;
789: }
790: }
791:
792: private static final OpenType inProgress;
793: static {
794: OpenType t;
795: try {
796: t = new InProgress();
797: } catch (OpenDataException e) {
798: // Should not reach here
799: throw Util.newAssertionError(e);
800: }
801: inProgress = t;
802: }
803:
804: private static final OpenType[] simpleTypes = { BIGDECIMAL,
805: BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE, DOUBLE, FLOAT,
806: INTEGER, LONG, OBJECTNAME, SHORT, STRING, VOID, };
807: static {
808: try {
809: for (int i = 0; i < simpleTypes.length; i++) {
810: final OpenType t = simpleTypes[i];
811: Class c;
812: try {
813: c = Class.forName(t.getClassName(), false,
814: String.class.getClassLoader());
815: MappedMXBeanType.newBasicType(c, t);
816: } catch (ClassNotFoundException e) {
817: // the classes that these predefined types declare
818: // must exist!
819: throw Util.newAssertionError(e);
820: } catch (OpenDataException e) {
821: throw Util.newAssertionError(e);
822: }
823:
824: if (c.getName().startsWith("java.lang.")) {
825: try {
826: final Field typeField = c.getField("TYPE");
827: final Class primitiveType = (Class) typeField
828: .get(null);
829: MappedMXBeanType.newBasicType(primitiveType, t);
830: } catch (NoSuchFieldException e) {
831: // OK: must not be a primitive wrapper
832: } catch (IllegalAccessException e) {
833: // Should not reach here
834: throw Util.newAssertionError(e);
835: }
836: }
837: }
838: } catch (OpenDataException e) {
839: throw Util.newAssertionError(e);
840: }
841: }
842:
843: /**
844: * Utility method to take a string and convert it to normal Java variable
845: * name capitalization. This normally means converting the first
846: * character from upper case to lower case, but in the (unusual) special
847: * case when there is more than one character and both the first and
848: * second characters are upper case, we leave it alone.
849: * <p>
850: * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
851: * as "URL".
852: *
853: * @param name The string to be decapitalized.
854: * @return The decapitalized version of the string.
855: */
856: private static String decapitalize(String name) {
857: if (name == null || name.length() == 0) {
858: return name;
859: }
860: if (name.length() > 1 && Character.isUpperCase(name.charAt(1))
861: && Character.isUpperCase(name.charAt(0))) {
862: return name;
863: }
864: char chars[] = name.toCharArray();
865: chars[0] = Character.toLowerCase(chars[0]);
866: return new String(chars);
867: }
868:
869: }
|