KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > transformer > ClassLiteralVisitor


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.transformer;
33
34 import java.util.*;
35 import net.sf.retrotranslator.runtime.asm.*;
36 import static net.sf.retrotranslator.runtime.asm.Opcodes.*;
37
38 /**
39  * @author Taras Puchko
40  */

41 class ClassLiteralVisitor extends ClassAdapter {
42
43     private static final Map<Integer JavaDoc, Integer JavaDoc> primitiveTypes = getPrimitiveTypes();
44
45     private Set<String JavaDoc> currentFieldNames = new HashSet<String JavaDoc>();
46     private Set<String JavaDoc> syntheticFieldNames = new HashSet<String JavaDoc>();
47     private String JavaDoc currentClassName;
48     private boolean isInterface;
49
50     public ClassLiteralVisitor(final ClassVisitor cv) {
51         super(cv);
52     }
53
54     public void visit(final int version, final int access, final String JavaDoc name, final String JavaDoc signature, final String JavaDoc superName, final String JavaDoc[] interfaces) {
55         currentClassName = name;
56         isInterface = (access & ACC_INTERFACE) != 0;
57         super.visit(version, access, name, signature, superName, interfaces);
58     }
59
60     public void visitEnd() {
61         for (String JavaDoc fieldName : syntheticFieldNames) {
62             if (!currentFieldNames.contains(fieldName)) {
63                 cv.visitField(ACC_STATIC + ACC_SYNTHETIC, fieldName, Type.getDescriptor(Class JavaDoc.class), null, null).visitEnd();
64             }
65         }
66         super.visitEnd();
67     }
68
69     public FieldVisitor visitField(final int access, final String JavaDoc name, final String JavaDoc desc, final String JavaDoc signature, final Object JavaDoc value) {
70         currentFieldNames.add(name);
71         return super.visitField(access, name, desc, signature, value);
72     }
73
74     public MethodVisitor visitMethod(final int access, final String JavaDoc name, final String JavaDoc desc, final String JavaDoc signature, final String JavaDoc[] exceptions) {
75         MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
76         return visitor == null ? null : new MethodAdapter(visitor) {
77
78             public void visitLdcInsn(final Object JavaDoc cst) {
79                 if (cst instanceof Type) {
80                     visitClassLiteral((Type) cst);
81                 } else {
82                     super.visitLdcInsn(cst);
83                 }
84             }
85
86             private void visitClassLiteral(Type type) {
87                 if (isInterface) {
88                     loadClassLiteral(type);
89                     return;
90                 }
91                 String JavaDoc fieldName = getFieldName(type);
92                 syntheticFieldNames.add(fieldName);
93                 mv.visitFieldInsn(GETSTATIC, currentClassName, fieldName, Type.getDescriptor(Class JavaDoc.class));
94                 mv.visitInsn(DUP);
95                 Label label = new Label();
96                 visitJumpInsn(IFNONNULL, label);
97                 mv.visitInsn(POP);
98                 loadClassLiteral(type);
99                 mv.visitInsn(DUP);
100                 visitFieldInsn(PUTSTATIC, currentClassName, fieldName, Type.getDescriptor(Class JavaDoc.class));
101                 visitLabel(label);
102             }
103
104             private void loadClassLiteral(Type type) {
105                 mv.visitInsn(ICONST_0);
106                 visitNewArray(type);
107                 mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Object JavaDoc.class),
108                         "getClass", TransformerTools.descriptor(Class JavaDoc.class));
109                 if (type.getSort() != Type.ARRAY) {
110                     mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Class JavaDoc.class),
111                             "getComponentType", TransformerTools.descriptor(Class JavaDoc.class));
112                 }
113             }
114
115             private void visitNewArray(Type type) {
116                 if (type.getSort() != Type.ARRAY) {
117                     mv.visitTypeInsn(ANEWARRAY, type.getInternalName());
118                 } else if (type.getDimensions() != 1) {
119                     mv.visitTypeInsn(ANEWARRAY, type.toString().substring(1));
120                 } else {
121                     Type elementType = type.getElementType();
122                     if (elementType.getSort() == Type.OBJECT) {
123                         mv.visitTypeInsn(ANEWARRAY, elementType.getInternalName());
124                     } else {
125                         mv.visitIntInsn(NEWARRAY, primitiveTypes.get(elementType.getSort()));
126                     }
127                 }
128             }
129
130         };
131     }
132
133     private static String JavaDoc getFieldName(Type type) {
134         String JavaDoc var = type.getDescriptor();
135         if (var.startsWith("L")) {
136             var = "class$" + var.substring(1);
137         } else if (var.startsWith("[")) {
138             var = "array$" + var.substring(1);
139         }
140         if (var.endsWith(";")) {
141             var = var.substring(0, var.length() - 1);
142         }
143         return var.replace('[', '$').replace('/', '$');
144     }
145
146     private static Map<Integer JavaDoc, Integer JavaDoc> getPrimitiveTypes() {
147         Map<Integer JavaDoc, Integer JavaDoc> types = new HashMap<Integer JavaDoc, Integer JavaDoc>();
148         types.put(Type.BOOLEAN, T_BOOLEAN);
149         types.put(Type.CHAR, T_CHAR);
150         types.put(Type.FLOAT, T_FLOAT);
151         types.put(Type.DOUBLE, T_DOUBLE);
152         types.put(Type.BYTE, T_BYTE);
153         types.put(Type.SHORT, T_SHORT);
154         types.put(Type.INT, T_INT);
155         types.put(Type.LONG, T_LONG);
156         return types;
157     }
158 }
159
Popular Tags