1 19 20 package jode.obfuscator; 21 import jode.GlobalOptions; 22 import jode.bytecode.*; 23 import jode.obfuscator.modules.ModifierMatcher; 24 import java.util.Comparator ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.ArrayList ; 28 import java.util.Arrays ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.LinkedList ; 32 import java.util.Map ; 33 import java.lang.UnsupportedOperationException ; 34 35 import java.lang.reflect.Modifier ; 36 import java.security.MessageDigest ; 37 import java.security.NoSuchAlgorithmException ; 38 import java.io.OutputStream ; 39 import java.io.DataOutputStream ; 40 import java.io.IOException ; 41 42 public class ClassIdentifier extends Identifier { 43 PackageIdentifier pack; 44 String name; 45 String fullName; 46 ClassInfo info; 47 String superName; 48 String [] ifaceNames; 49 50 List fieldIdents, methodIdents; 51 List knownSubClasses = new LinkedList (); 52 List virtualReachables = new LinkedList (); 53 54 public ClassIdentifier(PackageIdentifier pack, String fullName, 55 String name, ClassInfo info) { 56 super(name); 57 this.pack = pack; 58 this.fullName = fullName; 59 this.name = name; 60 this.info = info; 61 } 62 63 public void addSubClass(ClassIdentifier ci) { 64 knownSubClasses.add(ci); 65 for(Iterator i = virtualReachables.iterator(); i.hasNext(); ) 66 ci.reachableReference((Reference) i.next(), true); 67 } 68 69 private FieldIdentifier findField(String name, String typeSig) { 70 for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) { 71 FieldIdentifier ident = (FieldIdentifier) i.next(); 72 if (ident.getName().equals(name) 73 && ident.getType().equals(typeSig)) 74 return ident; 75 } 76 return null; 77 } 78 79 private MethodIdentifier findMethod(String name, String typeSig) { 80 for (Iterator i = methodIdents.iterator(); i.hasNext(); ) { 81 MethodIdentifier ident = (MethodIdentifier) i.next(); 82 if (ident.getName().equals(name) 83 && ident.getType().equals(typeSig)) 84 return ident; 85 } 86 return null; 87 } 88 89 public void reachableReference(Reference ref, boolean isVirtual) { 90 boolean found = false; 91 for (Iterator i = getChilds(); i.hasNext(); ) { 92 Identifier ident = (Identifier) i.next(); 93 if (ref.getName().equals(ident.getName()) 94 && ref.getType().equals(ident.getType())) { 95 ident.setReachable(); 96 found = true; 97 } 98 } 99 if (!found) { 100 ClassIdentifier superIdent = Main.getClassBundle() 108 .getClassIdentifier(info.getSuperclass().getName()); 109 if (superIdent != null) 110 superIdent.reachableReference(ref, false); 111 } 112 113 if (isVirtual) { 114 for(Iterator i = virtualReachables.iterator(); i.hasNext(); ) { 115 Reference prevRef = (Reference) i.next(); 116 if (prevRef.getName().equals(ref.getName()) 117 && prevRef.getType().equals(ref.getType())) 118 return; 120 } 121 for (Iterator i = knownSubClasses.iterator(); i.hasNext(); ) 122 ((ClassIdentifier)i.next()) 123 .reachableReference(ref, false); 124 virtualReachables.add(ref); 125 } 126 } 127 128 public void chainMethodIdentifier(Identifier chainIdent) { 129 String name = chainIdent.getName(); 130 String typeSig = chainIdent.getType(); 131 for (Iterator i = methodIdents.iterator(); i.hasNext(); ) { 132 Identifier ident = (Identifier) i.next(); 133 if (ident.getName().equals(name) 134 && ident.getType().equals(typeSig)) 135 chainIdent.addShadow(ident); 136 } 137 } 138 139 142 public long calcSerialVersionUID() { 143 final MessageDigest md; 144 try { 145 md = MessageDigest.getInstance("SHA"); 146 } catch (NoSuchAlgorithmException ex) { 147 ex.printStackTrace(); 148 GlobalOptions.err.println("Can't calculate serialVersionUID"); 149 return 0L; 150 } 151 OutputStream digest = new OutputStream () { 152 153 public void write(int b) { 154 md.update((byte) b); 155 } 156 157 public void write(byte[] data, int offset, int length) { 158 md.update(data, offset, length); 159 } 160 }; 161 DataOutputStream out = new DataOutputStream (digest); 162 try { 163 out.writeUTF(info.getName()); 164 165 int modifiers = info.getModifiers(); 166 modifiers = modifiers & ( Modifier.ABSTRACT | Modifier.FINAL 168 | Modifier.INTERFACE | Modifier.PUBLIC ); 169 out.writeInt(modifiers); 170 171 ClassInfo[] interfaces 172 = (ClassInfo[]) info.getInterfaces().clone(); 173 Arrays.sort(interfaces, new Comparator () { 174 public int compare( Object o1, Object o2 ) { 175 return ((ClassInfo)o1).getName() 176 .compareTo(((ClassInfo)o2).getName()); 177 } 178 }); 179 for( int i=0; i < interfaces.length; i++ ) { 180 out.writeUTF(interfaces[i].getName()); 181 } 182 183 184 Comparator identCmp = new Comparator () { 185 public int compare(Object o1, Object o2) { 186 Identifier i1 = (Identifier)o1; 187 Identifier i2 = (Identifier)o2; 188 String name1 = i1.getName(); 189 String name2 = i2.getName(); 190 boolean special1 = (name1.equals("<init>") 191 || name1.equals("<clinit>")); 192 boolean special2 = (name2.equals("<init>") 193 || name2.equals("<clinit>")); 194 if (special1 != special2) { 196 return special1 ? -1 : 1; 197 } 198 199 int comp = i1.getName().compareTo(i2.getName()); 200 if (comp != 0) { 201 return comp; 202 } else { 203 return i1.getType().compareTo(i2.getType()); 204 } 205 } 206 }; 207 208 List fields = Arrays.asList(fieldIdents.toArray()); 209 List methods = Arrays.asList(methodIdents.toArray()); 210 Collections.sort(fields, identCmp); 211 Collections.sort(methods, identCmp); 212 213 for (Iterator i = fields.iterator(); i.hasNext();) { 214 FieldIdentifier field = (FieldIdentifier) i.next(); 215 modifiers = field.info.getModifiers(); 216 if ((modifiers & Modifier.PRIVATE) != 0 217 && (modifiers & (Modifier.STATIC 218 | Modifier.TRANSIENT)) != 0) 219 continue; 220 221 out.writeUTF(field.getName()); 222 out.writeInt(modifiers); 223 out.writeUTF(field.getType()); 224 } 225 for (Iterator i = methods.iterator(); i.hasNext(); ) { 226 MethodIdentifier method = (MethodIdentifier) i.next(); 227 modifiers = method.info.getModifiers(); 228 if( Modifier.isPrivate(modifiers)) 229 continue; 230 231 out.writeUTF(method.getName()); 232 out.writeInt(modifiers); 233 234 out.writeUTF(method.getType().replace('/', '.')); 237 } 238 239 out.close(); 240 241 byte[] sha = md.digest(); 242 long result = 0; 243 for (int i=0; i < 8; i++) { 244 result += (long)(sha[i] & 0xFF) << (8 * i); 245 } 246 return result; 247 } catch (IOException ex) { 248 ex.printStackTrace(); 249 GlobalOptions.err.println("Can't calculate serialVersionUID"); 250 return 0L; 251 } 252 } 253 254 public void addSUID() { 255 256 long serialVersion = calcSerialVersionUID(); 257 FieldInfo UIDField = new FieldInfo 258 (info, "serialVersionUID", "J", 259 Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL); 260 UIDField.setConstant(new Long (serialVersion)); 261 FieldIdentifier UIDident = new FieldIdentifier(this, UIDField); 262 fieldIdents.add(UIDident); 263 UIDident.setPreserved(); 264 } 265 266 public boolean isSerializable() { 267 return ClassInfo.forName("java.io.Serializable") 268 .implementedBy(info); 269 } 270 public boolean hasSUID() { 271 return (findField("serialVersionUID", "J") != null); 272 } 273 274 277 protected void setSinglePreserved() { 278 pack.setPreserved(); 279 } 280 281 public void setSingleReachable() { 282 super.setSingleReachable(); 283 Main.getClassBundle().analyzeIdentifier(this); 284 } 285 286 public void analyzeSuperClasses(ClassInfo superclass) { 287 while (superclass != null) { 288 289 ClassIdentifier superident = Main.getClassBundle() 290 .getClassIdentifier(superclass.getName()); 291 if (superident != null) { 292 superident.addSubClass(this); 293 } else { 294 String clazzType = ("L"+superclass.getName().replace('.', '/') 296 +";").intern(); 297 MethodInfo[] topmethods = superclass.getMethods(); 298 for (int i=0; i< topmethods.length; i++) { 299 int modif = topmethods[i].getModifiers(); 300 if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL) 301 & modif) == 0 302 && !topmethods[i].getName().equals("<init>")) { 303 reachableReference 304 (Reference.getReference(clazzType, 305 topmethods[i].getName(), 306 topmethods[i].getType()), 307 true); 308 } 309 } 310 } 311 ClassInfo[] ifaces = superclass.getInterfaces(); 312 for (int i=0; i < ifaces.length; i++) 313 analyzeSuperClasses(ifaces[i]); 314 superclass = superclass.getSuperclass(); 315 } 316 } 317 318 public void analyze() { 319 if (GlobalOptions.verboseLevel > 0) 320 GlobalOptions.err.println("Reachable: "+this); 321 322 ClassInfo[] ifaces = info.getInterfaces(); 323 for (int i=0; i < ifaces.length; i++) 324 analyzeSuperClasses(ifaces[i]); 325 analyzeSuperClasses(info.getSuperclass()); 326 } 327 328 public void initSuperClasses(ClassInfo superclass) { 329 while (superclass != null) { 330 ClassIdentifier superident = Main.getClassBundle() 331 .getClassIdentifier(superclass.getName()); 332 if (superident != null) { 333 for (Iterator i = superident.getMethodIdents().iterator(); 334 i.hasNext(); ) { 335 MethodIdentifier mid = (MethodIdentifier) i.next(); 336 int modif = mid.info.getModifiers(); 338 if (((Modifier.PRIVATE 339 | Modifier.STATIC 340 | Modifier.FINAL) & modif) == 0 341 && !(mid.getName().equals("<init>"))) { 342 chainMethodIdentifier(mid); 344 } 345 } 346 } else { 347 MethodInfo[] topmethods = superclass.getMethods(); 349 for (int i=0; i< topmethods.length; i++) { 350 int modif = topmethods[i].getModifiers(); 353 if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL) 354 & modif) == 0 355 && !topmethods[i].getName().equals("<init>")) { 356 Identifier method = findMethod 357 (topmethods[i].getName(), topmethods[i].getType()); 358 if (method != null) 359 method.setPreserved(); 360 } 361 } 362 } 363 ClassInfo[] ifaces = superclass.getInterfaces(); 364 for (int i=0; i < ifaces.length; i++) 365 initSuperClasses(ifaces[i]); 366 superclass = superclass.getSuperclass(); 367 } 368 } 369 370 public void initClass() { 371 info.loadInfo(info.FULLINFO); 372 373 FieldInfo[] finfos = info.getFields(); 374 MethodInfo[] minfos = info.getMethods(); 375 if (Main.swapOrder) { 376 Collections.shuffle(Arrays.asList(finfos), Main.rand); 377 Collections.shuffle(Arrays.asList(minfos), Main.rand); 378 } 379 fieldIdents = new ArrayList (finfos.length); 380 methodIdents = new ArrayList (minfos.length); 381 for (int i=0; i< finfos.length; i++) 382 fieldIdents.add(new FieldIdentifier(this, finfos[i])); 383 384 for (int i=0; i< minfos.length; i++) { 385 MethodIdentifier ident = new MethodIdentifier(this, minfos[i]); 386 methodIdents.add(ident); 387 if (ident.getName().equals("<clinit>")) { 388 391 ident.setPreserved(); 392 ident.setReachable(); 393 } else if (ident.getName().equals("<init>")) 394 ident.setPreserved(); 395 } 396 397 ClassInfo[] ifaces = info.getInterfaces(); 399 ifaceNames = new String [ifaces.length]; 400 for (int i=0; i < ifaces.length; i++) { 401 ifaceNames[i] = ifaces[i].getName(); 402 initSuperClasses(ifaces[i]); 403 } 404 405 if (info.getSuperclass() != null) { 406 superName = info.getSuperclass().getName(); 407 initSuperClasses(info.getSuperclass()); 408 } 409 410 if ((Main.stripping & Main.STRIP_SOURCE) != 0) { 411 info.setSourceFile(null); 412 } 413 if ((Main.stripping & Main.STRIP_INNERINFO) != 0) { 414 info.setInnerClasses(new InnerClassInfo[0]); 415 info.setOuterClasses(new InnerClassInfo[0]); 416 info.setExtraClasses(new InnerClassInfo[0]); 417 } 418 InnerClassInfo[] innerClasses = info.getInnerClasses(); 420 InnerClassInfo[] outerClasses = info.getOuterClasses(); 421 InnerClassInfo[] extraClasses = info.getExtraClasses(); 422 if (outerClasses != null) { 423 for (int i=0; i < outerClasses.length; i++) { 424 if (outerClasses[i].outer != null) { 425 Main.getClassBundle() 426 .getClassIdentifier(outerClasses[i].outer); 427 } 428 } 429 } 430 if (innerClasses != null) { 431 for (int i=0; i < innerClasses.length; i++) { 432 Main.getClassBundle() 433 .getClassIdentifier(innerClasses[i].inner); 434 } 435 } 436 if (extraClasses != null) { 437 for (int i=0; i < extraClasses.length; i++) { 438 Main.getClassBundle() 439 .getClassIdentifier(extraClasses[i].inner); 440 if (extraClasses[i].outer != null) 441 Main.getClassBundle() 442 .getClassIdentifier(extraClasses[i].outer); 443 } 444 } 445 } 446 447 454 public void addIfaces(Collection result, ClassIdentifier ancestor) { 455 ClassInfo[] ifaceInfos = ancestor.info.getInterfaces(); 456 for (int i=0; i < ifaceInfos.length; i++) { 457 ClassIdentifier ifaceident 458 = Main.getClassBundle().getClassIdentifier(ifaceInfos[i].getName()); 459 if (ifaceident != null && !ifaceident.isReachable()) 460 addIfaces(result, ifaceident); 461 else 462 result.add(ifaceInfos[i]); 463 } 464 } 465 466 473 public void transformSuperIfaces() { 474 if ((Main.stripping & Main.STRIP_UNREACH) == 0) 475 return; 476 477 Collection newIfaces = new LinkedList (); 478 ClassIdentifier ancestor = this; 479 while(true) { 480 addIfaces(newIfaces, ancestor); 481 ClassIdentifier superident 482 = Main.getClassBundle().getClassIdentifier(ancestor.superName); 483 if (superident == null || superident.isReachable()) 484 break; 485 ancestor = superident; 486 } 487 ClassInfo superInfo = ancestor.info.getSuperclass(); 488 ClassInfo[] ifaces = (ClassInfo[]) 489 newIfaces.toArray(new ClassInfo[newIfaces.size()]); 490 info.setSuperclass(superInfo); 491 info.setInterfaces(ifaces); 492 } 493 494 public void transformInnerClasses() { 495 InnerClassInfo[] outerClasses = info.getOuterClasses(); 496 if (outerClasses != null) { 497 int newOuterCount = outerClasses.length; 498 if ((Main.stripping & Main.STRIP_UNREACH) != 0) { 499 for (int i=0; i < outerClasses.length; i++) { 500 if (outerClasses[i].outer != null) { 501 ClassIdentifier outerIdent = Main.getClassBundle() 502 .getClassIdentifier(outerClasses[i].outer); 503 if (outerIdent != null && !outerIdent.isReachable()) 504 newOuterCount--; 505 } 506 } 507 } 508 if (newOuterCount == 0) { 509 info.setOuterClasses(null); 510 } else { 511 InnerClassInfo[] newOuters = new InnerClassInfo[newOuterCount]; 512 int pos = 0; 513 String lastClass = getFullAlias(); 514 for (int i=0; i<outerClasses.length; i++) { 515 ClassIdentifier outerIdent = outerClasses[i].outer != null 516 ? (Main.getClassBundle() 517 .getClassIdentifier(outerClasses[i].outer)) 518 : null; 519 520 if ((Main.stripping & Main.STRIP_UNREACH) != 0 521 && outerIdent != null && !outerIdent.isReachable()) 522 continue; 523 524 String inner = lastClass; 525 String outer = outerIdent == null 526 ? outerClasses[i].outer 527 : outerIdent.getFullAlias(); 528 String name = outerClasses[i].name == null ? null 529 : ((outer != null && inner.startsWith(outer+"$")) 530 ? inner.substring(outer.length()+1) 531 : inner.substring(inner.lastIndexOf('.')+1)); 532 533 newOuters[pos++] = new InnerClassInfo 534 (inner, outer, name, outerClasses[i].modifiers); 535 lastClass = outer; 536 } 537 info.setOuterClasses(newOuters); 538 } 539 } 540 541 InnerClassInfo[] innerClasses = info.getInnerClasses(); 542 if (innerClasses != null) { 543 int newInnerCount = innerClasses.length; 544 if ((Main.stripping & Main.STRIP_UNREACH) != 0) { 545 for (int i=0; i < innerClasses.length; i++) { 546 ClassIdentifier innerIdent = Main.getClassBundle() 547 .getClassIdentifier(innerClasses[i].inner); 548 if (innerIdent != null && !innerIdent.isReachable()) 549 newInnerCount--; 550 } 551 } 552 if (newInnerCount == 0) { 553 info.setInnerClasses(null); 554 } else { 555 InnerClassInfo[] newInners = new InnerClassInfo[newInnerCount]; 556 int pos = 0; 557 for (int i=0; i<innerClasses.length; i++) { 558 ClassIdentifier innerIdent = Main.getClassBundle() 559 .getClassIdentifier(innerClasses[i].inner); 560 if ((Main.stripping & Main.STRIP_UNREACH) != 0 561 && innerIdent != null && !innerIdent.isReachable()) 562 continue; 563 564 String inner = innerIdent == null 565 ? innerClasses[i].inner 566 : innerIdent.getFullAlias(); 567 String outer = getFullAlias(); 568 String name = innerClasses[i].name == null ? null 569 : ((outer != null && inner.startsWith(outer+"$")) 570 ? inner.substring(outer.length()+1) 571 : inner.substring(inner.lastIndexOf('.')+1)); 572 573 newInners[pos++] = new InnerClassInfo 574 (inner, outer, name, innerClasses[i].modifiers); 575 } 576 info.setInnerClasses(newInners); 577 } 578 } 579 580 InnerClassInfo[] extraClasses = info.getExtraClasses(); 581 if (extraClasses != null) { 582 int newExtraCount = extraClasses.length; 583 if ((Main.stripping & Main.STRIP_UNREACH) != 0) { 584 for (int i=0; i < extraClasses.length; i++) { 585 ClassIdentifier outerIdent = extraClasses[i].outer != null 586 ? (Main.getClassBundle() 587 .getClassIdentifier(extraClasses[i].outer)) 588 : null; 589 ClassIdentifier innerIdent = Main.getClassBundle() 590 .getClassIdentifier(extraClasses[i].inner); 591 if ((outerIdent != null && !outerIdent.isReachable()) 592 || (innerIdent != null && !innerIdent.isReachable())) 593 newExtraCount--; 594 } 595 } 596 597 if (newExtraCount == 0) { 598 info.setExtraClasses(null); 599 } else { 600 InnerClassInfo[] newExtras = newExtraCount > 0 601 ? new InnerClassInfo[newExtraCount] : null; 602 603 int pos = 0; 604 for (int i=0; i<extraClasses.length; i++) { 605 ClassIdentifier outerIdent = extraClasses[i].outer != null 606 ? (Main.getClassBundle() 607 .getClassIdentifier(extraClasses[i].outer)) 608 : null; 609 ClassIdentifier innerIdent = Main.getClassBundle() 610 .getClassIdentifier(extraClasses[i].inner); 611 612 if ((Main.stripping & Main.STRIP_UNREACH) != 0) { 613 if (innerIdent != null && !innerIdent.isReachable()) 614 continue; 615 if (outerIdent != null && !outerIdent.isReachable()) 616 continue; 617 } 618 619 String inner = innerIdent == null 620 ? extraClasses[i].inner 621 : innerIdent.getFullAlias(); 622 String outer = outerIdent == null 623 ? extraClasses[i].outer 624 : outerIdent.getFullAlias(); 625 626 String name = extraClasses[i].name == null ? null 627 : ((outer != null && inner.startsWith(outer+"$")) 628 ? inner.substring(outer.length()+1) 629 : inner.substring(inner.lastIndexOf('.')+1)); 630 631 newExtras[pos++] = new InnerClassInfo 632 (inner, outer, name, extraClasses[i].modifiers); 633 } 634 info.setExtraClasses(newExtras); 635 } 636 } 637 } 638 639 public void doTransformations() { 640 if (GlobalOptions.verboseLevel > 0) 641 GlobalOptions.err.println("Transforming "+this); 642 info.setName(getFullAlias()); 643 transformSuperIfaces(); 644 transformInnerClasses(); 645 646 Collection newFields = new ArrayList (fieldIdents.size()); 647 Collection newMethods = new ArrayList (methodIdents.size()); 648 649 for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) { 650 FieldIdentifier ident = (FieldIdentifier)i.next(); 651 if ((Main.stripping & Main.STRIP_UNREACH) == 0 652 || ident.isReachable()) { 653 ident.doTransformations(); 654 newFields.add(ident.info); 655 } 656 } 657 for (Iterator i = methodIdents.iterator(); i.hasNext(); ) { 658 MethodIdentifier ident = (MethodIdentifier)i.next(); 659 if ((Main.stripping & Main.STRIP_UNREACH) == 0 660 || ident.isReachable()) { 661 ident.doTransformations(); 662 newMethods.add(ident.info); 663 } 664 } 665 666 info.setFields((FieldInfo[]) newFields.toArray 667 (new FieldInfo[newFields.size()])); 668 info.setMethods((MethodInfo[]) newMethods.toArray 669 (new MethodInfo[newMethods.size()])); 670 } 671 672 public void storeClass(DataOutputStream out) throws IOException { 673 if (GlobalOptions.verboseLevel > 0) 674 GlobalOptions.err.println("Writing "+this); 675 info.write(out); 676 info = null; 677 fieldIdents = methodIdents = null; 678 } 679 680 public Identifier getParent() { 681 return pack; 682 } 683 684 687 public String getFullName() { 688 return fullName; 689 } 690 691 694 public String getFullAlias() { 695 if (pack.parent == null) 696 return getAlias(); 697 else 698 return pack.getFullAlias() + "." + getAlias(); 699 } 700 701 public String getName() { 702 return name; 703 } 704 705 public String getType() { 706 return "Ljava/lang/Class;"; 707 } 708 709 public int getModifiers() { 710 return info.getModifiers(); 711 } 712 713 public List getFieldIdents() { 714 return fieldIdents; 715 } 716 717 public List getMethodIdents() { 718 return methodIdents; 719 } 720 721 public Iterator getChilds() { 722 final Iterator fieldIter = fieldIdents.iterator(); 723 final Iterator methodIter = methodIdents.iterator(); 724 725 return new Iterator () { 726 boolean fieldsNext = fieldIter.hasNext(); 727 public boolean hasNext() { 728 return fieldsNext ? true : methodIter.hasNext(); 729 } 730 731 public Object next() { 732 if (fieldsNext) { 733 Object result = fieldIter.next(); 734 fieldsNext = fieldIter.hasNext(); 735 return result; 736 } 737 return methodIter.next(); 738 } 739 740 public void remove() { 741 throw new UnsupportedOperationException (); 742 } 743 }; 744 } 745 746 public String toString() { 747 return "ClassIdentifier "+getFullName(); 748 } 749 750 public Identifier getIdentifier(String fieldName, String typeSig) { 751 for (Iterator i = getChilds(); i.hasNext(); ) { 752 Identifier ident = (Identifier) i.next(); 753 if (ident.getName().equals(fieldName) 754 && ident.getType().startsWith(typeSig)) 755 return ident; 756 } 757 758 if (superName != null) { 759 ClassIdentifier superident = Main.getClassBundle() 760 .getClassIdentifier(superName); 761 if (superident != null) { 762 Identifier ident 763 = superident.getIdentifier(fieldName, typeSig); 764 if (ident != null) 765 return ident; 766 } 767 } 768 return null; 769 } 770 771 public boolean containsFieldAliasDirectly(String fieldName, String typeSig, 772 IdentifierMatcher matcher) { 773 for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) { 774 Identifier ident = (Identifier) i.next(); 775 if (((Main.stripping & Main.STRIP_UNREACH) == 0 776 || ident.isReachable()) 777 && ident.wasAliased() 778 && ident.getAlias().equals(fieldName) 779 && ident.getType().startsWith(typeSig) 780 && matcher.matches(ident)) 781 return true; 782 } 783 return false; 784 } 785 786 public boolean containsMethodAliasDirectly(String methodName, 787 String paramType, 788 IdentifierMatcher matcher) { 789 for (Iterator i = methodIdents.iterator(); i.hasNext(); ) { 790 Identifier ident = (Identifier) i.next(); 791 if (((Main.stripping & Main.STRIP_UNREACH) == 0 792 || ident.isReachable()) 793 && ident.wasAliased() 794 && ident.getAlias().equals(methodName) 795 && ident.getType().startsWith(paramType) 796 && matcher.matches(ident)) 797 return true; 798 } 799 return false; 800 } 801 802 public boolean fieldConflicts(FieldIdentifier field, String newAlias) { 803 String typeSig = (Main.options & Main.OPTION_STRONGOVERLOAD) != 0 804 ? field.getType() : ""; 805 806 811 812 813 ModifierMatcher mm = ModifierMatcher.allowAll; 814 if (containsFieldAliasDirectly(newAlias, typeSig, mm)) 815 return true; 816 return false; 817 } 818 819 public boolean methodConflicts(MethodIdentifier method, String newAlias) { 820 String paramType = method.getType(); 821 if ((Main.options & Main.OPTION_STRONGOVERLOAD) == 0) 822 paramType = paramType.substring(0, paramType.indexOf(')')+1); 823 824 ModifierMatcher matcher = ModifierMatcher.allowAll; 825 if (containsMethodAliasDirectly(newAlias, paramType, matcher)) 826 return true; 827 828 ModifierMatcher packMatcher = matcher.forceAccess(0, true); 829 if (method.info.isStatic()) { 830 833 packMatcher.forbidModifier(Modifier.STATIC); 834 } 835 839 ClassInfo superInfo = info.getSuperclass(); 840 ClassIdentifier superIdent = this; 841 while (superInfo != null) { 842 ClassIdentifier superident = Main.getClassBundle() 843 .getClassIdentifier(superInfo.getName()); 844 if (superident != null) { 845 if (superident.containsMethodAliasDirectly 846 (newAlias, paramType, packMatcher)) 847 return true; 848 } else { 849 MethodInfo[] minfos = superInfo.getMethods(); 850 for (int i=0; i< minfos.length; i++) { 851 if (minfos[i].getName().equals(newAlias) 852 && minfos[i].getType().startsWith(paramType) 853 && packMatcher.matches(minfos[i].getModifiers())) 854 return true; 855 } 856 } 857 superInfo = superInfo.getSuperclass(); 858 } 859 if (packMatcher.matches(method)) { 860 for (Iterator i = knownSubClasses.iterator(); i.hasNext(); ) { 861 ClassIdentifier ci = (ClassIdentifier) i.next(); 862 if (ci.containsMethodAliasDirectly(newAlias, paramType, 863 packMatcher)) 864 return true; 865 } 866 } 867 return false; 868 } 869 870 public boolean conflicting(String newAlias) { 871 return pack.contains(newAlias, this); 872 } 873 } 874 | Popular Tags |