KickJava   Java API By Example, From Geeks To Geeks.

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


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 net.sf.retrotranslator.runtime.asm.*;
35 import net.sf.retrotranslator.runtime.impl.BytecodeTransformer;
36
37 /**
38  * @author Taras Puchko
39  */

40 class ClassTransformer implements BytecodeTransformer {
41
42     private boolean lazy;
43     private boolean stripsign;
44     private boolean retainflags;
45     private EmbeddingConverter converter;
46     private SystemLogger logger;
47     private ReplacementLocatorFactory factory;
48
49     public ClassTransformer(boolean lazy, boolean stripsign, boolean retainflags, SystemLogger logger,
50                             EmbeddingConverter converter, ReplacementLocatorFactory factory) {
51         this.lazy = lazy;
52         this.stripsign = stripsign;
53         this.retainflags = retainflags;
54         this.converter = converter;
55         this.logger = logger;
56         this.factory = factory;
57     }
58
59     public byte[] transform(byte[] bytes, int offset, int length) {
60         if (lazy && !factory.getTarget().isBefore(TransformerTools.getClassVersion(bytes, offset))) {
61             if (offset == 0 && length == bytes.length) return bytes;
62             byte[] result = new byte[length];
63             System.arraycopy(bytes, offset, result, 0, length);
64             return result;
65         }
66         ClassWriter classWriter = new ClassWriter(true);
67         MethodCounter counter = new MethodCounter();
68         ClassVisitor visitor = new DuplicateInterfacesVisitor(
69                 new VersionVisitor(classWriter, factory.getTarget()), logger, counter);
70         boolean isTarget14 = factory.getTarget() == ClassVersion.VERSION_14;
71         if (isTarget14) {
72             visitor = new ArrayCloningVisitor(new ClassLiteralVisitor(visitor));
73         }
74         if (converter != null) {
75             visitor = new PrefixingVisitor(visitor, converter);
76         }
77         if (isTarget14 && !factory.isRetainapi()) {
78             visitor = new SpecificReplacementVisitor(visitor, factory.isAdvanced());
79         }
80         if (!factory.isEmpty()) {
81             visitor = new GeneralReplacementVisitor(new EnumVisitor(visitor), factory.getLocator());
82         }
83         if (stripsign) {
84             visitor = new SignatureStrippingVisitor(visitor);
85         }
86         new ClassReader(bytes, offset, length).accept(visitor, false);
87         if (counter.containsDuplicates()) {
88             byte[] bytecode = classWriter.toByteArray();
89             classWriter = new ClassWriter(true);
90             new ClassReader(bytecode).accept(new DuplicateMethodsVisitor(classWriter, logger, counter), false);
91         }
92         return classWriter.toByteArray(isTarget14 && !retainflags);
93     }
94
95 }
96
Popular Tags