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.transformer;
032:
033: import java.util.*;
034: import net.sf.retrotranslator.runtime.asm.*;
035: import static net.sf.retrotranslator.runtime.asm.Opcodes.*;
036: import static net.sf.retrotranslator.runtime.impl.RuntimeTools.CONSTRUCTOR_NAME;
037:
038: /**
039: * @author Taras Puchko
040: */
041: class InstantiationReplacementVisitor extends ClassAdapter {
042:
043: private final Map<String, List<InstantiationPoint>> pointListMap;
044:
045: public InstantiationReplacementVisitor(ClassVisitor visitor,
046: Map<String, List<InstantiationPoint>> pointListMap) {
047: super (visitor);
048: this .pointListMap = pointListMap;
049: }
050:
051: public MethodVisitor visitMethod(final int access,
052: final String name, final String desc,
053: final String signature, final String[] exceptions) {
054: List<InstantiationPoint> points = pointListMap.get(name + desc);
055: MethodVisitor visitor = super .visitMethod(access, name, desc,
056: signature, exceptions);
057: return visitor == null || points == null ? visitor
058: : new InstantiationReplacementMethodVisitor(visitor,
059: points);
060: }
061:
062: private static class InstantiationReplacementMethodVisitor extends
063: MethodAdapter {
064:
065: private final List<InstantiationPoint> points;
066: private int allocationIndex;
067: private int duplicationIndex;
068: private int initializationIndex;
069:
070: public InstantiationReplacementMethodVisitor(MethodVisitor mv,
071: List<InstantiationPoint> points) {
072: super (mv);
073: this .points = points;
074: }
075:
076: public void visitTypeInsn(int opcode, String desc) {
077: if (opcode == NEW) {
078: int index = ++allocationIndex;
079: for (InstantiationPoint point : points) {
080: if (point.getAllocationIndex() == index) {
081: return;
082: }
083: }
084: }
085: super .visitTypeInsn(opcode, desc);
086: }
087:
088: public void visitInsn(int opcode) {
089: if (opcode == DUP) {
090: int index = ++duplicationIndex;
091: for (InstantiationPoint point : points) {
092: if (point.getDuplicationIndex() == index) {
093: return;
094: }
095: }
096: }
097: super .visitInsn(opcode);
098: }
099:
100: public void visitMethodInsn(int opcode, String owner,
101: String name, String desc) {
102: if (opcode == INVOKESPECIAL
103: && name.equals(CONSTRUCTOR_NAME)) {
104: int index = ++initializationIndex;
105: for (InstantiationPoint point : points) {
106: if (point.getInitializationIndex() == index) {
107: if (!owner.equals(point.getInternalName())) {
108: throw new IllegalStateException();
109: }
110: MemberReplacement replacement = point
111: .getReplacement();
112: mv.visitMethodInsn(INVOKESTATIC, replacement
113: .getOwner(), replacement.getName(),
114: replacement.getDesc());
115: return;
116: }
117: }
118: }
119: super.visitMethodInsn(opcode, owner, name, desc);
120: }
121: }
122:
123: }
|