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.java.lang;
032:
033: import java.lang.annotation.Annotation;
034: import java.lang.reflect.*;
035: import java.util.Arrays;
036: import net.sf.retrotranslator.registry.Advanced;
037: import net.sf.retrotranslator.runtime.asm.Opcodes;
038: import net.sf.retrotranslator.runtime.impl.*;
039:
040: /**
041: * @author Taras Puchko
042: */
043: public class _Class {
044:
045: public static Class asSubclass(Class aClass, Class super class) {
046: if (super class.isAssignableFrom(aClass))
047: return aClass;
048: throw new ClassCastException(aClass.toString());
049: }
050:
051: public static Object cast(Class aClass, Object obj) {
052: if (obj == null || aClass.isInstance(obj))
053: return obj;
054: throw new ClassCastException(aClass.toString());
055: }
056:
057: public static Annotation getAnnotation(Class aClass,
058: Class annotationType) {
059: return ClassDescriptor.getInstance(aClass).getAnnotation(
060: annotationType);
061: }
062:
063: public static Annotation[] getAnnotations(Class aClass) {
064: return ClassDescriptor.getInstance(aClass).getAnnotations();
065: }
066:
067: public static String getCanonicalName(Class aClass) {
068: if (aClass.isArray()) {
069: String name = getCanonicalName(aClass.getComponentType());
070: return name == null ? null : name + "[]";
071: }
072: if (ClassDescriptor.getInstance(aClass).isLocalOrAnonymous())
073: return null;
074: Class declaringClass = aClass.getDeclaringClass();
075: return declaringClass == null ? aClass.getName()
076: : getCanonicalName(declaringClass) + "."
077: + getSimpleName(aClass);
078: }
079:
080: public static Annotation[] getDeclaredAnnotations(Class aClass) {
081: return ClassDescriptor.getInstance(aClass)
082: .getDeclaredAnnotations();
083: }
084:
085: @Advanced("Class.getDeclaredMethod")
086: public static Method getDeclaredMethod(Class aClass, String name,
087: Class... parameterTypes) throws NoSuchMethodException,
088: SecurityException {
089: Method method = findMethod(aClass.getDeclaredMethods(), name,
090: parameterTypes);
091: return method != null ? method : aClass.getDeclaredMethod(name,
092: parameterTypes);
093: }
094:
095: public static Class getEnclosingClass(Class aClass) {
096: MethodDescriptor descriptor = ClassDescriptor.getInstance(
097: aClass).getEnclosingMethodDescriptor();
098: return descriptor == null ? aClass.getDeclaringClass()
099: : descriptor.getClassDescriptor().getTarget();
100: }
101:
102: public static Constructor getEnclosingConstructor(Class aClass) {
103: MethodDescriptor descriptor = ClassDescriptor.getInstance(
104: aClass).getEnclosingMethodDescriptor();
105: return descriptor == null ? null : descriptor.getConstructor();
106: }
107:
108: public static Method getEnclosingMethod(Class aClass) {
109: MethodDescriptor descriptor = ClassDescriptor.getInstance(
110: aClass).getEnclosingMethodDescriptor();
111: return descriptor == null ? null : descriptor.getMethod();
112: }
113:
114: public static Object[] getEnumConstants(Class aClass) {
115: return Enum_.getEnumConstants(aClass);
116: }
117:
118: public static Type[] getGenericInterfaces(Class aClass) {
119: return RuntimeTools.getTypes(aClass.getInterfaces(),
120: ClassDescriptor.getInstance(aClass)
121: .getGenericInterfaces());
122: }
123:
124: public static Type getGenericSuperclass(Class aClass) {
125: return RuntimeTools.getType(aClass.getSuperclass(),
126: ClassDescriptor.getInstance(aClass)
127: .getGenericSuperclass());
128: }
129:
130: @Advanced("Class.getMethod")
131: public static Method getMethod(Class aClass, String name,
132: Class... parameterTypes) throws NoSuchMethodException,
133: SecurityException {
134: Method method = findMethod(aClass.getMethods(), name,
135: parameterTypes);
136: return method != null ? method : aClass.getMethod(name,
137: parameterTypes);
138: }
139:
140: public static String getSimpleName(Class aClass) {
141: if (aClass.isArray())
142: return getSimpleName(aClass.getComponentType()) + "[]";
143: String this Name = aClass.getName();
144: Class enclosingClass = getEnclosingClass(aClass);
145: if (enclosingClass == null)
146: return this Name.substring(this Name.lastIndexOf('.') + 1);
147: String enclosingName = enclosingClass.getName();
148: if (!this Name.startsWith(enclosingName))
149: throw new InternalError();
150: String name = this Name.substring(enclosingName.length());
151: if (!name.startsWith("$"))
152: throw new InternalError();
153: for (int i = 1; i < name.length(); i++) {
154: char c = name.charAt(i);
155: if (c < '0' || c > '9')
156: return name.substring(i);
157: }
158: return "";
159: }
160:
161: public static TypeVariable[] getTypeParameters(Class aClass) {
162: return ClassDescriptor.getInstance(aClass).getTypeParameters();
163: }
164:
165: public static boolean isAnnotation(Class aClass) {
166: return ClassDescriptor.getInstance(aClass).isAccess(
167: Opcodes.ACC_ANNOTATION);
168: }
169:
170: public static boolean isAnnotationPresent(Class aClass,
171: Class annotationType) {
172: return ClassDescriptor.getInstance(aClass).isAnnotationPresent(
173: annotationType);
174: }
175:
176: public static boolean isAnonymousClass(Class aClass) {
177: return "".equals(getSimpleName(aClass));
178: }
179:
180: public static boolean isEnum(Class aClass) {
181: return aClass.getSuperclass() == Enum.class
182: && ClassDescriptor.getInstance(aClass).isAccess(
183: Opcodes.ACC_ENUM);
184: }
185:
186: public static boolean isLocalClass(Class aClass) {
187: return ClassDescriptor.getInstance(aClass).isLocalOrAnonymous()
188: && !isAnonymousClass(aClass);
189: }
190:
191: public static boolean isMemberClass(Class aClass) {
192: return aClass.getDeclaringClass() != null;
193: }
194:
195: public static boolean isSynthetic(Class aClass) {
196: return ClassDescriptor.getInstance(aClass).isAccess(
197: Opcodes.ACC_SYNTHETIC);
198: }
199:
200: private static Method findMethod(Method[] methods, String name,
201: Class... parameterTypes) {
202: Method result = null;
203: for (Method method : methods) {
204: if (method.getName().equals(name)
205: && Arrays.equals(method.getParameterTypes(),
206: parameterTypes)
207: && (result == null || result.getReturnType()
208: .isAssignableFrom(method.getReturnType()))) {
209: result = method;
210: }
211: }
212: return result;
213: }
214:
215: // Referenced from translated bytecode
216: public static void setEncodedMetadata(Class aClass, String metadata) {
217: ClassDescriptor.setEncodedMetadata(aClass, metadata);
218: }
219:
220: }
|