1 19 20 25 26 27 package soot.jimple.toolkits.typing; 28 29 import soot.*; 30 import soot.jimple.*; 31 import soot.util.*; 32 import java.util.*; 33 34 39 class ClassHierarchy 40 { 41 42 43 public final TypeNode OBJECT; 44 public final TypeNode CLONEABLE; 45 public final TypeNode SERIALIZABLE; 46 public final TypeNode NULL; 47 public final TypeNode INT; 48 51 52 private final Scene scene; 53 54 55 private final List typeNodeList = new ArrayList(); 56 57 58 private final HashMap typeNodeMap = new HashMap(); 59 60 61 private final ToInt transform = new ToInt(); 62 63 64 private final ConstructorChooser make = new ConstructorChooser(); 65 66 private ClassHierarchy(Scene scene) 67 { 68 if(scene == null) 69 { 70 throw new InternalTypingException(); 71 } 72 73 this.scene = scene; 74 G.v().ClassHierarchy_classHierarchyMap.put(scene, this); 75 76 NULL = typeNode(NullType.v()); 77 OBJECT = typeNode(RefType.v("java.lang.Object")); 78 79 if (!G.v().isJ2ME) { 82 CLONEABLE = typeNode(RefType.v("java.lang.Cloneable")); 83 SERIALIZABLE = typeNode(RefType.v("java.io.Serializable")); 84 } else { 85 CLONEABLE = null; 86 SERIALIZABLE = null; 87 } 88 89 INT = typeNode(IntType.v()); 90 } 91 92 93 public static ClassHierarchy classHierarchy(Scene scene) 94 { 95 if(scene == null) 96 { 97 throw new InternalTypingException(); 98 } 99 100 ClassHierarchy classHierarchy = 101 (ClassHierarchy) G.v().ClassHierarchy_classHierarchyMap.get(scene); 102 103 if(classHierarchy == null) 104 { 105 classHierarchy = new ClassHierarchy(scene); 106 } 107 108 return classHierarchy; 109 } 110 111 112 public TypeNode typeNode(Type type) 113 { 114 if(type == null) 115 { 116 throw new InternalTypingException(); 117 } 118 119 type = transform.toInt(type); 120 TypeNode typeNode = (TypeNode) typeNodeMap.get(type); 121 122 if(typeNode == null) 123 { 124 int id = typeNodeList.size(); 125 typeNodeList.add(null); 126 127 typeNode = make.typeNode(id, type, this); 128 129 typeNodeList.set(id, typeNode); 130 typeNodeMap.put(type, typeNode); 131 } 132 133 return typeNode; 134 } 135 136 137 public String toString () 138 { 139 StringBuffer s = new StringBuffer (); 140 boolean colon = false; 141 142 s.append("ClassHierarchy:{"); 143 for(Iterator i = typeNodeList.iterator(); i.hasNext();) 144 { 145 if(colon) 146 { 147 s.append(","); 148 } 149 else 150 { 151 colon = true; 152 } 153 154 s.append(i.next()); 155 } 156 s.append("}"); 157 158 return s.toString(); 159 } 160 161 164 private static class ToInt extends TypeSwitch 165 { 166 private Type result; 167 private final Type intType = IntType.v(); 168 169 private ToInt() 170 { 171 } 172 173 174 Type toInt(Type type) 175 { 176 type.apply(this); 177 return result; 178 } 179 180 public void caseBooleanType(BooleanType type) 181 { 182 result = intType; 183 } 184 185 public void caseByteType(ByteType type) 186 { 187 result = intType; 188 } 189 190 public void caseShortType(ShortType type) 191 { 192 result = intType; 193 } 194 195 public void caseCharType(CharType type) 196 { 197 result = intType; 198 } 199 200 public void defaultCase(Type type) 201 { 202 result = type; 203 } 204 } 205 206 209 private static class ConstructorChooser extends TypeSwitch 210 { 211 private int id; 212 private ClassHierarchy hierarchy; 213 214 private TypeNode result; 215 216 ConstructorChooser() 217 { 218 } 219 220 221 TypeNode typeNode(int id, Type type, ClassHierarchy hierarchy) 222 { 223 if(type == null || hierarchy == null) 224 { 225 throw new InternalTypingException(); 226 } 227 228 this.id = id; 229 this.hierarchy = hierarchy; 230 231 type.apply(this); 232 233 return result; 234 } 235 236 public void caseRefType(RefType type) 237 { 238 result = new TypeNode(id, type, hierarchy); 239 } 240 241 public void caseArrayType(ArrayType type) 242 { 243 result = new TypeNode(id, type, hierarchy); 244 } 245 246 public void defaultCase(Type type) 247 { 248 result = new TypeNode(id, type, hierarchy); 249 } 250 } 251 } 252 | Popular Tags |