1 19 20 package jode.type; 21 import jode.bytecode.ClassInfo; 22 import java.util.Vector ; 23 import java.util.Stack ; 24 import java.util.Hashtable ; 25 26 38 public class ClassInterfacesType extends ReferenceType { 39 40 ClassInfo clazz; 41 ClassInfo ifaces[]; 42 43 public ClassInfo getClazz() { 44 return clazz != null ? clazz : ClassInfo.javaLangObject; 45 } 46 47 public ClassInterfacesType(String clazzName) { 48 super(TC_CLASS); 49 ClassInfo clazz = ClassInfo.forName(clazzName); 50 if (clazz.isInterface()) { 51 this.clazz = null; 52 ifaces = new ClassInfo[] {clazz}; 53 } else { 54 this.clazz = 55 (clazz == ClassInfo.javaLangObject) ? null : clazz; 56 ifaces = new ClassInfo[0]; 57 } 58 } 59 60 public ClassInterfacesType(ClassInfo clazz) { 61 super(TC_CLASS); 62 if (clazz.isInterface()) { 63 this.clazz = null; 64 ifaces = new ClassInfo[] { clazz }; 65 } else { 66 this.clazz = 67 (clazz == ClassInfo.javaLangObject) ? null : clazz; 68 ifaces = new ClassInfo[0]; 69 } 70 } 71 72 public ClassInterfacesType(ClassInfo clazz, ClassInfo[] ifaces) { 73 super(TC_CLASS); 74 this.clazz = clazz; 75 this.ifaces = ifaces; 76 } 77 78 static ClassInterfacesType create(ClassInfo clazz, ClassInfo[] ifaces) { 79 80 if (ifaces.length == 0 && clazz == null) 81 return tObject; 82 if (ifaces.length == 0) 83 return tClass(clazz); 84 if (ifaces.length == 1 && clazz == null) 85 return tClass(ifaces[0]); 86 return new ClassInterfacesType(clazz, ifaces); 87 } 88 89 public Type getSubType() { 90 if ((clazz == null && ifaces.length == 1) 91 || ifaces.length == 0) 92 return tRange(this, tNull); 93 94 97 throw new jode.AssertError 98 ("getSubType called on set of classes and interfaces!"); 99 } 100 101 public Type getHint() { 102 if (ifaces.length == 0 103 || (clazz == null && ifaces.length == 1)) 104 return this; 105 if (clazz != null) 106 return Type.tClass(clazz.getName()); 107 else 108 return Type.tClass(ifaces[0].getName()); 109 } 110 111 public Type getCanonic() { 112 if (ifaces.length == 0 113 || (clazz == null && ifaces.length == 1)) 114 return this; 115 if (clazz != null) 116 return Type.tClass(clazz.getName()); 117 else 118 return Type.tClass(ifaces[0].getName()); 119 } 120 121 130 public Type createRangeType(ReferenceType bottomType) { 131 if (bottomType.typecode != TC_CLASS) 132 return tError; 133 134 ClassInterfacesType bottom = (ClassInterfacesType) bottomType; 135 136 if (bottomType == tObject) 137 return (this == tObject) ? tObject : tRange(tObject, this); 138 139 if (bottom.clazz != null) { 140 142 if (!bottom.clazz.superClassOf(this.clazz)) 143 return tError; 144 145 147 for (int i=0; i < bottom.ifaces.length; i++) { 148 if (!bottom.ifaces[i].implementedBy(this.clazz)) 149 return tError; 150 } 151 152 if (bottom.clazz == this.clazz 153 && bottom.ifaces.length == 0) 154 return bottom; 155 156 if (this.ifaces.length != 0) 157 return tRange(bottom, create(this.clazz, new ClassInfo[0])); 158 return tRange(bottom, this); 159 160 } else { 161 162 165 166 ClassInfo clazz = this.clazz; 167 if (clazz != null) { 168 for (int i=0; i < bottom.ifaces.length; i++) { 169 if (!bottom.ifaces[i].implementedBy(clazz)) { 170 clazz = null; 171 break; 172 } 173 } 174 } 175 176 179 if (clazz == null && bottom.ifaces.length == 1) { 180 for (int i=0; i< this.ifaces.length; i++) { 181 if (this.ifaces[i] == bottom.ifaces[0]) 182 return bottom; 183 } 184 } 185 186 ClassInfo[] ifaces = new ClassInfo[this.ifaces.length]; 187 int count = 0; 188 big_loop: 189 for (int j=0; j < this.ifaces.length; j++) { 190 for (int i=0; i < bottom.ifaces.length; i++) { 191 if (!bottom.ifaces[i].implementedBy(this.ifaces[j])) 192 continue big_loop; 193 } 194 ifaces[count++] = (this.ifaces[j]); 195 } 196 197 if (clazz == null && count == 0) { 198 201 return tError; 202 } else if (count < ifaces.length) { 203 ClassInfo[] shortIfaces = new ClassInfo[count]; 204 System.arraycopy(ifaces, 0, shortIfaces, 0, count); 205 ifaces = shortIfaces; 206 } else if (clazz == this.clazz) 207 return tRange(bottom, this); 208 return tRange(bottom, create(clazz, ifaces)); 209 } 210 } 211 212 218 public Type getSpecializedType(Type type) { 219 int code = type.typecode; 220 if (code == TC_RANGE) { 221 type = ((RangeType) type).getBottom(); 222 code = type.typecode; 223 } 224 if (code == TC_NULL) 225 return this; 226 if (code == TC_ARRAY) 227 return ((ArrayType) type).getSpecializedType(this); 228 if (code != TC_CLASS) 229 return tError; 230 231 ClassInterfacesType other = (ClassInterfacesType) type; 232 ClassInfo clazz; 233 234 237 238 if (this.clazz == null) 239 clazz = other.clazz; 240 else if (other.clazz == null) 241 clazz = this.clazz; 242 else if (this.clazz.superClassOf(other.clazz)) 243 clazz = other.clazz; 244 else if (other.clazz.superClassOf(this.clazz)) 245 clazz = this.clazz; 246 else 247 return tError; 248 249 253 if (clazz == this.clazz 254 && implementsAllIfaces(this.clazz, this.ifaces, other.ifaces)) 255 return this; 256 else if (clazz == other.clazz 257 && implementsAllIfaces(other.clazz, other.ifaces, 258 this.ifaces)) 259 return other; 260 261 265 Vector ifaces = new Vector (); 266 big_loop_this: 267 for (int i=0; i< this.ifaces.length; i++) { 268 ClassInfo iface = this.ifaces[i]; 269 if (clazz != null && iface.implementedBy(clazz)) { 270 continue big_loop_this; 271 } 272 for (int j=0; j<other.ifaces.length; j++) { 273 if (iface.implementedBy(other.ifaces[j])) { 274 continue big_loop_this; 275 } 276 } 277 278 281 ifaces.addElement(iface); 282 } 283 big_loop_other: 284 for (int i=0; i< other.ifaces.length; i++) { 285 ClassInfo iface = other.ifaces[i]; 286 if (clazz != null && iface.implementedBy(clazz)) { 287 continue big_loop_other; 288 } 289 for (int j=0; j<ifaces.size(); j++) { 290 if (iface.implementedBy((ClassInfo) 291 ifaces.elementAt(j))) { 292 continue big_loop_other; 293 } 294 } 295 296 299 ifaces.addElement(iface); 300 } 301 302 ClassInfo[] ifaceArray = new ClassInfo[ifaces.size()]; 303 ifaces.copyInto(ifaceArray); 304 return create(clazz, ifaceArray); 305 } 306 307 313 public Type getGeneralizedType(Type type) { 314 int code = type.typecode; 315 if (code == TC_RANGE) { 316 type = ((RangeType) type).getTop(); 317 code = type.typecode; 318 } 319 if (code == TC_NULL) 320 return this; 321 if (code == TC_ARRAY) 322 return ((ArrayType) type).getGeneralizedType(this); 323 if (code != TC_CLASS) 324 return tError; 325 ClassInterfacesType other = (ClassInterfacesType) type; 326 ClassInfo clazz; 327 328 329 if (this.clazz == null || other.clazz == null) 330 clazz = null; 331 else { 332 clazz = this.clazz; 333 334 while(clazz != null) { 335 if (clazz.superClassOf(other.clazz)) 336 break; 337 clazz = clazz.getSuperclass(); 338 } 339 if (clazz == ClassInfo.javaLangObject) 340 clazz = null; 341 } 342 343 if (clazz == this.clazz 344 && implementsAllIfaces(other.clazz, other.ifaces, this.ifaces)) 345 return this; 346 else if (clazz == other.clazz 347 && implementsAllIfaces(this.clazz, this.ifaces, other.ifaces)) 348 return other; 349 350 355 356 Stack allIfaces = new Stack (); 357 if (this.clazz != null) { 358 ClassInfo c = this.clazz; 359 while (clazz != c) { 360 ClassInfo clazzIfaces[] = c.getInterfaces(); 361 for (int i=0; i<clazzIfaces.length; i++) 362 allIfaces.push(clazzIfaces[i]); 363 c = c.getSuperclass(); 364 } 365 } 366 367 Vector ifaces = new Vector (); 368 369 for (int i=0; i<this.ifaces.length; i++) 370 allIfaces.push(this.ifaces[i]); 371 372 376 iface_loop: 377 while (!allIfaces.isEmpty()) { 378 ClassInfo iface = (ClassInfo) allIfaces.pop(); 379 if ((clazz != null && iface.implementedBy(clazz)) 380 || ifaces.contains(iface)) 381 383 continue iface_loop; 384 385 if (other.clazz != null && iface.implementedBy(other.clazz)) { 386 ifaces.addElement(iface); 387 continue iface_loop; 388 } 389 for (int i=0; i<other.ifaces.length; i++) { 390 if (iface.implementedBy(other.ifaces[i])) { 391 ifaces.addElement(iface); 392 continue iface_loop; 393 } 394 } 395 396 399 ClassInfo clazzIfaces[] = iface.getInterfaces(); 400 for (int i=0; i<clazzIfaces.length; i++) 401 allIfaces.push(clazzIfaces[i]); 402 } 403 404 ClassInfo[] ifaceArray = new ClassInfo[ifaces.size()]; 405 ifaces.copyInto(ifaceArray); 406 return create(clazz, ifaceArray); 407 } 408 409 public String getTypeSignature() { 410 if (clazz != null) 411 return "L" + clazz.getName().replace('.','/') + ";"; 412 else if (ifaces.length > 0) 413 return "L" + ifaces[0].getName().replace('.','/') + ";"; 414 else 415 return "Ljava/lang/Object;"; 416 } 417 418 public Class getTypeClass() throws ClassNotFoundException { 419 if (clazz != null) 420 return Class.forName(clazz.getName()); 421 else if (ifaces.length > 0) 422 return Class.forName(ifaces[0].getName()); 423 else 424 return Class.forName("java.lang.Object"); 425 } 426 427 public ClassInfo getClassInfo() { 428 if (clazz != null) 429 return clazz; 430 else if (ifaces.length > 0) 431 return ifaces[0]; 432 else 433 return ClassInfo.javaLangObject; 434 } 435 436 public String toString() 437 { 438 if (this == tObject) 439 return "java.lang.Object"; 440 441 if (ifaces.length == 0) 442 return clazz.getName(); 443 if (clazz == null && ifaces.length == 1) 444 return ifaces[0].getName(); 445 446 StringBuffer sb = new StringBuffer ("{"); 447 String comma = ""; 448 if (clazz != null) { 449 sb = sb.append(clazz.getName()); 450 comma = ", "; 451 } 452 for (int i=0; i< ifaces.length; i++) { 453 sb.append(comma).append(ifaces[i].getName()); 454 comma = ", "; 455 } 456 return sb.append("}").toString(); 457 } 458 459 464 public Type getCastHelper(Type fromType) { 465 Type hintType = fromType.getHint(); 466 switch (hintType.getTypeCode()) { 467 case TC_ARRAY: 468 if (clazz == null 469 && implementsAllIfaces(null, ArrayType.arrayIfaces, 470 this.ifaces)) 471 return null; 472 else 473 return tObject; 474 case TC_CLASS: 475 ClassInterfacesType hint = (ClassInterfacesType) hintType; 476 if (hint.clazz == null || clazz == null 477 || clazz.superClassOf(hint.clazz) 478 || hint.clazz.superClassOf(clazz)) 479 return null; 480 ClassInfo superClazz = clazz.getSuperclass(); 481 while (superClazz != null 482 && !superClazz.superClassOf(hint.clazz)) { 483 superClazz = superClazz.getSuperclass(); 484 } 485 return tClass(superClazz.getName()); 486 case TC_UNKNOWN: 487 return null; 488 } 489 return tObject; 490 } 491 492 496 public boolean isValidType() { 497 return ifaces.length == 0 498 || (clazz == null && ifaces.length == 1); 499 } 500 501 506 public boolean isClassType() { 507 return true; 508 } 509 510 private final static Hashtable keywords = new Hashtable (); 511 static { 512 keywords.put("abstract", Boolean.TRUE); 513 keywords.put("default", Boolean.TRUE); 514 keywords.put("if", Boolean.TRUE); 515 keywords.put("private", Boolean.TRUE); 516 keywords.put("throw", Boolean.TRUE); 517 keywords.put("boolean", Boolean.TRUE); 518 keywords.put("do", Boolean.TRUE); 519 keywords.put("implements", Boolean.TRUE); 520 keywords.put("protected", Boolean.TRUE); 521 keywords.put("throws", Boolean.TRUE); 522 keywords.put("break", Boolean.TRUE); 523 keywords.put("double", Boolean.TRUE); 524 keywords.put("import", Boolean.TRUE); 525 keywords.put("public", Boolean.TRUE); 526 keywords.put("transient", Boolean.TRUE); 527 keywords.put("byte", Boolean.TRUE); 528 keywords.put("else", Boolean.TRUE); 529 keywords.put("instanceof", Boolean.TRUE); 530 keywords.put("return", Boolean.TRUE); 531 keywords.put("try", Boolean.TRUE); 532 keywords.put("case", Boolean.TRUE); 533 keywords.put("extends", Boolean.TRUE); 534 keywords.put("int", Boolean.TRUE); 535 keywords.put("short", Boolean.TRUE); 536 keywords.put("void", Boolean.TRUE); 537 keywords.put("catch", Boolean.TRUE); 538 keywords.put("final", Boolean.TRUE); 539 keywords.put("interface", Boolean.TRUE); 540 keywords.put("static", Boolean.TRUE); 541 keywords.put("volatile", Boolean.TRUE); 542 keywords.put("char", Boolean.TRUE); 543 keywords.put("finally", Boolean.TRUE); 544 keywords.put("long", Boolean.TRUE); 545 keywords.put("super", Boolean.TRUE); 546 keywords.put("while", Boolean.TRUE); 547 keywords.put("class", Boolean.TRUE); 548 keywords.put("float", Boolean.TRUE); 549 keywords.put("native", Boolean.TRUE); 550 keywords.put("switch", Boolean.TRUE); 551 keywords.put("const", Boolean.TRUE); 552 keywords.put("for", Boolean.TRUE); 553 keywords.put("new", Boolean.TRUE); 554 keywords.put("synchronized", Boolean.TRUE); 555 keywords.put("continue", Boolean.TRUE); 556 keywords.put("goto", Boolean.TRUE); 557 keywords.put("package", Boolean.TRUE); 558 keywords.put("this", Boolean.TRUE); 559 keywords.put("strictfp", Boolean.TRUE); 560 keywords.put("null", Boolean.TRUE); 561 keywords.put("true", Boolean.TRUE); 562 keywords.put("false", Boolean.TRUE); 563 } 564 565 570 public String getDefaultName() { 571 ClassInfo type; 572 if (clazz != null) 573 type = clazz; 574 else if (ifaces.length > 0) 575 type = ifaces[0]; 576 else 577 type = ClassInfo.javaLangObject; 578 String name = type.getName(); 579 int dot = Math.max(name.lastIndexOf('.'), name.lastIndexOf('$')); 580 if (dot >= 0) 581 name = name.substring(dot+1); 582 if (Character.isUpperCase(name.charAt(0))) { 583 name = name.toLowerCase(); 584 if (keywords.get(name) != null) 585 return "var_" + name; 586 return name; 587 } else 588 return "var_" + name; 589 } 590 591 public int hashCode() { 592 int hash = clazz == null ? 0 : clazz.hashCode(); 593 for (int i=0; i < ifaces.length; i++) { 594 hash ^= ifaces[i].hashCode(); 595 } 596 return hash; 597 } 598 599 public boolean equals(Object o) { 600 if (o == this) 601 return true; 602 if (o instanceof Type && ((Type)o).typecode == TC_CLASS) { 603 ClassInterfacesType type = (ClassInterfacesType) o; 604 if (type.clazz == clazz 605 && type.ifaces.length == ifaces.length) { 606 big_loop: 607 for (int i=0; i< type.ifaces.length; i++) { 608 for (int j=0; j<ifaces.length; j++) { 609 if (type.ifaces[i] == ifaces[j]) 610 continue big_loop; 611 } 612 return false; 613 } 614 return true; 615 } 616 } 617 return false; 618 } 619 } 620 | Popular Tags |