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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 778 jeremybenn
/* sun.reflect.annotation.AnnotationInvocationHandler
2
   Copyright (C) 2006
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.InvocationTargetException;
47
import java.lang.reflect.Method;
48
import java.lang.reflect.Proxy;
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 type;
66
    private final Map 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 type, Map memberValues)
74
    {
75
        this.type = type;
76
        this.memberValues = memberValues;
77
    }
78
 
79
    public static Annotation create(Class 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 static boolean equals(Class type, Map memberValues, 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, new Object[0]);
122
                        if (! deepEquals(memberValues.get(key), val))
123
                        {
124
                            return false;
125
                        }
126
                    }
127
                    return true;
128
                }
129
            }
130
            catch (IllegalAccessException _)
131
            {
132
                // Ignore exception, like the JDK
133
            }
134
            catch (InvocationTargetException _)
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 static int hashCode(Class type, Map memberValues)
221
    {
222
        int h = 0;
223
        Iterator iter = memberValues.keySet().iterator();
224
        while (iter.hasNext())
225
        {
226
            Object key = iter.next();
227
            Object val = memberValues.get(key);
228
            h += deepHashCode(val) ^ 127 * key.hashCode();
229
        }
230
        return h;
231
    }
232
 
233
    private static String deepToString(Object obj)
234
    {
235
        if (obj instanceof boolean[])
236
            return Arrays.toString((boolean[]) obj);
237
 
238
        if (obj instanceof byte[])
239
            return Arrays.toString((byte[]) obj);
240
 
241
        if (obj instanceof char[])
242
            return Arrays.toString((char[]) obj);
243
 
244
        if (obj instanceof short[])
245
            return Arrays.toString((short[]) obj);
246
 
247
        if (obj instanceof int[])
248
            return Arrays.toString((int[]) obj);
249
 
250
        if (obj instanceof float[])
251
            return Arrays.toString((float[]) obj);
252
 
253
        if (obj instanceof long[])
254
            return Arrays.toString((long[]) obj);
255
 
256
        if (obj instanceof double[])
257
            return Arrays.toString((double[]) obj);
258
 
259
        if (obj instanceof Object[])
260
            return Arrays.toString((Object[]) obj);
261
 
262
        return obj.toString();
263
    }
264
 
265
    /**
266
     * This method is public for use by other parts of the VM. Some VMs
267
     * (can) use different representations of annotations that reuse this
268
     * method.
269
     */
270
    public static String toString(Class type, Map memberValues)
271
    {
272
        StringBuffer sb = new StringBuffer();
273
        sb.append('@').append(type.getName()).append('(');
274
        String sep = "";
275
        Iterator iter = memberValues.keySet().iterator();
276
        while (iter.hasNext())
277
        {
278
            Object key = iter.next();
279
            Object val = memberValues.get(key);
280
            sb.append(sep).append(key).append('=').append(deepToString(val));
281
            sep = ", ";
282
        }
283
        sb.append(')');
284
        return sb.toString();
285
    }
286
 
287
    private static Class getBoxedReturnType(Method method)
288
    {
289
        Class returnType = method.getReturnType();
290
 
291
        if (returnType == boolean.class)
292
            return Boolean.class;
293
 
294
        if (returnType == byte.class)
295
            return Byte.class;
296
 
297
        if (returnType == char.class)
298
            return Character.class;
299
 
300
        if (returnType == short.class)
301
            return Short.class;
302
 
303
        if (returnType == int.class)
304
            return Integer.class;
305
 
306
        if (returnType == float.class)
307
            return Float.class;
308
 
309
        if (returnType == long.class)
310
            return Long.class;
311
 
312
        if (returnType == double.class)
313
            return Double.class;
314
 
315
        return returnType;
316
    }
317
 
318
    private Object arrayClone(Object obj)
319
    {
320
        if (obj instanceof boolean[])
321
            return ((boolean[]) obj).clone();
322
 
323
        if (obj instanceof byte[])
324
            return ((byte[]) obj).clone();
325
 
326
        if (obj instanceof char[])
327
            return ((char[]) obj).clone();
328
 
329
        if (obj instanceof short[])
330
            return ((short[]) obj).clone();
331
 
332
        if (obj instanceof int[])
333
            return ((int[]) obj).clone();
334
 
335
        if (obj instanceof float[])
336
            return ((float[]) obj).clone();
337
 
338
        if (obj instanceof long[])
339
            return ((long[]) obj).clone();
340
 
341
        if (obj instanceof double[])
342
            return ((double[]) obj).clone();
343
 
344
        if (obj instanceof Object[])
345
            return ((Object[]) obj).clone();
346
 
347
        return obj;
348
    }
349
 
350
    public Object invoke(Object proxy, Method method, Object[] args)
351
      throws Throwable
352
    {
353
        String methodName = method.getName().intern();
354
        if (args == null || args.length == 0)
355
        {
356
            if (methodName == "toString")
357
            {
358
                return toString(type, memberValues);
359
            }
360
            else if (methodName == "hashCode")
361
            {
362
                return Integer.valueOf(hashCode(type, memberValues));
363
            }
364
            else if (methodName == "annotationType")
365
            {
366
                return type;
367
            }
368
            else
369
            {
370
                Object val = memberValues.get(methodName);
371
                if (val == null)
372
                {
373
                    throw new IncompleteAnnotationException(type, methodName);
374
                }
375
                if (! getBoxedReturnType(method).isInstance(val))
376
                {
377
                    throw new AnnotationTypeMismatchException(method,
378
                        val.getClass().getName());
379
                }
380
                if (val.getClass().isArray())
381
                {
382
                    val = arrayClone(val);
383
                }
384
                return val;
385
            }
386
        }
387
        else if (args.length == 1)
388
        {
389
            if (methodName == "equals")
390
            {
391
                return Boolean.valueOf(equals(type, memberValues, args[0]));
392
            }
393
        }
394
        throw new InternalError("Invalid annotation proxy");
395
    }
396
}

powered by: WebSVN 2.1.0

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