001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2004 Ondrej Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot;
021:
022: import java.util.*;
023:
024: /** Representation of a reference to a field as it appears in a class file.
025: * Note that the field directly referred to may not actually exist; the
026: * actual target of the reference is determined according to the resolution
027: * procedure in the Java Virtual Machine Specification, 2nd ed, section 5.4.3.2.
028: */
029:
030: class AbstractSootFieldRef implements SootFieldRef {
031: public AbstractSootFieldRef(SootClass declaringClass, String name,
032: Type type, boolean isStatic) {
033: this .declaringClass = declaringClass;
034: this .name = name;
035: this .type = type;
036: this .isStatic = isStatic;
037: if (declaringClass == null)
038: throw new RuntimeException(
039: "Attempt to create SootFieldRef with null class");
040: if (name == null)
041: throw new RuntimeException(
042: "Attempt to create SootFieldRef with null name");
043: if (type == null)
044: throw new RuntimeException(
045: "Attempt to create SootFieldRef with null type");
046: }
047:
048: private final SootClass declaringClass;
049: private final String name;
050: private final Type type;
051: private final boolean isStatic;
052:
053: public SootClass declaringClass() {
054: return declaringClass;
055: }
056:
057: public String name() {
058: return name;
059: }
060:
061: public Type type() {
062: return type;
063: }
064:
065: public boolean isStatic() {
066: return isStatic;
067: }
068:
069: public String getSignature() {
070: return SootField.getSignature(declaringClass, name, type);
071: }
072:
073: public class FieldResolutionFailedException extends
074: ResolutionFailedException {
075: public FieldResolutionFailedException() {
076: super (
077: "Class "
078: + declaringClass
079: + " doesn't have field "
080: + name
081: + " : "
082: + type
083: + "; failed to resolve in superclasses and interfaces");
084: }
085:
086: public String toString() {
087: StringBuffer ret = new StringBuffer();
088: ret.append(super .toString());
089: resolve(ret);
090: return ret.toString();
091: }
092: }
093:
094: public SootField resolve() {
095: return resolve(null);
096: }
097:
098: private SootField checkStatic(SootField ret) {
099: if (ret.isStatic() != isStatic()) {
100: throw new ResolutionFailedException("Resolved " + this
101: + " to " + ret + " which has wrong static-ness");
102: }
103: return ret;
104: }
105:
106: private SootField resolve(StringBuffer trace) {
107: SootClass cl = declaringClass;
108: while (true) {
109: if (trace != null)
110: trace.append("Looking in " + cl + " which has fields "
111: + cl.getFields() + "\n");
112: if (cl.declaresField(name, type)) {
113: return checkStatic(cl.getField(name, type));
114: }
115:
116: if (Scene.v().allowsPhantomRefs() && cl.isPhantom()) {
117: SootField f = new SootField(name, type,
118: isStatic() ? Modifier.STATIC : 0);
119: f.setPhantom(true);
120: cl.addField(f);
121: return f;
122: } else {
123: LinkedList<SootClass> queue = new LinkedList<SootClass>();
124: queue.addAll(cl.getInterfaces());
125: while (!queue.isEmpty()) {
126: SootClass iface = queue.removeFirst();
127: if (trace != null)
128: trace.append("Looking in " + iface
129: + " which has fields "
130: + iface.getFields() + "\n");
131: if (iface.declaresField(name, type)) {
132: return checkStatic(iface.getField(name, type));
133: }
134: queue.addAll(iface.getInterfaces());
135: }
136: if (cl.hasSuperclass())
137: cl = cl.getSuperclass();
138: else
139: break;
140: }
141: }
142: if (trace == null)
143: throw new FieldResolutionFailedException();
144: return null;
145: }
146:
147: public String toString() {
148: return getSignature();
149: }
150: }
|