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: import soot.util.*;
024:
025: /** Representation of a reference to a method as it appears in a class file.
026: * Note that the method directly referred to may not actually exist; the
027: * actual target of the reference is determined according to the resolution
028: * procedure in the Java Virtual Machine Specification, 2nd ed, section 5.4.3.3.
029: */
030:
031: class AbstractSootMethodRef implements SootMethodRef {
032: public AbstractSootMethodRef(SootClass declaringClass, String name,
033: List parameterTypes, Type returnType, boolean isStatic) {
034: this .declaringClass = declaringClass;
035: this .name = name;
036: List l = new ArrayList();
037: l.addAll(parameterTypes);
038: this .parameterTypes = Collections.unmodifiableList(l);
039: this .returnType = returnType;
040: this .isStatic = isStatic;
041: if (declaringClass == null)
042: throw new RuntimeException(
043: "Attempt to create SootMethodRef with null class");
044: if (name == null)
045: throw new RuntimeException(
046: "Attempt to create SootMethodRef with null name");
047: if (parameterTypes == null)
048: throw new RuntimeException(
049: "Attempt to create SootMethodRef with null parameterTypes");
050: if (returnType == null)
051: throw new RuntimeException(
052: "Attempt to create SootMethodRef with null returnType");
053: }
054:
055: private final SootClass declaringClass;
056: private final String name;
057: private final List parameterTypes;
058: private final Type returnType;
059: private final boolean isStatic;
060:
061: private NumberedString subsig;
062:
063: public SootClass declaringClass() {
064: return declaringClass;
065: }
066:
067: public String name() {
068: return name;
069: }
070:
071: public List parameterTypes() {
072: return parameterTypes;
073: }
074:
075: public Type returnType() {
076: return returnType;
077: }
078:
079: public boolean isStatic() {
080: return isStatic;
081: }
082:
083: public NumberedString getSubSignature() {
084: if (subsig == null) {
085: subsig = Scene.v().getSubSigNumberer().findOrAdd(
086: SootMethod.getSubSignature(name, parameterTypes,
087: returnType));
088: }
089: return subsig;
090: }
091:
092: public String getSignature() {
093: return SootMethod.getSignature(declaringClass, name,
094: parameterTypes, returnType);
095: }
096:
097: public Type parameterType(int i) {
098: return (Type) parameterTypes.get(i);
099: }
100:
101: public class ClassResolutionFailedException extends
102: ResolutionFailedException {
103: public ClassResolutionFailedException() {
104: super (
105: "Class "
106: + declaringClass
107: + " doesn't have method "
108: + name
109: + "("
110: + parameterTypes
111: + ")"
112: + " : "
113: + returnType
114: + "; failed to resolve in superclasses and interfaces");
115: }
116:
117: public String toString() {
118: StringBuffer ret = new StringBuffer();
119: ret.append(super .toString());
120: resolve(ret);
121: return ret.toString();
122: }
123: }
124:
125: public SootMethod resolve() {
126: return resolve(null);
127: }
128:
129: private SootMethod checkStatic(SootMethod ret) {
130: if (ret.isStatic() != isStatic()) {
131: throw new ResolutionFailedException("Resolved " + this
132: + " to " + ret + " which has wrong static-ness");
133: }
134: return ret;
135: }
136:
137: private SootMethod resolve(StringBuffer trace) {
138: SootClass cl = declaringClass;
139: while (true) {
140: if (trace != null)
141: trace.append("Looking in " + cl + " which has methods "
142: + cl.getMethods() + "\n");
143: if (cl.declaresMethod(getSubSignature()))
144: return checkStatic(cl.getMethod(getSubSignature()));
145: if (Scene.v().allowsPhantomRefs() && cl.isPhantom()) {
146: SootMethod m = new SootMethod(name, parameterTypes,
147: returnType, isStatic() ? Modifier.STATIC : 0);
148: m.setPhantom(true);
149: cl.addMethod(m);
150: return checkStatic(m);
151: }
152: if (cl.hasSuperclass())
153: cl = cl.getSuperclass();
154: else
155: break;
156: }
157: cl = declaringClass;
158: while (true) {
159: LinkedList<SootClass> queue = new LinkedList<SootClass>();
160: queue.addAll(cl.getInterfaces());
161: while (!queue.isEmpty()) {
162: SootClass iface = queue.removeFirst();
163: if (trace != null)
164: trace.append("Looking in " + iface
165: + " which has methods "
166: + iface.getMethods() + "\n");
167: if (iface.declaresMethod(getSubSignature()))
168: return checkStatic(iface
169: .getMethod(getSubSignature()));
170: queue.addAll(iface.getInterfaces());
171: }
172: if (cl.hasSuperclass())
173: cl = cl.getSuperclass();
174: else
175: break;
176: }
177: if (trace == null)
178: throw new ClassResolutionFailedException();
179: return null;
180: }
181:
182: public String toString() {
183: return getSignature();
184: }
185: }
|