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 net.sf.retrotranslator.runtime.asm.*;
034: import net.sf.retrotranslator.runtime.impl.EmptyVisitor;
035:
036: /**
037: * @author Taras Puchko
038: */
039: class InheritedConstantVisitor extends ClassAdapter {
040:
041: private final ReplacementLocator locator;
042:
043: public InheritedConstantVisitor(ClassVisitor visitor,
044: ReplacementLocator locator) {
045: super (visitor);
046: this .locator = locator;
047: }
048:
049: public MethodVisitor visitMethod(int access, String name,
050: String desc, String signature, String[] exceptions) {
051: MethodVisitor visitor = super .visitMethod(access, name, desc,
052: signature, exceptions);
053: return visitor == null ? null : new MethodAdapter(visitor) {
054: public void visitFieldInsn(int opcode, String owner,
055: String name, String desc) {
056: super .visitFieldInsn(opcode, fixFieldOwner(opcode,
057: owner, name), name, desc);
058: }
059: };
060: }
061:
062: private String fixFieldOwner(int opcode, String owner, String name) {
063: if (opcode == Opcodes.GETSTATIC) {
064: String fieldOwner = findFieldOwner(owner, name);
065: if (fieldOwner != null) {
066: return fieldOwner;
067: }
068: }
069: return owner;
070: }
071:
072: private String findFieldOwner(String className, String fieldName) {
073: String uniqueTypeName = locator.getUniqueTypeName(className);
074: ClassReader classReader = locator.getEnvironment()
075: .findClassReader(uniqueTypeName);
076: if (classReader == null) {
077: return null;
078: }
079: FieldSearchingVisitor visitor = new FieldSearchingVisitor(
080: fieldName);
081: classReader.accept(visitor, true);
082: if (visitor.fieldFound) {
083: return (visitor.access & Opcodes.ACC_INTERFACE) != 0 ? uniqueTypeName
084: : null;
085: }
086: if (visitor.interfaces != null) {
087: for (String interfaceName : visitor.interfaces) {
088: String result = findFieldOwner(interfaceName, fieldName);
089: if (result != null) {
090: return result;
091: }
092: }
093: }
094: return visitor.super Name != null ? findFieldOwner(
095: visitor.super Name, fieldName) : null;
096: }
097:
098: private class FieldSearchingVisitor extends EmptyVisitor {
099:
100: private final String fieldName;
101: public boolean fieldFound;
102: public int access;
103: public String super Name;
104: public String[] interfaces;
105:
106: public FieldSearchingVisitor(String fieldName) {
107: this .fieldName = fieldName;
108: }
109:
110: public void visit(int version, int access, String name,
111: String signature, String super Name, String[] interfaces) {
112: this .access = access;
113: this .super Name = super Name;
114: this .interfaces = interfaces;
115: }
116:
117: public FieldVisitor visitField(int access, String name,
118: String desc, String signature, Object value) {
119: if (name.equals(fieldName)
120: && (access & Opcodes.ACC_STATIC) != 0) {
121: fieldFound = true;
122: }
123: return null;
124: }
125: }
126:
127: }
|