Thu, 12 Oct 2017 19:44:07 +0800
merge
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.bind.v2.model.annotation;
28 import java.lang.annotation.Annotation;
29 import java.lang.reflect.InvocationHandler;
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.Proxy;
33 import java.lang.reflect.Modifier;
34 import java.util.HashMap;
35 import java.util.Map;
37 import com.sun.xml.internal.bind.v2.runtime.Location;
39 /**
40 * {@link Annotation} that also implements {@link Locatable}.
41 *
42 * @author Kohsuke Kawaguchi
43 */
44 public class LocatableAnnotation implements InvocationHandler, Locatable, Location {
45 private final Annotation core;
47 private final Locatable upstream;
49 /**
50 * Wraps the annotation into a proxy so that the returned object will also implement
51 * {@link Locatable}.
52 */
53 public static <A extends Annotation> A create( A annotation, Locatable parentSourcePos ) {
54 if(annotation==null) return null;
55 Class<? extends Annotation> type = annotation.annotationType();
56 if(quicks.containsKey(type)) {
57 // use the existing proxy implementation if available
58 return (A)quicks.get(type).newInstance(parentSourcePos,annotation);
59 }
61 // otherwise take the slow route
63 ClassLoader cl = SecureLoader.getClassClassLoader(LocatableAnnotation.class);
65 try {
66 Class loadableT = Class.forName(type.getName(), false, cl);
67 if(loadableT !=type)
68 return annotation; // annotation type not loadable from this class loader
70 return (A)Proxy.newProxyInstance(cl,
71 new Class[]{ type, Locatable.class },
72 new LocatableAnnotation(annotation,parentSourcePos));
73 } catch (ClassNotFoundException e) {
74 // annotation not loadable
75 return annotation;
76 } catch (IllegalArgumentException e) {
77 // Proxy.newProxyInstance throws this if it cannot resolve this annotation
78 // in this classloader
79 return annotation;
80 }
82 }
84 LocatableAnnotation(Annotation core, Locatable upstream) {
85 this.core = core;
86 this.upstream = upstream;
87 }
89 public Locatable getUpstream() {
90 return upstream;
91 }
93 public Location getLocation() {
94 return this;
95 }
97 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
98 try {
99 if(method.getDeclaringClass()==Locatable.class)
100 return method.invoke(this,args);
101 if(Modifier.isStatic(method.getModifiers()))
102 // malicious code can pass in a static Method object.
103 // doing method.invoke() would end up executing it,
104 // so we need to protect against it.
105 throw new IllegalArgumentException();
107 return method.invoke(core,args);
108 } catch (InvocationTargetException e) {
109 if(e.getTargetException()!=null)
110 throw e.getTargetException();
111 throw e;
112 }
113 }
115 public String toString() {
116 return core.toString();
117 }
120 /**
121 * List of {@link Quick} implementations keyed by their annotation type.
122 */
123 private static final Map<Class,Quick> quicks = new HashMap<Class, Quick>();
125 static {
126 for( Quick q : Init.getAll() ) {
127 quicks.put(q.annotationType(),q);
128 }
129 }
130 }