001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1997-1999 Raja Vallee-Rai
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: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: package soot;
027:
028: import soot.util.*;
029: import java.util.*;
030:
031: /**
032: * A class that models Java's reference types. RefTypes are parametrized by a class name.
033: * Two RefType are equal iff they are parametrized by the same class name as a String.
034: */
035:
036: public class RefType extends RefLikeType implements Comparable {
037: public RefType(Singletons.Global g) {
038: className = "";
039: }
040:
041: public static RefType v() {
042: return G.v().soot_RefType();
043: }
044:
045: /** the class name that parametrizes this RefType */
046: private String className;
047:
048: public String getClassName() {
049: return className;
050: }
051:
052: private SootClass sootClass;
053: private AnySubType anySubType;
054:
055: private RefType(String className) {
056: if (className.startsWith("["))
057: throw new RuntimeException(
058: "Attempt to create RefType whose name starts with [ --> "
059: + className);
060: if (className.indexOf("/") >= 0)
061: throw new RuntimeException(
062: "Attempt to create RefType containing a / --> "
063: + className);
064: if (className.indexOf(";") >= 0)
065: throw new RuntimeException(
066: "Attempt to create RefType containing a ; --> "
067: + className);
068: this .className = className;
069: }
070:
071: /**
072: * Create a RefType for a class.
073: * @param className The name of the class used to parametrize the created RefType.
074: * @return a RefType for the given class name.
075: */
076: public static RefType v(String className) {
077: RefType ret = Scene.v().getRefType(className);
078: if (ret == null) {
079: ret = new RefType(className);
080: Scene.v().addRefType(ret);
081: }
082: return ret;
083: }
084:
085: public int compareTo(Object o) throws ClassCastException {
086: RefType t = (RefType) o;
087: return this .toString().compareTo(t.toString());
088: }
089:
090: /**
091: * Create a RefType for a class.
092: * @param c A SootClass for which to create a RefType.
093: * @return a RefType for the given SootClass..
094: */
095: public static RefType v(SootClass c) {
096: return v(c.getName());
097: }
098:
099: /**
100: * Get the SootClass object corresponding to this RefType.
101: * @return the corresponding SootClass
102: */
103: public SootClass getSootClass() {
104: if (sootClass == null) {
105: //System.out.println( "wrning: "+this+" has no sootclass" );
106: sootClass = SootResolver.v().makeClassRef(className);
107: }
108: return sootClass;
109: }
110:
111: public boolean hasSootClass() {
112: return sootClass != null;
113: }
114:
115: public void setClassName(String className) {
116: this .className = className;
117: }
118:
119: /**
120: * Set the SootClass object corresponding to this RefType.
121: * @param sootClass The SootClass corresponding to this RefType.
122: */
123: public void setSootClass(SootClass sootClass) {
124: this .sootClass = sootClass;
125: }
126:
127: /**
128: * 2 RefTypes are considered equal if they are parametrized by the same class name String.
129: * @param t an object to test for equality.
130: * @ return true if t is a RefType parametrized by the same name as this.
131: */
132: public boolean equals(Object t) {
133: return ((t instanceof RefType) && className
134: .equals(((RefType) t).className));
135: }
136:
137: public String toString() {
138: return className;
139: }
140:
141: public int hashCode() {
142: return className.hashCode();
143: }
144:
145: public void apply(Switch sw) {
146: ((TypeSwitch) sw).caseRefType(this );
147: }
148:
149: /** Returns the least common superclass of this type and other. */
150: public Type merge(Type other, Scene cm) {
151: if (other.equals(UnknownType.v()) || this .equals(other))
152: return this ;
153:
154: if (!(other instanceof RefType))
155: throw new RuntimeException("illegal type merge: " + this
156: + " and " + other);
157:
158: {
159: // Return least common superclass
160:
161: SootClass this Class = cm.getSootClass((this ).className);
162: SootClass otherClass = cm
163: .getSootClass(((RefType) other).className);
164: SootClass javalangObject = cm
165: .getSootClass("java.lang.Object");
166:
167: LinkedList<SootClass> this Hierarchy = new LinkedList<SootClass>();
168: LinkedList<SootClass> otherHierarchy = new LinkedList<SootClass>();
169:
170: // Build thisHierarchy
171: {
172: SootClass SootClass = this Class;
173:
174: for (;;) {
175: this Hierarchy.addFirst(SootClass);
176:
177: if (SootClass == javalangObject)
178: break;
179:
180: SootClass = SootClass.getSuperclass();
181: }
182: }
183:
184: // Build otherHierarchy
185: {
186: SootClass SootClass = otherClass;
187:
188: for (;;) {
189: otherHierarchy.addFirst(SootClass);
190:
191: if (SootClass == javalangObject)
192: break;
193:
194: SootClass = SootClass.getSuperclass();
195: }
196: }
197:
198: // Find least common superclass
199: {
200: SootClass commonClass = null;
201:
202: while (!otherHierarchy.isEmpty()
203: && !this Hierarchy.isEmpty()
204: && otherHierarchy.getFirst() == this Hierarchy
205: .getFirst()) {
206: commonClass = otherHierarchy.removeFirst();
207: this Hierarchy.removeFirst();
208: }
209:
210: return RefType.v(commonClass.getName());
211: }
212: }
213:
214: }
215:
216: public Type getArrayElementType() {
217: if (className.equals("java.lang.Object")
218: || className.equals("java.io.Serializable")
219: || className.equals("java.lang.Cloneable")) {
220: return RefType.v("java.lang.Object");
221: }
222: throw new RuntimeException(
223: "Attempt to get array base type of a non-array");
224:
225: }
226:
227: public AnySubType getAnySubType() {
228: return anySubType;
229: }
230:
231: public void setAnySubType(AnySubType anySubType) {
232: this.anySubType = anySubType;
233: }
234: }
|