KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > runtime > impl > AnnotatedElementDescriptor


1 /***
2  * Retrotranslator: a Java bytecode transformer that translates Java classes
3  * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
4  *
5  * Copyright (c) 2005 - 2007 Taras Puchko
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the copyright holders nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */

32 package net.sf.retrotranslator.runtime.impl;
33
34 import java.lang.reflect.*;
35 import java.util.*;
36 import net.sf.retrotranslator.runtime.asm.*;
37 import net.sf.retrotranslator.runtime.asm.Type;
38 import net.sf.retrotranslator.runtime.java.lang.Enum_;
39 import net.sf.retrotranslator.runtime.java.lang.annotation.*;
40
41 /**
42  * @author Taras Puchko
43  */

44 public abstract class AnnotatedElementDescriptor extends EmptyVisitor {
45
46     private static final Annotation_[] EMPTY = new Annotation_[0];
47     protected static final EmptyVisitor EMPTY_VISITOR = new EmptyVisitor();
48
49     protected int access;
50
51     private LazyList<AnnotationValue, Annotation_> declaredAnnotations = new LazyList<AnnotationValue, Annotation_>() {
52         protected Annotation_ resolve(AnnotationValue input) {
53             return createAnnotation(input);
54         }
55
56         protected Annotation_[] newArray(int size) {
57             return new Annotation_[size];
58         }
59     };
60
61     private LazyValue<LazyList<AnnotationValue, Annotation_>, Annotation_[]> annotations
62             = new LazyValue<LazyList<AnnotationValue, Annotation_>, Annotation_[]>(declaredAnnotations) {
63         protected Annotation_[] resolve(LazyList<AnnotationValue, Annotation_> input) {
64             return createAnnotations(input.getLive());
65         }
66     };
67
68     public boolean isAccess(int mask) {
69         return (access & mask) != 0;
70     }
71
72     public boolean isAnnotationPresent(Class JavaDoc annotationType) {
73         for (Annotation_ annotation : annotations.get()) {
74             if (annotationType.isInstance(annotation)) return true;
75         }
76         return false;
77     }
78
79     public Annotation_ getAnnotation(Class JavaDoc annotationType) {
80         for (Annotation_ annotation : annotations.get()) {
81             if (annotationType.isInstance(annotation)) return annotation;
82         }
83         return null;
84     }
85
86     public Annotation_[] getAnnotations() {
87         Annotation_[] result = annotations.get();
88         return result.length == 0 ? result : result.clone();
89     }
90
91     public Annotation_[] getDeclaredAnnotations() {
92         return declaredAnnotations.getClone();
93     }
94
95     public abstract ClassDescriptor getClassDescriptor();
96
97     protected abstract TypeVariable findTypeVariable(String JavaDoc name);
98
99     protected abstract Annotation_[] createAnnotations(Annotation_[] declaredAnnotations);
100
101     protected Annotation_[] createAnnotations(List<AnnotationValue> values) {
102         if (values == null) return EMPTY;
103         Annotation_[] result = new Annotation_[values.size()];
104         for (int i = 0; i < result.length; i++) {
105             result[i] = createAnnotation(values.get(i));
106         }
107         return result;
108     }
109
110     public AnnotationVisitor visitAnnotation(String JavaDoc desc, boolean visible) {
111         if (!visible) return EMPTY_VISITOR;
112         AnnotationValue value = new AnnotationValue(desc);
113         declaredAnnotations.add(value);
114         return value;
115     }
116
117     private ClassLoader JavaDoc getClassLoader() {
118         return getClassDescriptor().getTarget().getClassLoader();
119     }
120
121     protected Class JavaDoc getClassByInternalName(String JavaDoc name) {
122         name = name.replace('/', '.');
123         try {
124             return Class.forName(name, false, getClassLoader());
125         } catch (ClassNotFoundException JavaDoc e) {
126             throw new TypeNotPresentException JavaDoc(name, e);
127         }
128     }
129
130     protected Class JavaDoc getClassByType(net.sf.retrotranslator.runtime.asm.Type type) {
131         Class JavaDoc baseClass = RuntimeTools.getBaseClass(type);
132         if (baseClass != null) return baseClass;
133         return getClassByInternalName(type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName());
134     }
135
136     private Class JavaDoc getClassByDesc(String JavaDoc desc) {
137         return getClassByType(net.sf.retrotranslator.runtime.asm.Type.getType(desc));
138     }
139
140     public java.lang.reflect.Type JavaDoc[] createTypes(List<TypeDescriptor> descriptors) {
141         if (descriptors == null) return null;
142         java.lang.reflect.Type JavaDoc[] result = new java.lang.reflect.Type JavaDoc[descriptors.size()];
143         Iterator<TypeDescriptor> iterator = descriptors.iterator();
144         for (int i = 0; i < result.length; i++) {
145             result[i] = createType(iterator.next());
146         }
147         return result;
148     }
149
150     public java.lang.reflect.Type JavaDoc createType(TypeDescriptor descriptor) {
151         if (descriptor == null) return null;
152         if (descriptor.arrayType != null) {
153             return new GenericArrayTypeImpl(createType(descriptor.arrayType));
154         }
155         if (descriptor.typeVariable != null) {
156             return findTypeVariable(descriptor.typeVariable);
157         }
158         LinkedList<ClassTypeElement> elements = descriptor.elements;
159         if (elements != null) {
160             return createClassType(elements.toArray(new ClassTypeElement[elements.size()]));
161         }
162         return RuntimeTools.getBaseClass(descriptor.baseType);
163     }
164
165     private java.lang.reflect.Type JavaDoc createClassType(ClassTypeElement[] typeElements) {
166         class Element {
167             Class JavaDoc rawType;
168             List<TypeArgument> arguments;
169
170             public Element(Class JavaDoc rawType, List<TypeArgument> arguments) {
171                 this.rawType = rawType;
172                 this.arguments = arguments;
173             }
174         }
175         String JavaDoc className = null;
176         for (ClassTypeElement typeElement : typeElements) {
177             className = (className == null ? "" : className + "$") + typeElement.getName();
178         }
179         LinkedList<Element> elements = new LinkedList<Element>();
180         Class JavaDoc currentClass = getClassByInternalName(className);
181         for (int i = typeElements.length - 1; i >= 0; i--) {
182             elements.addFirst(new Element(currentClass, typeElements[i].getArguments()));
183             currentClass = currentClass.getDeclaringClass();
184             if (currentClass == null) break;
185         }
186         java.lang.reflect.Type JavaDoc result = elements.getFirst().arguments.isEmpty() ? null : currentClass;
187         for (Element element : elements) {
188             result = (result == null && element.arguments.isEmpty()) ? element.rawType
189                     : new ParameterizedTypeImpl(createArguments(element.arguments), element.rawType, result);
190         }
191         return result;
192     }
193
194     private java.lang.reflect.Type JavaDoc[] createArguments(List<TypeArgument> arguments) {
195         java.lang.reflect.Type JavaDoc[] result = new java.lang.reflect.Type JavaDoc[arguments.size()];
196         Iterator<TypeArgument> iterator = arguments.iterator();
197         for (int i = 0; i < result.length; i++) {
198             TypeArgument argument = iterator.next();
199             result[i] = argument.wildcard == INSTANCEOF ? createType(argument.descriptor)
200                     : new WildcardTypeImpl(argument.wildcard == EXTENDS, getLazyType(argument.descriptor));
201         }
202         return result;
203     }
204
205     protected Annotation_ createAnnotation(AnnotationValue annotationValue) {
206         Class JavaDoc annotationType = getClassByDesc(annotationValue.getDesc());
207         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("@").append(annotationType.getName()).append('(');
208         Map<String JavaDoc, Object JavaDoc> values = new HashMap<String JavaDoc, Object JavaDoc>();
209         boolean isFirst = true;
210         for (MethodDescriptor descriptor : ClassDescriptor.getInstance(annotationType).getMethodDescriptors()) {
211             if (isFirst) {
212                 isFirst = false;
213             } else {
214                 buffer.append(", ");
215             }
216             String JavaDoc elementName = descriptor.getName();
217             Object JavaDoc elementValue = annotationValue.getElement(elementName);
218             Object JavaDoc resolvedValue = elementValue == null ? descriptor.getDefaultValue()
219                     : resolveValue(elementValue, descriptor.getReturnType(), descriptor);
220             if (resolvedValue == null) throw new IncompleteAnnotationException_(annotationType, elementName);
221             values.put(elementName, resolvedValue);
222             buffer.append(elementName).append('=');
223             append(buffer, resolvedValue);
224         }
225         buffer.append(")");
226         Class JavaDoc[] interfaces = Annotation_.class.isAssignableFrom(annotationType) ?
227                 new Class JavaDoc[]{annotationType} : new Class JavaDoc[]{annotationType, Annotation_.class};
228         return (Annotation_) Proxy.newProxyInstance(getClassLoader(),
229                 interfaces, new AnnotationHandler(annotationType, buffer.toString(), values));
230     }
231
232     protected Object JavaDoc resolveValue(Object JavaDoc value, Class JavaDoc type, MethodDescriptor descriptor) {
233         if (value == null) return null;
234         if (value instanceof net.sf.retrotranslator.runtime.asm.Type) {
235             value = getClassByType((net.sf.retrotranslator.runtime.asm.Type) value);
236         } else if (value instanceof EnumValue) {
237             EnumValue enumValue = (EnumValue) value;
238             value = Enum.valueOf(getClassByDesc(enumValue.getDescriptor()), enumValue.getValue());
239         } else if (value instanceof AnnotationValue) {
240             value = createAnnotation((AnnotationValue) value);
241         } else if (value instanceof AnnotationArray) {
242             AnnotationArray array = (AnnotationArray) value;
243             Class JavaDoc componentType = type.getComponentType();
244             List<Object JavaDoc> values = array.getValues();
245             value = Array.newInstance(componentType, values.size());
246             for (int i = Array.getLength(value) - 1; i >= 0; i--) {
247                 Array.set(value, i, resolveValue(values.get(i), componentType, descriptor));
248             }
249         }
250         if (!type.isPrimitive() && !type.isInstance(value)) {
251             throw new AnnotationTypeMismatchException_(descriptor.getMethod(), type.getName());
252         }
253         return value;
254     }
255
256
257     private static void append(StringBuffer JavaDoc buffer, Object JavaDoc value) {
258         if (value.getClass().isArray()) {
259             buffer.append('[');
260             int length = Array.getLength(value);
261             for (int i = 0; i < length; i++) {
262                 if (i > 0) buffer.append(", ");
263                 append(buffer, Array.get(value, i));
264             }
265             buffer.append(']');
266         } else {
267             buffer.append(value);
268         }
269     }
270
271     protected LazyValue<TypeDescriptor, java.lang.reflect.Type JavaDoc> getLazyType(TypeDescriptor descriptor) {
272         if (descriptor == null) return null;
273         return new LazyValue<TypeDescriptor, java.lang.reflect.Type JavaDoc>(descriptor) {
274             protected java.lang.reflect.Type JavaDoc resolve(TypeDescriptor input) {
275                 return createType(input);
276             }
277         };
278     }
279
280     protected LazyList<TypeDescriptor, java.lang.reflect.Type JavaDoc> getLazyList() {
281         return new LazyList<TypeDescriptor, java.lang.reflect.Type JavaDoc>() {
282
283             protected java.lang.reflect.Type JavaDoc resolve(TypeDescriptor descriptor) {
284                 return createType(descriptor);
285             }
286
287             protected java.lang.reflect.Type JavaDoc[] newArray(int size) {
288                 return new java.lang.reflect.Type JavaDoc[size];
289             }
290         };
291     }
292
293 }
294
Popular Tags