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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [sun/] [reflect/] [annotation/] [AnnotationInvocationHandler.java] - Blame information for rev 763

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 763 jeremybenn
/* sun.reflect.annotation.AnnotationInvocationHandler
2
   Copyright (C) 2006, 2007
3
   Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
package sun.reflect.annotation;
40
 
41
import java.io.Serializable;
42
import java.lang.annotation.Annotation;
43
import java.lang.annotation.AnnotationTypeMismatchException;
44
import java.lang.annotation.IncompleteAnnotationException;
45
import java.lang.reflect.InvocationHandler;
46
import java.lang.reflect.Method;
47
import java.lang.reflect.Proxy;
48
import java.lang.reflect.Array;
49
import java.util.Arrays;
50
import java.util.Iterator;
51
import java.util.Map;
52
 
53
/**
54
 * This class exists for serialization compatibility with the JDK.
55
 * VMs can choose to implement annotations by constructing proxies
56
 * with this invocation handler, but that is not required.
57
 * If a different strategy for proxy objects is chosen, they can
58
 * have a writeReplace method to substitute a Proxy based on this
59
 * invocation handler is used for serialization.
60
 */
61
public final class AnnotationInvocationHandler
62
  implements InvocationHandler, Serializable
63
{
64
  private static final long serialVersionUID = 6182022883658399397L;
65
  private final Class<? extends Annotation> type;
66
  private final Map<String, ?> memberValues;
67
 
68
  /**
69
   * Construct a new invocation handler for an annotation proxy.
70
   * Note that the VM is responsible for filling the memberValues map
71
   * with the default values of all the annotation members.
72
   */
73
  public AnnotationInvocationHandler(Class<? extends Annotation> type, Map memberValues)
74
  {
75
    this.type = type;
76
    this.memberValues = (Map<String, ?>)memberValues;
77
  }
78
 
79
  public static Annotation create(Class<? extends Annotation> type, Map memberValues)
80
  {
81
    for (Method m : type.getDeclaredMethods())
82
      {
83
        String name = m.getName();
84
        if (! memberValues.containsKey(name))
85
          {
86
            // FIXME: what to do about exceptions here?
87
            memberValues.put(name, m.getDefaultValue());
88
          }
89
      }
90
    AnnotationInvocationHandler handler
91
      = new AnnotationInvocationHandler(type, memberValues);
92
    return (Annotation) Proxy.newProxyInstance(type.getClassLoader(),
93
                                               new Class[] { type },
94
                                               handler);
95
  }
96
 
97
  /**
98
   * Compare an instance of AnnotationInvocationHandler with another object.
99
   * Note that the other object does not have to be an
100
   * AnnotationInvocationHandler, any implementation of the annotation
101
   * interface is allowed to be compared for equality.
102
   * Note that this makes the equals method asymmetric, but this behavior
103
   * is specified by Annotation.equals and identical to the JDK.
104
   *
105
   * This method is public for use by other parts of the VM. Some VMs
106
   * (can) use different representations of annotations that reuse this
107
   * method.
108
   */
109
  public boolean equals(Object proxy, Object other)
110
  {
111
    if (type.isInstance(other))
112
      {
113
        try
114
          {
115
            Method[] methods = type.getDeclaredMethods();
116
            if (methods.length == memberValues.size())
117
              {
118
                for (int i = 0; i < methods.length; i++)
119
                  {
120
                    String key = methods[i].getName();
121
                    Object val = methods[i].invoke(other, (Object[])null);
122
                    Object thisVal
123
                      = invoke(proxy,
124
                               methods[i],
125
                               (Object[])null);
126
                    if (! deepEquals(thisVal, val))
127
                      {
128
                        return false;
129
                      }
130
                  }
131
                return true;
132
              }
133
          }
134
        catch (Throwable _)
135
          {
136
            // Ignore exception, like the JDK
137
          }
138
      }
139
    return false;
140
  }
141
 
142
  private static boolean deepEquals(Object o1, Object o2)
143
  {
144
    if (o1 == o2)
145
      return true;
146
 
147
    if (o1 == null || o2 == null)
148
      return false;
149
 
150
    if (o1 instanceof boolean[] && o2 instanceof boolean[])
151
      return Arrays.equals((boolean[]) o1, (boolean[]) o2);
152
 
153
    if (o1 instanceof byte[] && o2 instanceof byte[])
154
      return Arrays.equals((byte[]) o1, (byte[]) o2);
155
 
156
    if (o1 instanceof char[] && o2 instanceof char[])
157
      return Arrays.equals((char[]) o1, (char[]) o2);
158
 
159
    if (o1 instanceof short[] && o2 instanceof short[])
160
      return Arrays.equals((short[]) o1, (short[]) o2);
161
 
162
    if (o1 instanceof int[] && o2 instanceof int[])
163
      return Arrays.equals((int[]) o1, (int[]) o2);
164
 
165
    if (o1 instanceof float[] && o2 instanceof float[])
166
      return Arrays.equals((float[]) o1, (float[]) o2);
167
 
168
    if (o1 instanceof long[] && o2 instanceof long[])
169
      return Arrays.equals((long[]) o1, (long[]) o2);
170
 
171
    if (o1 instanceof double[] && o2 instanceof double[])
172
      return Arrays.equals((double[]) o1, (double[]) o2);
173
 
174
    if (o1 instanceof Object[] && o2 instanceof Object[])
175
      return Arrays.equals((Object[]) o1, (Object[]) o2);
176
 
177
    return o1.equals(o2);
178
  }
179
 
180
  private static int deepHashCode(Object obj)
181
  {
182
    if (obj instanceof boolean[])
183
      return Arrays.hashCode((boolean[]) obj);
184
 
185
    if (obj instanceof byte[])
186
      return Arrays.hashCode((byte[]) obj);
187
 
188
    if (obj instanceof char[])
189
      return Arrays.hashCode((char[]) obj);
190
 
191
    if (obj instanceof short[])
192
      return Arrays.hashCode((short[]) obj);
193
 
194
    if (obj instanceof int[])
195
      return Arrays.hashCode((int[]) obj);
196
 
197
    if (obj instanceof float[])
198
      return Arrays.hashCode((float[]) obj);
199
 
200
    if (obj instanceof long[])
201
      return Arrays.hashCode((long[]) obj);
202
 
203
    if (obj instanceof double[])
204
      return Arrays.hashCode((double[]) obj);
205
 
206
    if (obj instanceof Object[])
207
      return Arrays.hashCode((Object[]) obj);
208
 
209
    return obj.hashCode();
210
  }
211
 
212
  /**
213
   * Compute the hashCode for an annotation. Note that the algorithm is
214
   * specified by Annotation.hashCode.
215
   *
216
   * This method is public for use by other parts of the VM. Some VMs
217
   * (can) use different representations of annotations that reuse this
218
   * method.
219
   */
220
  public int hashCode()
221
  {
222
    int h = 0;
223
    Iterator iter = memberValues.keySet().iterator();
224
    while (iter.hasNext())
225
      {
226
        Object key = iter.next();
227
        try
228
          {
229
            Object val
230
              = invoke(null,
231
                       type.getDeclaredMethod((String)key, (Class[])null),
232
                       (Object[])null);
233
            h += deepHashCode(val) ^ 127 * key.hashCode();
234
          }
235
        catch (Throwable _)
236
          {
237
          }
238
      }
239
    return h;
240
  }
241
 
242
  private static String deepToString(Object obj)
243
  {
244
    if (obj instanceof Object[])
245
      return Arrays.toString((Object[]) obj);
246
 
247
    return obj.toString();
248
  }
249
 
250
  /**
251
   * This method is public for use by other parts of the VM. Some VMs
252
   * (can) use different representations of annotations that reuse this
253
   * method.
254
   */
255
  public String toString()
256
  {
257
    StringBuffer sb = new StringBuffer();
258
    sb.append('@').append(type.getName()).append('(');
259
    String sep = "";
260
    Iterator iter = memberValues.keySet().iterator();
261
    while (iter.hasNext())
262
      {
263
        Object key = iter.next();
264
        Object val = memberValues.get(key);
265
        sb.append(sep).append(key).append('=').append(deepToString(val));
266
        sep = ", ";
267
      }
268
    sb.append(')');
269
    return sb.toString();
270
  }
271
 
272
 
273
  private static Class getBoxedReturnType(Method method)
274
  {
275
    Class returnType = method.getReturnType();
276
 
277
    if (returnType == boolean.class)
278
      return Boolean.class;
279
 
280
    if (returnType == byte.class)
281
      return Byte.class;
282
 
283
    if (returnType == char.class)
284
      return Character.class;
285
 
286
    if (returnType == short.class)
287
      return Short.class;
288
 
289
    if (returnType == int.class)
290
      return Integer.class;
291
 
292
    if (returnType == float.class)
293
      return Float.class;
294
 
295
    if (returnType == long.class)
296
      return Long.class;
297
 
298
    if (returnType == double.class)
299
      return Double.class;
300
 
301
    return returnType;
302
  }
303
 
304
  // This is slightly awkward.  When the value of an annotation is an
305
  // array, libgcj constructs an Object[], but the value() method
306
  // returns an arrays of the appropriate primitive type.  We should
307
  // perhaps save the resulting array rather than the Object[].
308
 
309
  private Object coerce(Object val, Class dstType)
310
    throws ArrayStoreException
311
  {
312
    if (! val.getClass().isArray())
313
      return val;
314
 
315
    Object[] srcArray = (Object[])val;
316
    final int len = srcArray.length;
317
 
318
    if (dstType.getComponentType().isPrimitive())
319
      {
320
        if (dstType == boolean[].class)
321
          {
322
            boolean[] dst = new boolean[len];
323
            for (int i = 0; i < len; i++)
324
              dst[i] = (Boolean)srcArray[i];
325
            return dst;
326
          }
327
 
328
        if (dstType == byte[].class)
329
          {
330
            byte[] dst = new byte[len];
331
            for (int i = 0; i < len; i++)
332
              dst[i] = (Byte)srcArray[i];
333
            return dst;
334
          }
335
 
336
        if (dstType == char[].class)
337
          {
338
            char[] dst = new char[len];
339
            for (int i = 0; i < len; i++)
340
              dst[i] = (Character)srcArray[i];
341
            return dst;
342
          }
343
 
344
        if (dstType == short[].class)
345
          {
346
            short[] dst = new short[len];
347
            for (int i = 0; i < len; i++)
348
              dst[i] = (Short)srcArray[i];
349
            return dst;
350
          }
351
 
352
        if (dstType == int[].class)
353
          {
354
            int[] dst = new int[len];
355
            for (int i = 0; i < len; i++)
356
              dst[i] = (Integer)srcArray[i];
357
            return dst;
358
          }
359
 
360
        if (dstType == long[].class)
361
          {
362
            long[] dst = new long[len];
363
            for (int i = 0; i < len; i++)
364
              dst[i] = (Long)srcArray[i];
365
            return dst;
366
          }
367
 
368
        if (dstType == float[].class)
369
          {
370
            float[] dst = new float[len];
371
            for (int i = 0; i < len; i++)
372
              dst[i] = (Float)srcArray[i];
373
            return dst;
374
          }
375
 
376
        if (dstType == double[].class)
377
          {
378
            double[] dst = new double[len];
379
            for (int i = 0; i < len; i++)
380
              dst[i] = (Double)srcArray[i];
381
            return dst;
382
          }
383
      }
384
 
385
    Object dst = Array.newInstance(dstType.getComponentType(), len);
386
    System.arraycopy((Object)srcArray, 0, dst, 0, len);
387
    return dst;
388
  }
389
 
390
  public Object invoke(Object proxy, Method method, Object[] args)
391
    throws Throwable
392
  {
393
    String methodName = method.getName().intern();
394
 
395
    if (args == null || args.length == 0)
396
      {
397
        if (methodName == "toString")
398
          {
399
            return toString();
400
          }
401
        else if (methodName == "hashCode")
402
          {
403
            return Integer.valueOf(hashCode());
404
          }
405
        else if (methodName == "annotationType")
406
          {
407
            return type;
408
          }
409
        else
410
          {
411
            Object val = memberValues.get(methodName);
412
            if (val == null)
413
              {
414
                throw new IncompleteAnnotationException(type, methodName);
415
              }
416
            try
417
              {
418
                if (val.getClass().isArray())
419
                  val = coerce((Object[])val, method.getReturnType());
420
              }
421
            catch (ArrayStoreException _)
422
              {
423
                throw new AnnotationTypeMismatchException
424
                  (method, val.getClass().getName());
425
              }
426
            if (! getBoxedReturnType(method).isInstance(val))
427
              throw (new AnnotationTypeMismatchException
428
                     (method, val.getClass().getName()));
429
            return val;
430
          }
431
      }
432
    else if (args.length == 1)
433
      {
434
        if (methodName == "equals")
435
          {
436
            return Boolean.valueOf(equals(proxy, args[0]));
437
          }
438
      }
439
    throw new InternalError("Invalid annotation proxy");
440
  }
441
}

powered by: WebSVN 2.1.0

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