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.registry;
032:
033: import java.io.*;
034: import java.util.*;
035: import net.sf.retrotranslator.runtime.asm.*;
036: import net.sf.retrotranslator.runtime.impl.*;
037:
038: /**
039: * @author Taras Puchko
040: */
041: public class AdvancedPostProcessor {
042:
043: private final static String ADVANCED_DESCRIPTOR = Type.getType(
044: Advanced.class).getDescriptor();
045:
046: private final Map<String, String> map = new LinkedHashMap<String, String>();
047:
048: private class AdvancedClassVisitor extends ClassAdapter {
049:
050: private String className;
051:
052: public AdvancedClassVisitor(ClassVisitor visitor) {
053: super (visitor);
054: }
055:
056: public void visit(int version, int access, String name,
057: String signature, String super Name, String[] interfaces) {
058: super .visit(version, access, name, signature, super Name,
059: interfaces);
060: className = RuntimeTools.getDisplayClassName(name);
061: }
062:
063: public AnnotationVisitor visitAnnotation(String desc,
064: boolean visible) {
065: return desc.equals(ADVANCED_DESCRIPTOR) ? new AdvancedAnnotationVisitor(
066: className)
067: : super .visitAnnotation(desc, visible);
068: }
069:
070: public MethodVisitor visitMethod(int access, String name,
071: String desc, String signature, String[] exceptions) {
072: return new AdvancedMethodVisitor(RuntimeTools
073: .getMethodInfo(className, name, desc), super
074: .visitMethod(access, name, desc, signature,
075: exceptions));
076: }
077:
078: public FieldVisitor visitField(int access, String name,
079: String desc, String signature, Object value) {
080: return new AdvancedFieldVisitor(RuntimeTools.getFieldInfo(
081: className, name), super .visitField(access, name,
082: desc, signature, value));
083: }
084: }
085:
086: private class AdvancedMethodVisitor extends MethodAdapter {
087:
088: private final String key;
089:
090: public AdvancedMethodVisitor(String key, MethodVisitor visitor) {
091: super (visitor);
092: this .key = key;
093: }
094:
095: public AnnotationVisitor visitAnnotation(String desc,
096: boolean visible) {
097: return desc.equals(ADVANCED_DESCRIPTOR) ? new AdvancedAnnotationVisitor(
098: key)
099: : super .visitAnnotation(desc, visible);
100: }
101: }
102:
103: private class AdvancedFieldVisitor implements FieldVisitor {
104:
105: private final String key;
106: private final FieldVisitor visitor;
107:
108: public AdvancedFieldVisitor(String key, FieldVisitor visitor) {
109: this .key = key;
110: this .visitor = visitor;
111: }
112:
113: public AnnotationVisitor visitAnnotation(String desc,
114: boolean visible) {
115: return desc.equals(ADVANCED_DESCRIPTOR) ? new AdvancedAnnotationVisitor(
116: key)
117: : visitor.visitAnnotation(desc, visible);
118: }
119:
120: public void visitAttribute(Attribute attr) {
121: visitor.visitAttribute(attr);
122: }
123:
124: public void visitEnd() {
125: visitor.visitEnd();
126: }
127: }
128:
129: private class AdvancedAnnotationVisitor extends AnnotationValue {
130:
131: public AdvancedAnnotationVisitor(String descriptor) {
132: super (descriptor);
133: }
134:
135: public void visitEnd() {
136: AnnotationArray array = (AnnotationArray) getElement("value");
137: StringBuilder builder = new StringBuilder();
138: for (Object value : array.getValues()) {
139: if (builder.length() > 0) {
140: builder.append(',');
141: }
142: builder.append(value);
143: }
144: map.put(getDesc(), builder.toString());
145: }
146: }
147:
148: public static void main(String[] args) throws IOException {
149: if (args.length != 2) {
150: throw new IllegalArgumentException();
151: }
152: AdvancedPostProcessor processor = new AdvancedPostProcessor();
153: processor.traverse(new File(args[0]));
154: processor.save(new File(args[1]));
155: }
156:
157: private void traverse(File sourceFolder) throws IOException {
158: for (File file : sourceFolder.listFiles()) {
159: if (file.isDirectory()) {
160: traverse(file);
161: } else if (file.getPath().endsWith(".class")) {
162: translate(file);
163: }
164: }
165: }
166:
167: private void translate(File file) throws IOException {
168: ClassWriter classWriter = new ClassWriter(true);
169: FileInputStream inputStream = new FileInputStream(file);
170: try {
171: new ClassReader(inputStream).accept(
172: new AdvancedClassVisitor(classWriter), false);
173: } finally {
174: inputStream.close();
175: }
176: FileOutputStream outputStream = new FileOutputStream(file);
177: try {
178: outputStream.write(classWriter.toByteArray(true));
179: } finally {
180: outputStream.close();
181: }
182: }
183:
184: private void save(File outputFile) throws IOException {
185: outputFile.getParentFile().mkdirs();
186: Writer writer = new OutputStreamWriter(new FileOutputStream(
187: outputFile), "UTF-8");
188: try {
189: for (Map.Entry<String, String> entry : map.entrySet()) {
190: writer.write(entry.getKey());
191: writer.write(':');
192: writer.write(entry.getValue());
193: writer.write("\r\n");
194: }
195: } finally {
196: writer.close();
197: }
198: }
199:
200: }
|