KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.*;
35 import java.lang.annotation.Inherited JavaDoc;
36 import java.lang.ref.SoftReference JavaDoc;
37 import java.lang.reflect.*;
38 import java.lang.reflect.Type JavaDoc;
39 import java.util.*;
40 import net.sf.retrotranslator.runtime.asm.*;
41 import net.sf.retrotranslator.runtime.asm.signature.*;
42 import net.sf.retrotranslator.runtime.java.lang.annotation.Annotation_;
43
44 /**
45  * @author Taras Puchko
46  */

47 public class ClassDescriptor extends GenericDeclarationDescriptor {
48
49     public static final String JavaDoc SIGNATURES_NAME = "signatures.properties";
50
51     private static SoftReference JavaDoc<Map<Class JavaDoc, ClassDescriptor>> cache;
52     private static Properties signatures = getSignatures();
53     private static BytecodeTransformer bytecodeTransformer;
54
55     private String JavaDoc name;
56     private Class JavaDoc target;
57     private String JavaDoc enclosingClass;
58     private String JavaDoc enclosingMethod;
59     private LazyList<TypeDescriptor, Type JavaDoc> genericInterfaces;
60     private LazyValue<TypeDescriptor, Type JavaDoc> genericSuperclass;
61     private Map<String JavaDoc, FieldDescriptor> fieldDescriptors = new HashMap<String JavaDoc, FieldDescriptor>();
62     private Map<String JavaDoc, MethodDescriptor> methodDescriptors = new HashMap<String JavaDoc, MethodDescriptor>();
63
64     private static Properties getSignatures() {
65         try {
66             Properties properties = new Properties();
67             InputStream stream = ClassDescriptor.class.getResourceAsStream(SIGNATURES_NAME);
68             if (stream != null) {
69                 properties.load(stream);
70                 stream.close();
71             }
72             return properties;
73         } catch (IOException e) {
74             throw new RuntimeException JavaDoc(e);
75         }
76     }
77
78     public ClassDescriptor(Class JavaDoc target, byte[] bytecode) {
79         this.target = target;
80         if (bytecode != null) {
81             if (bytecodeTransformer != null) {
82                 bytecode = bytecodeTransformer.transform(bytecode, 0, bytecode.length);
83             }
84             new ClassReader(bytecode).accept(this, true);
85         }
86     }
87
88     public static void setBytecodeTransformer(BytecodeTransformer transformer) {
89         bytecodeTransformer = transformer;
90     }
91
92     public static ClassDescriptor getInstance(Class JavaDoc target) {
93         Map<Class JavaDoc, ClassDescriptor> map = getMap();
94         ClassDescriptor descriptor = map.get(target);
95         if (descriptor != null) return descriptor;
96         descriptor = new ClassDescriptor(target, RuntimeTools.getBytecode(target));
97         map.put(target, descriptor);
98         return descriptor;
99     }
100
101     private static synchronized Map<Class JavaDoc, ClassDescriptor> getMap() {
102         Map<Class JavaDoc, ClassDescriptor> map = cache == null ? null : cache.get();
103         if (map == null) {
104             map = new Hashtable<Class JavaDoc, ClassDescriptor>();
105             cache = new SoftReference JavaDoc<Map<Class JavaDoc, ClassDescriptor>>(map);
106         }
107         return map;
108     }
109
110     protected Annotation_[] createAnnotations(Annotation_[] declaredAnnotations) {
111         Class JavaDoc superclass = target.getSuperclass();
112         if (superclass == null) return declaredAnnotations;
113         Annotation_[] superAnnotations = getInstance(superclass).getAnnotations();
114         if (superAnnotations.length == 0) return declaredAnnotations;
115         Map<Class JavaDoc, Annotation_> result = new HashMap<Class JavaDoc, Annotation_>();
116         for (Annotation_ annotation : superAnnotations) {
117             Class JavaDoc annotationClass = annotation.getClass().getInterfaces()[0];
118             if (annotationClass.isAnnotationPresent(Inherited JavaDoc.class)) {
119                 result.put(annotationClass, annotation);
120             }
121         }
122         for (Annotation_ annotation : declaredAnnotations) {
123             result.put(annotation.getClass().getInterfaces()[0], annotation);
124         }
125         return result.values().toArray(new Annotation_[result.size()]);
126     }
127
128     public String JavaDoc getName() {
129         return name;
130     }
131
132     public ClassDescriptor getClassDescriptor() {
133         return this;
134     }
135
136     public MethodDescriptor getEnclosingMethodDescriptor() {
137         return enclosingMethod == null ? null
138                 : getInstance(getClassByInternalName(enclosingClass)).getMethodDescriptor(enclosingMethod);
139     }
140
141     public boolean isLocalOrAnonymous() {
142         return enclosingMethod != null;
143     }
144
145     public FieldDescriptor getFieldDescriptor(String JavaDoc name) {
146         return fieldDescriptors.get(name);
147     }
148
149     public Type JavaDoc[] getGenericInterfaces() {
150         return genericInterfaces == null ? null : genericInterfaces.getClone();
151     }
152
153     public Type JavaDoc getGenericSuperclass() {
154         return genericSuperclass == null ? null : genericSuperclass.get();
155     }
156
157     public MethodDescriptor getMethodDescriptor(String JavaDoc key) {
158         return methodDescriptors.get(key);
159     }
160
161     public Collection<MethodDescriptor> getMethodDescriptors() {
162         return methodDescriptors.values();
163     }
164
165     public Collection<FieldDescriptor> getFieldDescriptors() {
166         return fieldDescriptors.values();
167     }
168
169     public Class JavaDoc getTarget() {
170         return target;
171     }
172
173     protected TypeVariable findTypeVariable(String JavaDoc name) {
174         TypeVariable variable = getTypeVariable(name);
175         if (variable != null) return variable;
176         MethodDescriptor methodDescriptor = getEnclosingMethodDescriptor();
177         if (methodDescriptor != null) return methodDescriptor.findTypeVariable(name);
178         Class JavaDoc declaringClass = target.getDeclaringClass();
179         if (declaringClass != null) return getInstance(declaringClass).findTypeVariable(name);
180         throw new MalformedParameterizedTypeException();
181     }
182
183     public void visit(int version, int access, String JavaDoc name, String JavaDoc signature, String JavaDoc superName, String JavaDoc[] interfaces) {
184         this.access = access;
185         this.name = name;
186         if (signature == null) signature = signatures.getProperty(name);
187         if (signature != null) new SignatureReader(signature).accept(this);
188     }
189
190     public void visitOuterClass(String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
191         if (name != null) {
192             enclosingClass = owner;
193             enclosingMethod = name + desc;
194         }
195     }
196
197     public void visitInnerClass(String JavaDoc name, String JavaDoc outerName, String JavaDoc innerName, int access) {
198         if (name.equals(this.name)) this.access |= access;
199     }
200
201     public FieldVisitor visitField(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, Object JavaDoc value) {
202         FieldDescriptor fieldDescriptor = new FieldDescriptor(this, access, name, desc, signature);
203         fieldDescriptors.put(name, fieldDescriptor);
204         return fieldDescriptor;
205     }
206
207     public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
208         MethodDescriptor methodDescriptor = new MethodDescriptor(this, access, name, desc, signature);
209         methodDescriptors.put(name + desc, methodDescriptor);
210         return methodDescriptor;
211     }
212
213     public SignatureVisitor visitSuperclass() {
214         TypeDescriptor descriptor = new TypeDescriptor();
215         if (!isAccess(Opcodes.ACC_INTERFACE)) {
216             genericSuperclass = getLazyType(descriptor);
217         }
218         return descriptor;
219     }
220
221     public SignatureVisitor visitInterface() {
222         TypeDescriptor descriptor = new TypeDescriptor();
223         if (genericInterfaces == null) genericInterfaces = getLazyList();
224         genericInterfaces.add(descriptor);
225         return descriptor;
226     }
227
228 }
229
Popular Tags