1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46:
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57: import ;
58: import ;
59:
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72:
73:
80: public final class Translator
81: {
82:
83:
93: public static final Object[] fromJava(Object[] jtypes, Method method)
94: throws Throwable
95: {
96: Type[] gtypes = method.getGenericParameterTypes();
97: Object[] otypes = new Object[jtypes.length];
98: for (int a = 0; a < jtypes.length; ++a)
99: otypes[a] = fromJava(jtypes[a], gtypes[a]);
100: return otypes;
101: }
102:
103:
113: public static final Object fromJava(Object jtype, Type type)
114: throws Throwable
115: {
116: if (jtype == null)
117: return null;
118: Class<?> jclass = jtype.getClass();
119: if (OpenType.ALLOWED_CLASSNAMES_LIST.contains(jclass.getName()))
120: return jtype;
121: if (jclass.isArray())
122: {
123: Class<?> ctype = jclass.getComponentType();
124: if (ctype.isPrimitive())
125: return jtype;
126: if (OpenType.ALLOWED_CLASSNAMES_LIST.contains(ctype.getName()))
127: return jtype;
128: Object[] elems = (Object[]) jtype;
129: Object[] celems = new Object[elems.length];
130: for (int a = 0; a < elems.length; ++a)
131: celems[a] = fromJava(elems[a], elems[a].getClass());
132: return makeArraySpecific(celems);
133: }
134: String tName = getTypeName(type);
135: if (jtype instanceof List || jtype instanceof Set ||
136: jtype instanceof SortedSet)
137: {
138: if (jtype instanceof SortedSet)
139: {
140: ParameterizedType ptype = (ParameterizedType) type;
141: Class<?> elemClass = (Class<?>) ptype.getActualTypeArguments()[0];
142: if (!Comparable.class.isAssignableFrom(elemClass))
143: throw new IllegalArgumentException(jtype + " has a " +
144: "non-comparable element " +
145: "type, " + elemClass);
146: if (((SortedSet<?>) jtype).comparator() != null)
147: throw new IllegalArgumentException(jtype + " does not " +
148: "use natural ordering.");
149: }
150: Collection<?> elems = (Collection<?>) jtype;
151: int numElems = elems.size();
152: Object[] celems = new Object[numElems];
153: Iterator<?> i = elems.iterator();
154: for (int a = 0; a < numElems; ++a)
155: {
156: Object elem = i.next();
157: celems[a] = fromJava(elem, elem.getClass());
158: }
159: return makeArraySpecific(celems);
160: }
161: if (jtype instanceof Enum)
162: return ((Enum<?>) jtype).name();
163: if (jtype instanceof Map || jtype instanceof SortedMap)
164: {
165: int lparam = tName.indexOf("<");
166: int comma = tName.indexOf(",", lparam);
167: int rparam = tName.indexOf(">", comma);
168: String key = tName.substring(lparam + 1, comma).trim();
169: String value = tName.substring(comma + 1, rparam).trim();
170: String typeName = null;
171: if (jtype instanceof Map)
172: typeName = "java.util.Map" + tName.substring(lparam);
173: else
174: {
175: Class<?> keyClass = Class.forName(key);
176: if (!Comparable.class.isAssignableFrom(keyClass))
177: throw new IllegalArgumentException(jtype + " has a " +
178: "non-comparable element " +
179: "type, " + keyClass);
180: if (((SortedMap<?,?>) jtype).comparator() != null)
181: throw new IllegalArgumentException(jtype + " does not " +
182: "use natural ordering.");
183: typeName = "java.util.SortedMap" + tName.substring(lparam);
184: }
185: OpenType<?> k = translate(key).getOpenType();
186: OpenType<?> v = translate(value).getOpenType();
187: CompositeType rowType = new CompositeType(typeName, typeName,
188: new String[] { "key", "value" },
189: new String[] { "Map key", "Map value"},
190: new OpenType[] {k,v});
191: TabularType tabType = new TabularType(typeName, typeName, rowType,
192: new String[]{"key"});
193: TabularData data = new TabularDataSupport(tabType);
194: for (Map.Entry<?,?> entry : ((Map<?,?>) jtype).entrySet())
195: {
196: try
197: {
198: data.put(new CompositeDataSupport(rowType,
199: new String[] {
200: "key",
201: "value"
202: },
203: new Object[] {
204: entry.getKey(),
205: entry.getValue()
206: }));
207: }
208: catch (OpenDataException e)
209: {
210: throw (InternalError) (new InternalError("A problem occurred " +
211: "converting the map " +
212: "to a composite data " +
213: "structure.").initCause(e));
214: }
215: }
216: return data;
217: }
218: if (JMX.isMXBeanInterface(jclass))
219: {
220: try
221: {
222: MBeanServerInvocationHandler ih = (MBeanServerInvocationHandler)
223: Proxy.getInvocationHandler(jtype);
224: return ih.getObjectName();
225: }
226: catch (IllegalArgumentException e)
227: {
228: throw new IllegalArgumentException("For a MXBean to be translated " +
229: "to an open type, it must be a " +
230: "proxy.", e);
231: }
232: catch (ClassCastException e)
233: {
234: throw new IllegalArgumentException("For a MXBean to be translated " +
235: "to an open type, it must have a " +
236: "MBeanServerInvocationHandler.", e);
237: }
238: }
239:
240: throw new IllegalArgumentException("The type, " + jtype +
241: ", is not convertible.");
242: }
243:
244:
254: public static final Object toJava(Object otype, Method method)
255: throws Throwable
256: {
257: Class<?> returnType = method.getReturnType();
258: if (returnType.isEnum())
259: {
260: String ename = (String) otype;
261: Enum<?>[] constants = (Enum[]) returnType.getEnumConstants();
262: for (Enum<?> c : constants)
263: if (c.name().equals(ename))
264: return c;
265: }
266: if (List.class.isAssignableFrom(returnType))
267: {
268: Object[] elems = (Object[]) otype;
269: List<Object> l = new ArrayList<Object>(elems.length);
270: for (Object elem : elems)
271: l.add(elem);
272: return l;
273: }
274: if (Map.class.isAssignableFrom(returnType))
275: {
276: TabularData data = (TabularData) otype;
277: Map<Object,Object> m = new HashMap<Object,Object>(data.size());
278: for (Object val : data.values())
279: {
280: CompositeData vals = (CompositeData) val;
281: m.put(vals.get("key"), vals.get("value"));
282: }
283: return m;
284: }
285: try
286: {
287: Method m = returnType.getMethod("from",
288: new Class[]
289: { CompositeData.class });
290: return m.invoke(null, (CompositeData) otype);
291: }
292: catch (NoSuchMethodException e)
293: {
294:
296: }
297: return otype;
298: }
299:
300:
310: private static final Object[] makeArraySpecific(Object[] arr)
311: {
312: Object[] rcelems = (Object[]) Array.newInstance(arr[0].getClass(),
313: arr.length);
314: System.arraycopy(arr, 0, rcelems, 0, arr.length);
315: return rcelems;
316: }
317:
318:
329: public static final OpenMBeanParameterInfo translate(String type)
330: throws OpenDataException
331: {
332: if (type.equals("boolean") || type.equals(Boolean.class.getName()))
333: return new OpenMBeanParameterInfoSupport("TransParam",
334: "Translated parameter",
335: SimpleType.BOOLEAN,
336: null,
337: new Boolean[] {
338: Boolean.TRUE,
339: Boolean.FALSE
340: });
341: if (type.equals("byte") || type.equals(Byte.class.getName()))
342: return new OpenMBeanParameterInfoSupport("TransParam",
343: "Translated parameter",
344: SimpleType.BYTE,
345: null,
346: Byte.valueOf(Byte.MIN_VALUE),
347: Byte.valueOf(Byte.MAX_VALUE));
348: if (type.equals("char") || type.equals(Character.class.getName()))
349: return new OpenMBeanParameterInfoSupport("TransParam",
350: "Translated parameter",
351: SimpleType.CHARACTER,
352: null,
353: Character.valueOf(Character.MIN_VALUE),
354: Character.valueOf(Character.MAX_VALUE));
355: if (type.equals("double") || type.equals(Double.class.getName()))
356: return new OpenMBeanParameterInfoSupport("TransParam",
357: "Translated parameter",
358: SimpleType.DOUBLE,
359: null,
360: Double.valueOf(Double.MIN_VALUE),
361: Double.valueOf(Double.MAX_VALUE));
362: if (type.equals("float") || type.equals(Float.class.getName()))
363: return new OpenMBeanParameterInfoSupport("TransParam",
364: "Translated parameter",
365: SimpleType.FLOAT,
366: null,
367: Float.valueOf(Float.MIN_VALUE),
368: Float.valueOf(Float.MAX_VALUE));
369: if (type.equals("int") || type.equals(Integer.class.getName()))
370: return new OpenMBeanParameterInfoSupport("TransParam",
371: "Translated parameter",
372: SimpleType.INTEGER,
373: null,
374: Integer.valueOf(Integer.MIN_VALUE),
375: Integer.valueOf(Integer.MAX_VALUE));
376: if (type.equals("long") || type.equals(Long.class.getName()))
377: return new OpenMBeanParameterInfoSupport("TransParam",
378: "Translated parameter",
379: SimpleType.LONG,
380: null,
381: Long.valueOf(Long.MIN_VALUE),
382: Long.valueOf(Long.MAX_VALUE));
383: if (type.equals("short") || type.equals(Short.class.getName()))
384: return new OpenMBeanParameterInfoSupport("TransParam",
385: "Translated parameter",
386: SimpleType.SHORT,
387: null,
388: Short.valueOf(Short.MIN_VALUE),
389: Short.valueOf(Short.MAX_VALUE));
390: if (type.equals(String.class.getName()))
391: return new OpenMBeanParameterInfoSupport("TransParam",
392: "Translated parameter",
393: SimpleType.STRING);
394: if (type.equals("void"))
395: return new OpenMBeanParameterInfoSupport("TransParam",
396: "Translated parameter",
397: SimpleType.VOID);
398: if (type.startsWith("java.util.Map"))
399: {
400: int lparam = type.indexOf("<");
401: int comma = type.indexOf(",", lparam);
402: int rparam = type.indexOf(">", comma);
403: String key = type.substring(lparam + 1, comma).trim();
404: OpenType<?> k = translate(key).getOpenType();
405: OpenType<?> v = translate(type.substring(comma + 1, rparam).trim()).getOpenType();
406: CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(),
407: new String[] { "key", "value" },
408: new String[] { "Map key", "Map value"},
409: new OpenType[] { k, v});
410: TabularType ttype = new TabularType(key, key, ctype,
411: new String[] { "key" });
412: return new OpenMBeanParameterInfoSupport("TransParam",
413: "Translated parameter",
414: ttype);
415: }
416: if (type.startsWith("java.util.List"))
417: {
418: int lparam = type.indexOf("<");
419: int rparam = type.indexOf(">");
420: OpenType<?> e = translate(type.substring(lparam + 1, rparam).trim()).getOpenType();
421: return new OpenMBeanParameterInfoSupport("TransParam",
422: "Translated parameter",
423: new ArrayType<OpenType<?>>(1, e)
424: );
425: }
426: Class<?> c;
427: try
428: {
429: c = Class.forName(type);
430: }
431: catch (ClassNotFoundException e)
432: {
433: throw (InternalError)
434: (new InternalError("The class for a type used in a management bean " +
435: "could not be loaded.").initCause(e));
436: }
437: if (c.isEnum())
438: {
439: Object[] values = c.getEnumConstants();
440: String[] names = new String[values.length];
441: for (int a = 0; a < values.length; ++a)
442: names[a] = values[a].toString();
443: return new OpenMBeanParameterInfoSupport("TransParam",
444: "Translated parameter",
445: SimpleType.STRING,
446: null, names);
447: }
448: if (c.isArray())
449: {
450: int depth;
451: for (depth = 0; c.getName().charAt(depth) == '['; ++depth)
452: ;
453: OpenType<?> ot = getTypeFromClass(c.getComponentType());
454: return new OpenMBeanParameterInfoSupport("TransParam",
455: "Translated parameter",
456: new ArrayType<OpenType<?>>(depth, ot)
457: );
458: }
459: Method[] methods = c.getDeclaredMethods();
460: List<String> names = new ArrayList<String>();
461: List<OpenType<?>> types = new ArrayList<OpenType<?>>();
462: for (int a = 0; a < methods.length; ++a)
463: {
464: String name = methods[a].getName();
465: if (Modifier.isPublic(methods[a].getModifiers()))
466: {
467: if (name.startsWith("get"))
468: {
469: names.add(name.substring(3));
470: types.add(getTypeFromClass(methods[a].getReturnType()));
471: }
472: else if (name.startsWith("is"))
473: {
474: names.add(name.substring(2));
475: types.add(getTypeFromClass(methods[a].getReturnType()));
476: }
477: }
478: }
479: if (names.isEmpty())
480: throw new OpenDataException("The type used does not have an open type translation.");
481: String[] fields = names.toArray(new String[names.size()]);
482: CompositeType ctype = new CompositeType(c.getName(), c.getName(),
483: fields, fields,
484: types.toArray(new OpenType[types.size()]));
485: return new OpenMBeanParameterInfoSupport("TransParam",
486: "Translated parameter",
487: ctype);
488: }
489:
490:
498: private static final OpenType<?> getTypeFromClass(Class<?> c)
499: throws OpenDataException
500: {
501: return Translator.translate(c.getName()).getOpenType();
502: }
503:
504:
526: private static final String getTypeName(Type type)
527: {
528: if (type instanceof Class)
529: {
530: Class<?> c = (Class<?>) type;
531: if (c.isArray())
532: {
533: StringBuilder b =
534: new StringBuilder(c.getComponentType().getName());
535: String normName = c.getName();
536: for (int a = 0; a < normName.length(); ++a)
537: {
538: if (normName.charAt(a) == '[')
539: b.append("[]");
540: else
541: break;
542: }
543: return b.toString();
544: }
545: return c.getName();
546: }
547: return type.toString();
548: }
549:
550: }