001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.impl;
032:
033: import java.lang.annotation.Annotation;
034: import java.lang.reflect.*;
035: import java.util.*;
036: import net.sf.retrotranslator.runtime.asm.AnnotationVisitor;
037: import net.sf.retrotranslator.runtime.asm.signature.*;
038:
039: /**
040: * @author Taras Puchko
041: */
042: public class MethodDescriptor extends GenericDeclarationDescriptor {
043:
044: private String name;
045: private String desc;
046: private ClassDescriptor classDescriptor;
047: private LazyValue<Class, Method> method;
048: private LazyValue<String, Class> returnType;
049: private LazyValue<Object, Object> defaultValue;
050: private LazyValue<Class, Constructor> constructor;
051: private LazyValue<TypeDescriptor, Type> genericReturnType;
052: private LazyList<TypeDescriptor, Type> genericParameterTypes;
053: private LazyList<TypeDescriptor, Type> genericExceptionTypes;
054: private LazyList<List<AnnotationValue>, Annotation[]> parameterAnnotations;
055:
056: public MethodDescriptor(ClassDescriptor classDescriptor,
057: int access, final String name, final String desc,
058: String signature) {
059: this .classDescriptor = classDescriptor;
060: this .access = access;
061: this .name = name;
062: this .desc = desc;
063: if (signature != null)
064: new SignatureReader(signature).accept(this );
065: this .returnType = createReturnType();
066: if (name.equals(RuntimeTools.CONSTRUCTOR_NAME)) {
067: this .constructor = createConstructor();
068: } else if (!name.equals(RuntimeTools.STATIC_NAME)) {
069: this .method = createMethod();
070: }
071: parameterAnnotations = createParameterAnnotations();
072: }
073:
074: private LazyValue<String, Class> createReturnType() {
075: return new LazyValue<String, Class>(desc) {
076: protected Class resolve(String input) {
077: return getClassByType(net.sf.retrotranslator.runtime.asm.Type
078: .getReturnType(input));
079: }
080: };
081: }
082:
083: private LazyValue<Class, Constructor> createConstructor() {
084: return new LazyValue<Class, Constructor>(classDescriptor
085: .getTarget()) {
086: protected Constructor resolve(Class input) {
087: for (Constructor constructor : input
088: .getDeclaredConstructors()) {
089: if (RuntimeTools.getConstructorDescriptor(
090: constructor).equals(desc))
091: return constructor;
092: }
093: return null;
094: }
095: };
096: }
097:
098: private LazyValue<Class, Method> createMethod() {
099: return new LazyValue<Class, Method>(classDescriptor.getTarget()) {
100: protected Method resolve(Class input) {
101: for (Method method : input.getDeclaredMethods()) {
102: if (method.getName().equals(name)
103: && net.sf.retrotranslator.runtime.asm.Type
104: .getMethodDescriptor(method)
105: .equals(desc))
106: return method;
107: }
108: return null;
109: }
110: };
111: }
112:
113: public String getName() {
114: return name;
115: }
116:
117: public String getDesc() {
118: return desc;
119: }
120:
121: public Class getReturnType() {
122: return returnType.get();
123: }
124:
125: public Object getDefaultValue() {
126: return defaultValue == null ? null : RuntimeTools
127: .cloneNonEmptyArray(defaultValue.get());
128: }
129:
130: public static MethodDescriptor getInstance(Method method) {
131: ClassDescriptor classDescriptor = ClassDescriptor
132: .getInstance(method.getDeclaringClass());
133: String desc = net.sf.retrotranslator.runtime.asm.Type
134: .getMethodDescriptor(method);
135: MethodDescriptor methodDescriptor = classDescriptor
136: .getMethodDescriptor(method.getName() + desc);
137: if (methodDescriptor == null) {
138: methodDescriptor = new MethodDescriptor(classDescriptor,
139: method.getModifiers(), method.getName(), desc, null);
140: }
141: methodDescriptor.method.provide(method);
142: return methodDescriptor;
143: }
144:
145: public static MethodDescriptor getInstance(Constructor constructor) {
146: ClassDescriptor classDescriptor = ClassDescriptor
147: .getInstance(constructor.getDeclaringClass());
148: String desc = RuntimeTools
149: .getConstructorDescriptor(constructor);
150: MethodDescriptor methodDescriptor = classDescriptor
151: .getMethodDescriptor(RuntimeTools.CONSTRUCTOR_NAME
152: + desc);
153: if (methodDescriptor == null) {
154: methodDescriptor = new MethodDescriptor(classDescriptor,
155: constructor.getModifiers(),
156: RuntimeTools.CONSTRUCTOR_NAME, desc, null);
157: }
158: methodDescriptor.constructor.provide(constructor);
159: return methodDescriptor;
160: }
161:
162: public GenericDeclaration getTarget() {
163: return method != null ? method.get()
164: : constructor != null ? constructor.get() : null;
165: }
166:
167: public Method getMethod() {
168: return method == null ? null : method.get();
169: }
170:
171: public Constructor getConstructor() {
172: return constructor == null ? null : constructor.get();
173: }
174:
175: public ClassDescriptor getClassDescriptor() {
176: return classDescriptor;
177: }
178:
179: public String getInfo() {
180: return RuntimeTools.getMethodInfo(classDescriptor.getInfo(),
181: name, desc);
182: }
183:
184: protected TypeVariable findTypeVariable(String name) {
185: TypeVariable variable = getTypeVariable(name);
186: return variable != null ? variable : classDescriptor
187: .findTypeVariable(name);
188: }
189:
190: public Annotation[][] getParameterAnnotations() {
191: return parameterAnnotations.getClone();
192: }
193:
194: private LazyList<List<AnnotationValue>, Annotation[]> createParameterAnnotations() {
195: return new LazyList<List<AnnotationValue>, Annotation[]>() {
196: protected Annotation[] resolve(List<AnnotationValue> input) {
197: return createAnnotations(input);
198: }
199:
200: protected Annotation[][] newArray(int size) {
201: return new Annotation[net.sf.retrotranslator.runtime.asm.Type
202: .getArgumentTypes(desc).length][];
203: }
204: };
205: }
206:
207: public Type getGenericReturnType() {
208: return genericReturnType == null ? null : genericReturnType
209: .get();
210: }
211:
212: public Type[] getGenericParameterTypes() {
213: return genericParameterTypes == null ? null
214: : genericParameterTypes.getClone();
215: }
216:
217: public Type[] getGenericExceptionTypes() {
218: return genericExceptionTypes == null ? null
219: : genericExceptionTypes.getClone();
220: }
221:
222: protected Annotation[] createAnnotations(
223: Annotation[] declaredAnnotations) {
224: return declaredAnnotations;
225: }
226:
227: public AnnotationVisitor visitParameterAnnotation(int parameter,
228: String desc, boolean visible) {
229: if (!visible)
230: return EMPTY_VISITOR;
231: List<AnnotationValue> values = parameterAnnotations
232: .get(parameter);
233: if (values == null) {
234: values = new ArrayList<AnnotationValue>();
235: parameterAnnotations.set(parameter, values);
236: }
237: AnnotationValue value = new AnnotationValue(desc);
238: values.add(value);
239: return value;
240: }
241:
242: public void visit(String name, Object value) {
243: setDefaultValue(value);
244: }
245:
246: public void visitEnum(String name, String desc, String value) {
247: setDefaultValue(new EnumValue(desc, value));
248: }
249:
250: public AnnotationVisitor visitAnnotation(String name, String desc) {
251: AnnotationValue value = new AnnotationValue(desc);
252: setDefaultValue(value);
253: return value;
254: }
255:
256: public AnnotationVisitor visitArray(String name) {
257: AnnotationArray array = new AnnotationArray();
258: setDefaultValue(array);
259: return array;
260: }
261:
262: public SignatureVisitor visitParameterType() {
263: TypeDescriptor descriptor = new TypeDescriptor();
264: if (genericParameterTypes == null)
265: genericParameterTypes = getLazyList();
266: genericParameterTypes.add(descriptor);
267: return descriptor;
268: }
269:
270: public SignatureVisitor visitReturnType() {
271: TypeDescriptor descriptor = new TypeDescriptor();
272: genericReturnType = getLazyType(descriptor);
273: return descriptor;
274: }
275:
276: public SignatureVisitor visitExceptionType() {
277: TypeDescriptor descriptor = new TypeDescriptor();
278: if (genericExceptionTypes == null)
279: genericExceptionTypes = getLazyList();
280: genericExceptionTypes.add(descriptor);
281: return descriptor;
282: }
283:
284: private void setDefaultValue(Object o) {
285: defaultValue = new LazyValue<Object, Object>(o) {
286: protected Object resolve(Object input) {
287: return resolveValue(input, getReturnType(),
288: MethodDescriptor.this);
289: }
290: };
291: }
292:
293: }
|