KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > mbeanserver > OpenConverter


1 /*
2  * @(#)OpenConverter.java 1.22 07/10/25
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.mbeanserver;
9
10 import static com.sun.jmx.mbeanserver.Util.*;
11
12 import com.sun.jmx.remote.util.EnvHelp;
13
14 import java.beans.ConstructorProperties JavaDoc;
15 import java.io.InvalidObjectException JavaDoc;
16 import java.lang.ref.WeakReference JavaDoc;
17 import java.lang.reflect.Array JavaDoc;
18 import java.lang.reflect.Constructor JavaDoc;
19 import java.lang.reflect.Field JavaDoc;
20 import java.lang.reflect.GenericArrayType JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Modifier JavaDoc;
23 import java.lang.reflect.ParameterizedType JavaDoc;
24 import java.lang.reflect.Proxy JavaDoc;
25 import java.lang.reflect.Type JavaDoc;
26 import java.util.Arrays JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.BitSet JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Comparator JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.SortedMap JavaDoc;
36 import java.util.SortedSet JavaDoc;
37 import java.util.TreeSet JavaDoc;
38 import java.util.WeakHashMap JavaDoc;
39 import javax.management.JMX JavaDoc;
40 import javax.management.ObjectName JavaDoc;
41 import javax.management.openmbean.ArrayType JavaDoc;
42 import javax.management.openmbean.CompositeData JavaDoc;
43 import javax.management.openmbean.CompositeDataInvocationHandler JavaDoc;
44 import javax.management.openmbean.CompositeDataSupport JavaDoc;
45 import javax.management.openmbean.CompositeDataView JavaDoc;
46 import javax.management.openmbean.CompositeType JavaDoc;
47 import javax.management.openmbean.OpenDataException JavaDoc;
48 import javax.management.openmbean.OpenType JavaDoc;
49 import javax.management.openmbean.SimpleType JavaDoc;
50 import javax.management.openmbean.TabularData JavaDoc;
51 import javax.management.openmbean.TabularDataSupport JavaDoc;
52 import javax.management.openmbean.TabularType JavaDoc;
53 import static javax.management.openmbean.SimpleType JavaDoc.*;
54
55 /**
56    <p>A converter between Java types and the limited set of classes
57    defined by Open MBeans.</p>
58
59    <p>A Java type is an instance of java.lang.reflect.Type. For our
60    purposes, it is either a Class, such as String.class or int.class;
61    or a ParameterizedType, such as List<String> or Map<Integer,
62    String[]>. On J2SE 1.4 and earlier, it can only be a Class.</p>
63
64    <p>Each Type is associated with an OpenConverter. The
65    OpenConverter defines an OpenType corresponding to the Type, plus a
66    Java class corresponding to the OpenType. For example:</p>
67
68    <pre>
69    Type Open class OpenType
70    ---- ---------- --------
71    Integer Integer SimpleType.INTEGER
72    int int SimpleType.INTEGER
73    Integer[] Integer[] ArrayType(1, SimpleType.INTEGER)
74    int[] Integer[] ArrayType(SimpleType.INTEGER, true)
75    String[][] String[][] ArrayType(2, SimpleType.STRING)
76    List<String> String[] ArrayType(1, SimpleType.STRING)
77    ThreadState (an Enum) String SimpleType.STRING
78    Map<Integer, String[]> TabularData TabularType(
79                              CompositeType(
80                            {"key", SimpleType.INTEGER},
81                            {"value",
82                              ArrayType(1,
83                           SimpleType.STRING)}),
84                          indexNames={"key"})
85    </pre>
86
87    <p>Apart from simple types, arrays, and collections, Java types are
88    converted through introspection into CompositeType. The Java type
89    must have at least one getter (method such as "int getSize()" or
90    "boolean isBig()"), and we must be able to deduce how to
91    reconstruct an instance of the Java class from the values of the
92    getters using one of various heuristics.</p>
93
94    @since 1.6
95  */

96 public abstract class OpenConverter {
97     private OpenConverter(Type JavaDoc targetType, OpenType JavaDoc openType,
98               Class JavaDoc openClass) {
99     this.targetType = targetType;
100     this.openType = openType;
101     this.openClass = openClass;
102     }
103
104     /** <p>Convert an instance of openClass into an instance of targetType. */
105     public final Object JavaDoc fromOpenValue(MXBeanLookup lookup, Object JavaDoc value)
106             throws InvalidObjectException JavaDoc {
107         if (value == null)
108             return null;
109         else
110             return fromNonNullOpenValue(lookup, value);
111     }
112     
113     abstract Object JavaDoc fromNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value)
114             throws InvalidObjectException JavaDoc;
115
116     /** <p>Throw an appropriate InvalidObjectException if we will not be able
117         to convert back from the open data to the original Java object.</p> */

118     void checkReconstructible() throws InvalidObjectException JavaDoc {
119         // subclasses override if action necessary
120
}
121
122     /** <p>Convert an instance of targetType into an instance of openClass. */
123     final Object JavaDoc toOpenValue(MXBeanLookup lookup, Object JavaDoc value)
124             throws OpenDataException JavaDoc {
125         if (value == null)
126             return null;
127         else
128             return toNonNullOpenValue(lookup, value);
129     }
130     
131     abstract Object JavaDoc toNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value)
132             throws OpenDataException JavaDoc;
133
134     /** <p>True if and only if this OpenConverter's toOpenValue and fromOpenValue
135     methods are the identity function.</p> */

136     boolean isIdentity() {
137     return false;
138     }
139
140     final Type JavaDoc getTargetType() {
141     return targetType;
142     }
143
144     final OpenType JavaDoc getOpenType() {
145     return openType;
146     }
147
148     /* The Java class corresponding to getOpenType(). This is the class
149        named by getOpenType().getClassName(), except that it may be a
150        primitive type or an array of primitive type. */

151     final Class JavaDoc getOpenClass() {
152     return openClass;
153     }
154
155     private final Type JavaDoc targetType;
156     private final OpenType JavaDoc openType;
157     private final Class JavaDoc openClass;
158     
159     private static final class ConverterMap
160         extends WeakHashMap JavaDoc<Type JavaDoc, WeakReference JavaDoc<OpenConverter>> {}
161
162     private static final ConverterMap converterMap = new ConverterMap();
163
164     /** Following List simply serves to keep a reference to predefined
165         OpenConverters so they don't get garbage collected. */

166     private static final List JavaDoc<OpenConverter> permanentConverters = newList();
167
168     private static synchronized OpenConverter getConverter(Type JavaDoc type) {
169         // Work around bug 5041784:
170
if (type instanceof GenericArrayType JavaDoc) {
171             Type JavaDoc component = ((GenericArrayType JavaDoc) type).getGenericComponentType();
172             if (component instanceof Class JavaDoc)
173                 type = Array.newInstance((Class JavaDoc<?>) component, 0).getClass();
174         }
175
176         WeakReference JavaDoc<OpenConverter> wr = converterMap.get(type);
177         return (wr == null) ? null : wr.get();
178     }
179
180     private static synchronized void putConverter(Type JavaDoc type,
181                                                   OpenConverter conv) {
182         WeakReference JavaDoc<OpenConverter> wr =
183             new WeakReference JavaDoc<OpenConverter>(conv);
184         converterMap.put(type, wr);
185     }
186     
187     private static synchronized void putPermanentConverter(Type JavaDoc type,
188                                                            OpenConverter conv) {
189         putConverter(type, conv);
190         permanentConverters.add(conv);
191     }
192
193     static {
194     /* Set up the mappings for Java types that map to SimpleType. */
195
196     final OpenType JavaDoc[] simpleTypes = {
197         BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE,
198         DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING,
199         VOID,
200     };
201
202     for (int i = 0; i < simpleTypes.length; i++) {
203         final OpenType JavaDoc t = simpleTypes[i];
204         Class JavaDoc c;
205         try {
206         c = Class.forName(t.getClassName(), false,
207                   ObjectName JavaDoc.class.getClassLoader());
208         } catch (ClassNotFoundException JavaDoc e) {
209         // the classes that these predefined types declare must exist!
210
throw new Error JavaDoc(e);
211         }
212         final OpenConverter conv = new IdentityConverter(c, t, c);
213             putPermanentConverter(c, conv);
214
215             if (c.getName().startsWith("java.lang.")) {
216         try {
217             final Field JavaDoc typeField = c.getField("TYPE");
218             final Class JavaDoc primitiveType = (Class JavaDoc) typeField.get(null);
219             final OpenConverter primitiveConv =
220             new IdentityConverter(primitiveType, t, primitiveType);
221                     putPermanentConverter(primitiveType,
222                                           primitiveConv);
223                     if (primitiveType != void.class) {
224                         final Class JavaDoc primitiveArrayType =
225                             Array.newInstance(primitiveType, 0).getClass();
226                         final OpenType JavaDoc primitiveArrayOpenType =
227                             ArrayType.getPrimitiveArrayType(primitiveArrayType);
228                         final OpenConverter primitiveArrayConv =
229                             new IdentityConverter(primitiveArrayType,
230                                                   primitiveArrayOpenType,
231                                                   primitiveArrayType);
232                         putPermanentConverter(primitiveArrayType,
233                                               primitiveArrayConv);
234                     }
235         } catch (NoSuchFieldException JavaDoc e) {
236             // OK: must not be a primitive wrapper
237
} catch (IllegalAccessException JavaDoc e) {
238             // Should not reach here
239
assert(false);
240         }
241         }
242     }
243     }
244
245     /** Get the converter for the given Java type, creating it if necessary. */
246     public static synchronized OpenConverter toConverter(Type JavaDoc objType)
247         throws OpenDataException JavaDoc {
248         
249         if (inProgress.containsKey(objType))
250             throw new OpenDataException JavaDoc("Recursive data structure");
251         
252         OpenConverter conv;
253
254     conv = getConverter(objType);
255     if (conv != null)
256             return conv;
257         
258         inProgress.put(objType, objType);
259         try {
260             conv = makeConverter(objType);
261         } finally {
262             inProgress.remove(objType);
263         }
264
265     putConverter(objType, conv);
266         return conv;
267     }
268     
269     private static OpenConverter makeConverter(Type JavaDoc objType)
270             throws OpenDataException JavaDoc {
271         
272     /* It's not yet worth formalizing these tests by having for example
273        an array of factory classes, each of which says whether it
274        recognizes the Type (Chain of Responsibility pattern). */

275         if (objType instanceof GenericArrayType JavaDoc) {
276             Type JavaDoc componentType =
277                 ((GenericArrayType JavaDoc) objType).getGenericComponentType();
278             return makeArrayOrCollectionConverter(objType, componentType);
279         } else if (objType instanceof Class JavaDoc) {
280             Class JavaDoc objClass = (Class JavaDoc<?>) objType;
281             if (objClass.isEnum()) {
282                 return makeEnumConverter(objClass);
283             } else if (objClass.isArray()) {
284                 Type JavaDoc componentType = objClass.getComponentType();
285                 return makeArrayOrCollectionConverter(objClass, componentType);
286             } else if (JMX.isMXBeanInterface(objClass)) {
287                 return makeMXBeanConverter(objClass);
288             } else {
289                 return makeCompositeConverter(objClass);
290             }
291         } else if (objType instanceof ParameterizedType JavaDoc) {
292             return makeParameterizedConverter((ParameterizedType JavaDoc) objType);
293         } else
294             throw new OpenDataException JavaDoc("Cannot map type: " + objType);
295     }
296
297     private static <T extends Enum JavaDoc<T>> OpenConverter
298         makeEnumConverter(Class JavaDoc<T> enumClass) {
299     return new EnumConverter<T>(enumClass);
300     }
301
302     /* Make the converter for an array type, or a collection such as
303      * List<String> or Set<Integer>. We never see one-dimensional
304      * primitive arrays (e.g. int[]) here because they use the identity
305      * converter and are registered as such in the static initializer.
306      */

307     private static OpenConverter
308     makeArrayOrCollectionConverter(Type JavaDoc collectionType, Type JavaDoc elementType)
309         throws OpenDataException JavaDoc {
310
311         final OpenConverter elementConverter = toConverter(elementType);
312     final OpenType JavaDoc elementOpenType = elementConverter.getOpenType();
313     final ArrayType JavaDoc openType = new ArrayType JavaDoc(1, elementOpenType);
314     final Class JavaDoc elementOpenClass = elementConverter.getOpenClass();
315
316     final Class JavaDoc openArrayClass;
317         final String JavaDoc openArrayClassName;
318         if (elementOpenClass.isArray())
319             openArrayClassName = "[" + elementOpenClass.getName();
320         else
321             openArrayClassName = "[L" + elementOpenClass.getName() + ";";
322         try {
323             openArrayClass = Class.forName(openArrayClassName);
324         } catch (ClassNotFoundException JavaDoc e) {
325             throw openDataException("Cannot obtain array class", e);
326         }
327
328     if (collectionType instanceof ParameterizedType JavaDoc) {
329         return new CollectionConverter(collectionType,
330                        openType, openArrayClass,
331                        elementConverter);
332         } else {
333             if (elementConverter.isIdentity()) {
334         return new IdentityConverter(collectionType,
335                                              openType,
336                                              openArrayClass);
337         } else {
338         return new ArrayConverter(collectionType,
339                                           openType,
340                                           openArrayClass,
341                                           elementConverter);
342         }
343     }
344     }
345
346     private static final String JavaDoc[] keyArray = {"key"};
347     private static final String JavaDoc[] keyValueArray = {"key", "value"};
348
349     private static OpenConverter
350     makeTabularConverter(Type JavaDoc objType, boolean sortedMap,
351                              Type JavaDoc keyType, Type JavaDoc valueType)
352         throws OpenDataException JavaDoc {
353
354     final String JavaDoc objTypeName = objType.toString();
355     final OpenConverter keyConverter = toConverter(keyType);
356     final OpenConverter valueConverter = toConverter(valueType);
357     final OpenType JavaDoc keyOpenType = keyConverter.getOpenType();
358     final OpenType JavaDoc valueOpenType = valueConverter.getOpenType();
359     final CompositeType JavaDoc rowType =
360         new CompositeType JavaDoc(objTypeName,
361                   objTypeName,
362                   keyValueArray,
363                   keyValueArray,
364                   new OpenType JavaDoc[] {keyOpenType, valueOpenType});
365     final TabularType JavaDoc tabularType =
366         new TabularType JavaDoc(objTypeName, objTypeName, rowType, keyArray);
367     return new TabularConverter(objType, sortedMap, tabularType,
368                     keyConverter, valueConverter);
369     }
370
371     /* We know how to translate List<E>, Set<E>, SortedSet<E>,
372        Map<K,V>, SortedMap<K,V>, and that's it. We don't accept
373        subtypes of those because we wouldn't know how to deserialize
374        them. We don't accept Queue<E> because it is unlikely people
375        would use that as a parameter or return type in an MBean. */

376     private static OpenConverter
377     makeParameterizedConverter(ParameterizedType JavaDoc objType) throws OpenDataException JavaDoc {
378
379         final Type JavaDoc rawType = objType.getRawType();
380
381         if (rawType instanceof Class JavaDoc) {
382             Class JavaDoc c = (Class JavaDoc<?>) rawType;
383             if (c == List JavaDoc.class || c == Set JavaDoc.class || c == SortedSet JavaDoc.class) {
384                 Type JavaDoc[] actuals =
385                     ((ParameterizedType JavaDoc) objType).getActualTypeArguments();
386                 assert(actuals.length == 1);
387                 if (c == SortedSet JavaDoc.class)
388                     mustBeComparable(c, actuals[0]);
389                 return makeArrayOrCollectionConverter(objType, actuals[0]);
390             } else {
391                 boolean sortedMap = (c == SortedMap JavaDoc.class);
392                 if (c == Map JavaDoc.class || sortedMap) {
393                     Type JavaDoc[] actuals =
394                             ((ParameterizedType JavaDoc) objType).getActualTypeArguments();
395                     assert(actuals.length == 2);
396                     if (sortedMap)
397                         mustBeComparable(c, actuals[0]);
398                     return makeTabularConverter(objType, sortedMap,
399                             actuals[0], actuals[1]);
400                 }
401             }
402     }
403         throw new OpenDataException JavaDoc("Cannot convert type: " + objType);
404     }
405
406     private static OpenConverter makeMXBeanConverter(Type JavaDoc t)
407             throws OpenDataException JavaDoc {
408         return new MXBeanConverter(t);
409     }
410     
411     private static OpenConverter makeCompositeConverter(Class JavaDoc c)
412         throws OpenDataException JavaDoc {
413         
414         // For historical reasons GcInfo implements CompositeData but we
415
// shouldn't count its CompositeData.getCompositeType() field as
416
// an item in the computed CompositeType.
417
final boolean gcInfoHack =
418             (c.getName().equals("com.sun.management.GcInfo") &&
419                 c.getClassLoader() == null);
420
421     final List JavaDoc<Method JavaDoc> methods =
422                 MBeanAnalyzer.eliminateCovariantMethods(c.getMethods());
423     final SortedMap JavaDoc<String JavaDoc,Method JavaDoc> getterMap = newSortedMap();
424
425     /* Select public methods that look like "T getX()" or "boolean
426        isX()", where T is not void and X is not the empty
427        string. Exclude "Class getClass()" inherited from Object. */

428     for (Method JavaDoc method : methods) {
429         final String JavaDoc propertyName = propertyName(method);
430
431         if (propertyName == null)
432         continue;
433             if (gcInfoHack && propertyName.equals("CompositeType"))
434                 continue;
435
436             Method JavaDoc old =
437                 getterMap.put(decapitalize(propertyName),
438                             method);
439             if (old != null) {
440                 final String JavaDoc msg =
441                     "Class " + c.getName() + " has method name clash: " +
442                     old.getName() + ", " + method.getName();
443                 throw new OpenDataException JavaDoc(msg);
444             }
445     }
446
447         final int nitems = getterMap.size();
448
449     if (nitems == 0) {
450         throw new OpenDataException JavaDoc("Can't map " + c.getName() +
451                     " to an open data type");
452     }
453
454         final Method JavaDoc[] getters = new Method JavaDoc[nitems];
455         final String JavaDoc[] itemNames = new String JavaDoc[nitems];
456         final OpenType JavaDoc[] openTypes = new OpenType JavaDoc[nitems];
457         int i = 0;
458         for (Map.Entry JavaDoc<String JavaDoc,Method JavaDoc> entry : getterMap.entrySet()) {
459             itemNames[i] = entry.getKey();
460             final Method JavaDoc getter = entry.getValue();
461             getters[i] = getter;
462             final Type JavaDoc retType = getter.getGenericReturnType();
463             openTypes[i] = toConverter(retType).getOpenType();
464             i++;
465         }
466
467         CompositeType JavaDoc compositeType =
468         new CompositeType JavaDoc(c.getName(),
469                   c.getName(),
470                   itemNames, // field names
471
itemNames, // field descriptions
472
openTypes);
473
474     return new CompositeConverter(c,
475                       compositeType,
476                       itemNames,
477                       getters);
478     }
479
480     /* Converter for classes where the open data is identical to the
481        original data. This is true for any of the SimpleType types,
482        and for an any-dimension array of those. It is also true for
483        primitive types as of JMX 1.3, since an int[] needs to
484        can be directly represented by an ArrayType, and an int needs no mapping
485        because reflection takes care of it. */

486     private static final class IdentityConverter extends OpenConverter {
487     IdentityConverter(Type JavaDoc targetType, OpenType JavaDoc openType,
488                           Class JavaDoc openClass) {
489         super(targetType, openType, openClass);
490     }
491
492     boolean isIdentity() {
493         return true;
494     }
495
496     final Object JavaDoc toNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value) {
497         return value;
498     }
499
500     public final Object JavaDoc fromNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value) {
501         return value;
502     }
503     }
504
505     private static final class EnumConverter<T extends Enum JavaDoc<T>>
506         extends OpenConverter {
507
508     EnumConverter(Class JavaDoc<T> enumClass) {
509         super(enumClass, SimpleType.STRING, String JavaDoc.class);
510         this.enumClass = enumClass;
511     }
512
513     final Object JavaDoc toNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value) {
514         return ((Enum JavaDoc) value).name();
515     }
516
517         // return type could be T, but after erasure that would be
518
// java.lang.Enum, which doesn't exist on J2SE 1.4
519
public final Object JavaDoc fromNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value)
520                 throws InvalidObjectException JavaDoc {
521         try {
522         return Enum.valueOf(enumClass, (String JavaDoc) value);
523         } catch (Exception JavaDoc e) {
524         throw invalidObjectException("Cannot convert to enum: " +
525                                              value, e);
526         }
527     }
528
529     private final Class JavaDoc<T> enumClass;
530     }
531
532     private static final class ArrayConverter extends OpenConverter {
533     ArrayConverter(Type JavaDoc targetType,
534                ArrayType JavaDoc openArrayType, Class JavaDoc openArrayClass,
535                OpenConverter elementConverter) {
536         super(targetType, openArrayType, openArrayClass);
537         this.elementConverter = elementConverter;
538     }
539
540     final Object JavaDoc toNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc value)
541                 throws OpenDataException JavaDoc {
542         Object JavaDoc[] valueArray = (Object JavaDoc[]) value;
543         final int len = valueArray.length;
544             final Object JavaDoc[] openArray = (Object JavaDoc[])
545         Array.newInstance(getOpenClass().getComponentType(), len);
546         for (int i = 0; i < len; i++) {
547         openArray[i] =
548                     elementConverter.toOpenValue(lookup, valueArray[i]);
549             }
550         return openArray;
551     }
552
553     public final Object JavaDoc fromNonNullOpenValue(MXBeanLookup lookup, Object JavaDoc openValue)
554                 throws InvalidObjectException JavaDoc {
555         final Object JavaDoc[] openArray = (Object JavaDoc[]) openValue;
556         final Type JavaDoc targetType = getTargetType();
557         final Object JavaDoc[] valueArray;
558             final Type JavaDoc componentType;
559             if (targetType instanceof GenericArrayType JavaDoc) {
560                 componentType =
561                     ((GenericArrayType JavaDoc) targetType).getGenericComponentType();
562             } else if (targetType instanceof Class JavaDoc &&
563                        ((Class JavaDoc<?>) targetType).isArray()) {
564                 componentType = ((Class JavaDoc<?>) targetType).getComponentType();
565             } else {
566                 throw new IllegalArgumentException JavaDoc("Not an array: " +
567                                                    targetType);
568             }
569             valueArray = (Object JavaDoc[]) Array.newInstance((Class JavaDoc<?>) componentType,
570                                                       openArray.length);
571         for (int i = 0; i < openArray.length; i++) {
572         valueArray[i] =
573             elementConverter.fromOpenValue(lookup, openArray[i]);
574         }
575         return valueArray;
576     }
577
578         void checkReconstructible() throws InvalidObjectException JavaDoc {
579             elementConverter.checkReconstructible();
580         }
581
582     /** OpenConverter for the elements of this array. If this is an
583         array of arrays, the converter converts the second-level arrays,
584         not the deepest elements. */

585     private final OpenConverter elementConverter;
586     }
587
588     private static final class CollectionConverter extends OpenConverter {
589     CollectionConverter(Type JavaDoc targetType,
590                 ArrayType JavaDoc openArrayType,
591                 Class JavaDoc openArrayClass,
592                 OpenConverter elementConverter) {
593         super(targetType, openArrayType, openArrayClass);
594         this.elementConverter = elementConverter;
595
596         /* Determine the concrete class to be used when converting
597            back to this Java type. We convert all Lists to ArrayList
598            and all Sets to TreeSet. (TreeSet because it is a SortedSet,
599            so works for both Set and SortedSet.) */

600             Type JavaDoc raw = ((ParameterizedType JavaDoc) targetType).getRawType();
601             Class JavaDoc c = (Class JavaDoc<?>) raw;
602