OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [management/] [Translator.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* Translator.java -- Performs MXBean data type translation.
2
   Copyright (C) 2007 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.javax.management;
39
 
40
import java.lang.reflect.Array;
41
import java.lang.reflect.Method;
42
import java.lang.reflect.Modifier;
43
import java.lang.reflect.ParameterizedType;
44
import java.lang.reflect.Proxy;
45
import java.lang.reflect.Type;
46
 
47
import java.util.ArrayList;
48
import java.util.Collection;
49
import java.util.HashMap;
50
import java.util.Iterator;
51
import java.util.List;
52
import java.util.Map;
53
import java.util.Set;
54
import java.util.SortedMap;
55
import java.util.SortedSet;
56
 
57
import javax.management.JMX;
58
import javax.management.MBeanServerInvocationHandler;
59
 
60
import javax.management.openmbean.ArrayType;
61
import javax.management.openmbean.CompositeData;
62
import javax.management.openmbean.CompositeDataSupport;
63
import javax.management.openmbean.CompositeType;
64
import javax.management.openmbean.OpenDataException;
65
import javax.management.openmbean.OpenMBeanParameterInfo;
66
import javax.management.openmbean.OpenMBeanParameterInfoSupport;
67
import javax.management.openmbean.OpenType;
68
import javax.management.openmbean.SimpleType;
69
import javax.management.openmbean.TabularData;
70
import javax.management.openmbean.TabularDataSupport;
71
import javax.management.openmbean.TabularType;
72
 
73
/**
74
 * Translates Java data types to their equivalent
75
 * open data type, and vice versa, according to the
76
 * {@link javax.management.MXBean} rules.
77
 *
78
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
79
 */
80
public final class Translator
81
{
82
 
83
  /**
84
   * Translates the input Java data types to the equivalent
85
   * open data types.
86
   *
87
   * @param jtypes the Java types supplied as parameters.
88
   * @param method the method that was called.
89
   * @return the equivalent open types required by the {@link MXBean}.
90
   * @throws Throwable if an exception is thrown in performing the
91
   *                   conversion.
92
   */
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
  /**
104
   * Translates the input Java data type to the equivalent
105
   * open data type.
106
   *
107
   * @param jtype the Java type supplied as a parameter.
108
   * @param type the type of the parameter.
109
   * @return the equivalent open type required by the {@link MXBean}.
110
   * @throws Throwable if an exception is thrown in performing the
111
   *                   conversion.
112
   */
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
    /* FIXME: Handle other types */
240
    throw new IllegalArgumentException("The type, " + jtype +
241
                                       ", is not convertible.");
242
  }
243
 
244
  /**
245
   * Translates the returned open data type to the value
246
   * required by the interface.
247
   *
248
   * @param otype the open type returned by the method call.
249
   * @param method the method that was called.
250
   * @return the equivalent return type required by the interface.
251
   * @throws Throwable if an exception is thrown in performing the
252
   *                   conversion.
253
   */
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
        /* Ignored; we expect this if this
295
           isn't a from(CompositeData) class */
296
      }
297
    return otype;
298
  }
299
 
300
  /**
301
   * Creates a new array which has the specific type
302
   * used by the elements of the original {@link Object}
303
   * array supplied.
304
   *
305
   * @param arr a series of elements in an {@link Object}
306
   *            array.
307
   * @return the same elements in a new array of the specific
308
   *         type.
309
   */
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
  /**
319
   * Translates the name of a type into an equivalent
320
   * {@link javax.management.openmbean.OpenMBeanParameterInfo}
321
   * that describes it.
322
   *
323
   * @param type the type to describe.
324
   * @return an instance of
325
   * {@link javax.management.openmbean.OpenMBeanParameterInfo},
326
   * describing the translated type and limits of the given type.
327
   * @throws OpenDataException if a type is not open.
328
   */
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
  /**
491
   * Obtains the {@link javax.management.openmbean.OpenType}
492
   * for a particular class.
493
   *
494
   * @param c the class to obtain the type for.
495
   * @return the appropriate instance.
496
   * @throws OpenDataException if the type is not open.
497
   */
498
  private static final OpenType<?> getTypeFromClass(Class<?> c)
499
    throws OpenDataException
500
  {
501
    return Translator.translate(c.getName()).getOpenType();
502
  }
503
 
504
  /**
505
   * <p>
506
   * Returns the type name according to the rules described
507
   * in {@link javax.management.MXBean}.  Namely, for a type,
508
   * {@code T}, {@code typename(T)} is computed as follows:
509
   * </p>
510
   * <ul>
511
   * <li>If T is non-generic and not an array, then the value
512
   * of {@link java.lang.Class#getName()} is returned.</li>
513
   * <li>If T is an array type, {@code{E[]}, then the type name
514
   * is {@code typename(E)} followed by an occurrence
515
   * of {@code '[]'} for each dimension.</li>
516
   * <li>If T is a generic or parameterized type, the type name
517
   * is composed of {@code typename(P)}, where {@code P} is the
518
   * parameterized type name, followed by {@code '<'}, the resulting
519
   * list of type names of the parameters after applying {@code typename}
520
   * to each, separated by commas, and {@code '>'}.</li>
521
   * </ul>
522
   *
523
   * @param type the type to return the type name of.
524
   * @return the type name computed according to the rules above.
525
   */
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.