1 11 package org.eclipse.jdt.internal.core.hierarchy; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.io.OutputStream ; 16 import java.util.ArrayList ; 17 import java.util.HashMap ; 18 import java.util.Hashtable ; 19 import java.util.Iterator ; 20 import java.util.Map ; 21 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.ISafeRunnable; 26 import org.eclipse.core.runtime.IStatus; 27 import org.eclipse.core.runtime.OperationCanceledException; 28 import org.eclipse.core.runtime.SafeRunner; 29 import org.eclipse.jdt.core.*; 30 import org.eclipse.jdt.core.search.IJavaSearchScope; 31 import org.eclipse.jdt.core.search.SearchEngine; 32 import org.eclipse.jdt.internal.core.*; 33 import org.eclipse.jdt.internal.core.util.Messages; 34 import org.eclipse.jdt.internal.core.util.Util; 35 36 39 public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener { 40 41 public static boolean DEBUG = false; 42 43 static final byte VERSION = 0x0000; 44 static final byte SEPARATOR1 = '\n'; 46 static final byte SEPARATOR2 = ','; 47 static final byte SEPARATOR3 = '>'; 48 static final byte SEPARATOR4 = '\r'; 49 static final byte COMPUTE_SUBTYPES = 0x0001; 51 52 static final byte CLASS = 0x0000; 54 static final byte INTERFACE = 0x0001; 55 static final byte COMPUTED_FOR = 0x0002; 56 static final byte ROOT = 0x0004; 57 58 static final byte[] NO_FLAGS = new byte[]{}; 60 static final int SIZE = 10; 61 62 67 protected IJavaProject project; 68 72 protected IType focusType; 73 74 77 protected ICompilationUnit[] workingCopies; 78 79 protected Map classToSuperclass; 80 protected Map typeToSuperInterfaces; 81 protected Map typeToSubtypes; 82 protected Map typeFlags; 83 protected TypeVector rootClasses = new TypeVector(); 84 protected ArrayList interfaces = new ArrayList (10); 85 public ArrayList missingTypes = new ArrayList (4); 86 87 protected static final IType[] NO_TYPE = new IType[0]; 88 89 92 protected IProgressMonitor progressMonitor = null; 93 94 97 protected ArrayList changeListeners = null; 98 99 102 public Map files = null; 103 104 108 protected Region packageRegion = null; 109 110 114 protected Region projectRegion = null; 115 116 119 protected boolean computeSubtypes; 120 121 124 IJavaSearchScope scope; 125 126 129 public boolean needsRefresh = true; 130 131 134 protected ChangeCollector changeCollector; 135 136 139 public TypeHierarchy() { 140 } 142 145 public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaProject project, boolean computeSubtypes) { 146 this(type, workingCopies, SearchEngine.createJavaSearchScope(new IJavaElement[] {project}), computeSubtypes); 147 this.project = project; 148 } 149 152 public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) { 153 this.focusType = type == null ? null : (IType) ((JavaElement) type).unresolved(); this.workingCopies = workingCopies; 155 this.computeSubtypes = computeSubtypes; 156 this.scope = scope; 157 } 158 161 protected void initializeRegions() { 162 163 IType[] allTypes = getAllTypes(); 164 for (int i = 0; i < allTypes.length; i++) { 165 IType type = allTypes[i]; 166 Openable o = (Openable) ((JavaElement) type).getOpenableParent(); 167 if (o != null) { 168 ArrayList types = (ArrayList )this.files.get(o); 169 if (types == null) { 170 types = new ArrayList (); 171 this.files.put(o, types); 172 } 173 types.add(type); 174 } 175 IPackageFragment pkg = type.getPackageFragment(); 176 this.packageRegion.add(pkg); 177 IJavaProject declaringProject = type.getJavaProject(); 178 if (declaringProject != null) { 179 this.projectRegion.add(declaringProject); 180 } 181 checkCanceled(); 182 } 183 } 184 188 private void addAllCheckingDuplicates(ArrayList list, IType[] collection) { 189 for (int i = 0; i < collection.length; i++) { 190 IType element = collection[i]; 191 if (!list.contains(element)) { 192 list.add(element); 193 } 194 } 195 } 196 199 protected void addInterface(IType type) { 200 this.interfaces.add(type); 201 } 202 206 protected void addRootClass(IType type) { 207 if (this.rootClasses.contains(type)) return; 208 this.rootClasses.add(type); 209 } 210 213 protected void addSubtype(IType type, IType subtype) { 214 TypeVector subtypes = (TypeVector)this.typeToSubtypes.get(type); 215 if (subtypes == null) { 216 subtypes = new TypeVector(); 217 this.typeToSubtypes.put(type, subtypes); 218 } 219 if (!subtypes.contains(subtype)) { 220 subtypes.add(subtype); 221 } 222 } 223 226 public synchronized void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) { 227 ArrayList listeners = this.changeListeners; 228 if (listeners == null) { 229 this.changeListeners = listeners = new ArrayList (); 230 } 231 232 if (listeners.size() == 0) { 234 JavaCore.addElementChangedListener(this); 235 } 236 237 if (listeners.indexOf(listener) == -1) { 239 listeners.add(listener); 240 } 241 } 242 private static Integer bytesToFlags(byte[] bytes){ 243 if(bytes != null && bytes.length > 0) { 244 return new Integer (new String (bytes)); 245 } else { 246 return null; 247 } 248 } 249 252 public void cacheFlags(IType type, int flags) { 253 this.typeFlags.put(type, new Integer (flags)); 254 } 255 259 protected void cacheSuperclass(IType type, IType superclass) { 260 if (superclass != null) { 261 this.classToSuperclass.put(type, superclass); 262 addSubtype(superclass, type); 263 } 264 } 265 269 protected void cacheSuperInterfaces(IType type, IType[] superinterfaces) { 270 this.typeToSuperInterfaces.put(type, superinterfaces); 271 for (int i = 0; i < superinterfaces.length; i++) { 272 IType superinterface = superinterfaces[i]; 273 if (superinterface != null) { 274 addSubtype(superinterface, type); 275 } 276 } 277 } 278 286 protected void checkCanceled() { 287 if (this.progressMonitor != null && this.progressMonitor.isCanceled()) { 288 throw new OperationCanceledException(); 289 } 290 } 291 294 protected void compute() throws JavaModelException, CoreException { 295 if (this.focusType != null) { 296 HierarchyBuilder builder = 297 new IndexBasedHierarchyBuilder( 298 this, 299 this.scope); 300 builder.build(this.computeSubtypes); 301 } } 303 306 public boolean contains(IType type) { 307 if (this.classToSuperclass.get(type) != null) { 309 return true; 310 } 311 312 if (this.rootClasses.contains(type)) return true; 314 315 if (this.interfaces.contains(type)) return true; 317 318 return false; 319 } 320 324 public void elementChanged(ElementChangedEvent event) { 325 if (this.needsRefresh) return; 327 328 if (isAffected(event.getDelta())) { 329 this.needsRefresh = true; 330 fireChange(); 331 } 332 } 333 336 public boolean exists() { 337 if (!this.needsRefresh) return true; 338 339 return (this.focusType == null || this.focusType.exists()) && this.javaProject().exists(); 340 } 341 346 public void fireChange() { 347 ArrayList listeners = this.changeListeners; 348 if (listeners == null) { 349 return; 350 } 351 if (DEBUG) { 352 System.out.println("FIRING hierarchy change ["+Thread.currentThread()+"]"); if (this.focusType != null) { 354 System.out.println(" for hierarchy focused on " + ((JavaElement)this.focusType).toStringWithAncestors()); } 356 } 357 listeners = (ArrayList )listeners.clone(); 359 for (int i= 0; i < listeners.size(); i++) { 360 final ITypeHierarchyChangedListener listener= (ITypeHierarchyChangedListener)listeners.get(i); 361 SafeRunner.run(new ISafeRunnable() { 362 public void handleException(Throwable exception) { 363 Util.log(exception, "Exception occurred in listener of Type hierarchy change notification"); } 365 public void run() throws Exception { 366 listener.typeHierarchyChanged(TypeHierarchy.this); 367 } 368 }); 369 } 370 } 371 private static byte[] flagsToBytes(Integer flags){ 372 if(flags != null) { 373 return flags.toString().getBytes(); 374 } else { 375 return NO_FLAGS; 376 } 377 } 378 381 public IType[] getAllClasses() { 382 383 TypeVector classes = this.rootClasses.copy(); 384 for (Iterator iter = this.classToSuperclass.keySet().iterator(); iter.hasNext();){ 385 classes.add((IType)iter.next()); 386 } 387 return classes.elements(); 388 } 389 392 public IType[] getAllInterfaces() { 393 IType[] collection= new IType[this.interfaces.size()]; 394 this.interfaces.toArray(collection); 395 return collection; 396 } 397 400 public IType[] getAllSubtypes(IType type) { 401 return getAllSubtypesForType(type); 402 } 403 406 private IType[] getAllSubtypesForType(IType type) { 407 ArrayList subTypes = new ArrayList (); 408 getAllSubtypesForType0(type, subTypes); 409 IType[] subClasses = new IType[subTypes.size()]; 410 subTypes.toArray(subClasses); 411 return subClasses; 412 } 413 415 private void getAllSubtypesForType0(IType type, ArrayList subs) { 416 IType[] subTypes = getSubtypesForType(type); 417 if (subTypes.length != 0) { 418 for (int i = 0; i < subTypes.length; i++) { 419 IType subType = subTypes[i]; 420 subs.add(subType); 421 getAllSubtypesForType0(subType, subs); 422 } 423 } 424 } 425 428 public IType[] getAllSuperclasses(IType type) { 429 IType superclass = getSuperclass(type); 430 TypeVector supers = new TypeVector(); 431 while (superclass != null) { 432 supers.add(superclass); 433 superclass = getSuperclass(superclass); 434 } 435 return supers.elements(); 436 } 437 440 public IType[] getAllSuperInterfaces(IType type) { 441 ArrayList supers = new ArrayList (); 442 if (this.typeToSuperInterfaces.get(type) == null) { 443 return NO_TYPE; 444 } 445 getAllSuperInterfaces0(type, supers); 446 IType[] superinterfaces = new IType[supers.size()]; 447 supers.toArray(superinterfaces); 448 return superinterfaces; 449 } 450 private void getAllSuperInterfaces0(IType type, ArrayList supers) { 451 IType[] superinterfaces = (IType[]) this.typeToSuperInterfaces.get(type); 452 if (superinterfaces != null && superinterfaces.length != 0) { 453 addAllCheckingDuplicates(supers, superinterfaces); 454 for (int i = 0; i < superinterfaces.length; i++) { 455 getAllSuperInterfaces0(superinterfaces[i], supers); 456 } 457 } 458 IType superclass = (IType) this.classToSuperclass.get(type); 459 if (superclass != null) { 460 getAllSuperInterfaces0(superclass, supers); 461 } 462 } 463 466 public IType[] getAllSupertypes(IType type) { 467 ArrayList supers = new ArrayList (); 468 if (this.typeToSuperInterfaces.get(type) == null) { 469 return NO_TYPE; 470 } 471 getAllSupertypes0(type, supers); 472 IType[] supertypes = new IType[supers.size()]; 473 supers.toArray(supertypes); 474 return supertypes; 475 } 476 private void getAllSupertypes0(IType type, ArrayList supers) { 477 IType[] superinterfaces = (IType[]) this.typeToSuperInterfaces.get(type); 478 if (superinterfaces != null && superinterfaces.length != 0) { 479 addAllCheckingDuplicates(supers, superinterfaces); 480 for (int i = 0; i < superinterfaces.length; i++) { 481 getAllSuperInterfaces0(superinterfaces[i], supers); 482 } 483 } 484 IType superclass = (IType) this.classToSuperclass.get(type); 485 if (superclass != null) { 486 supers.add(superclass); 487 getAllSupertypes0(superclass, supers); 488 } 489 } 490 493 public IType[] getAllTypes() { 494 IType[] classes = getAllClasses(); 495 int classesLength = classes.length; 496 IType[] allInterfaces = getAllInterfaces(); 497 int interfacesLength = allInterfaces.length; 498 IType[] all = new IType[classesLength + interfacesLength]; 499 System.arraycopy(classes, 0, all, 0, classesLength); 500 System.arraycopy(allInterfaces, 0, all, classesLength, interfacesLength); 501 return all; 502 } 503 504 507 public int getCachedFlags(IType type) { 508 Integer flagObject = (Integer ) this.typeFlags.get(type); 509 if (flagObject != null){ 510 return flagObject.intValue(); 511 } 512 return -1; 513 } 514 515 518 public IType[] getExtendingInterfaces(IType type) { 519 if (!this.isInterface(type)) return NO_TYPE; 520 return getExtendingInterfaces0(type); 521 } 522 526 private IType[] getExtendingInterfaces0(IType extendedInterface) { 527 Iterator iter = this.typeToSuperInterfaces.entrySet().iterator(); 528 ArrayList interfaceList = new ArrayList (); 529 while (iter.hasNext()) { 530 Map.Entry entry = (Map.Entry ) iter.next(); 531 IType type = (IType) entry.getKey(); 532 if (!this.isInterface(type)) { 533 continue; 534 } 535 IType[] superInterfaces = (IType[]) entry.getValue(); 536 if (superInterfaces != null) { 537 for (int i = 0; i < superInterfaces.length; i++) { 538 IType superInterface = superInterfaces[i]; 539 if (superInterface.equals(extendedInterface)) { 540 interfaceList.add(type); 541 } 542 } 543 } 544 } 545 IType[] extendingInterfaces = new IType[interfaceList.size()]; 546 interfaceList.toArray(extendingInterfaces); 547 return extendingInterfaces; 548 } 549 552 public IType[] getImplementingClasses(IType type) { 553 if (!this.isInterface(type)) { 554 return NO_TYPE; 555 } 556 return getImplementingClasses0(type); 557 } 558 562 private IType[] getImplementingClasses0(IType interfce) { 563 564 Iterator iter = this.typeToSuperInterfaces.entrySet().iterator(); 565 ArrayList iMenters = new ArrayList (); 566 while (iter.hasNext()) { 567 Map.Entry entry = (Map.Entry ) iter.next(); 568 IType type = (IType) entry.getKey(); 569 if (this.isInterface(type)) { 570 continue; 571 } 572 IType[] types = (IType[]) entry.getValue(); 573 for (int i = 0; i < types.length; i++) { 574 IType iFace = types[i]; 575 if (iFace.equals(interfce)) { 576 iMenters.add(type); 577 } 578 } 579 } 580 IType[] implementers = new IType[iMenters.size()]; 581 iMenters.toArray(implementers); 582 return implementers; 583 } 584 587 public IType[] getRootClasses() { 588 return this.rootClasses.elements(); 589 } 590 593 public IType[] getRootInterfaces() { 594 IType[] allInterfaces = getAllInterfaces(); 595 IType[] roots = new IType[allInterfaces.length]; 596 int rootNumber = 0; 597 for (int i = 0; i < allInterfaces.length; i++) { 598 IType[] superInterfaces = getSuperInterfaces(allInterfaces[i]); 599 if (superInterfaces == null || superInterfaces.length == 0) { 600 roots[rootNumber++] = allInterfaces[i]; 601 } 602 } 603 IType[] result = new IType[rootNumber]; 604 if (result.length > 0) { 605 System.arraycopy(roots, 0, result, 0, rootNumber); 606 } 607 return result; 608 } 609 612 public IType[] getSubclasses(IType type) { 613 if (this.isInterface(type)) { 614 return NO_TYPE; 615 } 616 TypeVector vector = (TypeVector)this.typeToSubtypes.get(type); 617 if (vector == null) 618 return NO_TYPE; 619 else 620 return vector.elements(); 621 } 622 625 public IType[] getSubtypes(IType type) { 626 return getSubtypesForType(type); 627 } 628 631 private IType[] getSubtypesForType(IType type) { 632 TypeVector vector = (TypeVector)this.typeToSubtypes.get(type); 633 if (vector == null) 634 return NO_TYPE; 635 else 636 return vector.elements(); 637 } 638 641 public IType getSuperclass(IType type) { 642 if (this.isInterface(type)) { 643 return null; 644 } 645 return (IType) this.classToSuperclass.get(type); 646 } 647 650 public IType[] getSuperInterfaces(IType type) { 651 IType[] types = (IType[]) this.typeToSuperInterfaces.get(type); 652 if (types == null) { 653 return NO_TYPE; 654 } 655 return types; 656 } 657 660 public IType[] getSupertypes(IType type) { 661 IType superclass = getSuperclass(type); 662 if (superclass == null) { 663 return getSuperInterfaces(type); 664 } else { 665 TypeVector superTypes = new TypeVector(getSuperInterfaces(type)); 666 superTypes.add(superclass); 667 return superTypes.elements(); 668 } 669 } 670 673 public IType getType() { 674 return this.focusType; 675 } 676 680 protected IType[] growAndAddToArray(IType[] array, IType[] additions) { 681 if (array == null || array.length == 0) { 682 return additions; 683 } 684 IType[] old = array; 685 array = new IType[old.length + additions.length]; 686 System.arraycopy(old, 0, array, 0, old.length); 687 System.arraycopy(additions, 0, array, old.length, additions.length); 688 return array; 689 } 690 694 protected IType[] growAndAddToArray(IType[] array, IType addition) { 695 if (array == null || array.length == 0) { 696 return new IType[] {addition}; 697 } 698 IType[] old = array; 699 array = new IType[old.length + 1]; 700 System.arraycopy(old, 0, array, 0, old.length); 701 array[old.length] = addition; 702 return array; 703 } 704 707 public boolean hasFineGrainChanges() { 708 ChangeCollector collector = this.changeCollector; 709 return collector != null && collector.needsRefresh(); 710 } 711 715 private boolean hasSubtypeNamed(String simpleName) { 716 if (this.focusType != null && this.focusType.getElementName().equals(simpleName)) { 717 return true; 718 } 719 IType[] types = this.focusType == null ? getAllTypes() : getAllSubtypes(this.focusType); 720 for (int i = 0, length = types.length; i < length; i++) { 721 if (types[i].getElementName().equals(simpleName)) { 722 return true; 723 } 724 } 725 return false; 726 } 727 728 731 private boolean hasTypeNamed(String simpleName) { 732 IType[] types = this.getAllTypes(); 733 for (int i = 0, length = types.length; i < length; i++) { 734 if (types[i].getElementName().equals(simpleName)) { 735 return true; 736 } 737 } 738 return false; 739 } 740 741 745 boolean includesTypeOrSupertype(IType type) { 746 try { 747 if (hasTypeNamed(type.getElementName())) return true; 749 750 String superclassName = type.getSuperclassName(); 752 if (superclassName != null) { 753 int lastSeparator = superclassName.lastIndexOf('.'); 754 String simpleName = superclassName.substring(lastSeparator+1); 755 if (hasTypeNamed(simpleName)) return true; 756 } 757 758 String [] superinterfaceNames = type.getSuperInterfaceNames(); 760 if (superinterfaceNames != null) { 761 for (int i = 0, length = superinterfaceNames.length; i < length; i++) { 762 String superinterfaceName = superinterfaceNames[i]; 763 int lastSeparator = superinterfaceName.lastIndexOf('.'); 764 String simpleName = superinterfaceName.substring(lastSeparator+1); 765 if (hasTypeNamed(simpleName)) return true; 766 } 767 } 768 } catch (JavaModelException e) { 769 } 771 return false; 772 } 773 776 protected void initialize(int size) { 777 if (size < 10) { 778 size = 10; 779 } 780 int smallSize = (size / 2); 781 this.classToSuperclass = new HashMap (size); 782 this.interfaces = new ArrayList (smallSize); 783 this.missingTypes = new ArrayList (smallSize); 784 this.rootClasses = new TypeVector(); 785 this.typeToSubtypes = new HashMap (smallSize); 786 this.typeToSuperInterfaces = new HashMap (smallSize); 787 this.typeFlags = new HashMap (smallSize); 788 789 this.projectRegion = new Region(); 790 this.packageRegion = new Region(); 791 this.files = new HashMap (5); 792 } 793 796 public synchronized boolean isAffected(IJavaElementDelta delta) { 797 IJavaElement element= delta.getElement(); 798 switch (element.getElementType()) { 799 case IJavaElement.JAVA_MODEL: 800 return isAffectedByJavaModel(delta, element); 801 case IJavaElement.JAVA_PROJECT: 802 return isAffectedByJavaProject(delta, element); 803 case IJavaElement.PACKAGE_FRAGMENT_ROOT: 804 return isAffectedByPackageFragmentRoot(delta, element); 805 case IJavaElement.PACKAGE_FRAGMENT: 806 return isAffectedByPackageFragment(delta, (PackageFragment) element); 807 case IJavaElement.CLASS_FILE: 808 case IJavaElement.COMPILATION_UNIT: 809 return isAffectedByOpenable(delta, element); 810 } 811 return false; 812 } 813 818 private boolean isAffectedByChildren(IJavaElementDelta delta) { 819 if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) > 0) { 820 IJavaElementDelta[] children= delta.getAffectedChildren(); 821 for (int i= 0; i < children.length; i++) { 822 if (isAffected(children[i])) { 823 return true; 824 } 825 } 826 } 827 return false; 828 } 829 832 private boolean isAffectedByJavaModel(IJavaElementDelta delta, IJavaElement element) { 833 switch (delta.getKind()) { 834 case IJavaElementDelta.ADDED : 835 case IJavaElementDelta.REMOVED : 836 return element.equals(this.javaProject().getJavaModel()); 837 case IJavaElementDelta.CHANGED : 838 return isAffectedByChildren(delta); 839 } 840 return false; 841 } 842 845 private boolean isAffectedByJavaProject(IJavaElementDelta delta, IJavaElement element) { 846 int kind = delta.getKind(); 847 int flags = delta.getFlags(); 848 if ((flags & IJavaElementDelta.F_OPENED) != 0) { 849 kind = IJavaElementDelta.ADDED; } 851 if ((flags & IJavaElementDelta.F_CLOSED) != 0) { 852 kind = IJavaElementDelta.REMOVED; } 854 switch (kind) { 855 case IJavaElementDelta.ADDED : 856 try { 857 IClasspathEntry[] classpath = ((JavaProject)this.javaProject()).getExpandedClasspath(); 859 for (int i = 0; i < classpath.length; i++) { 860 if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT 861 && classpath[i].getPath().equals(element.getPath())) { 862 return true; 863 } 864 } 865 if (this.focusType != null) { 866 classpath = ((JavaProject)element).getExpandedClasspath(); 868 IPath hierarchyProject = javaProject().getPath(); 869 for (int i = 0; i < classpath.length; i++) { 870 if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT 871 && classpath[i].getPath().equals(hierarchyProject)) { 872 return true; 873 } 874 } 875 } 876 return false; 877 } catch (JavaModelException e) { 878 return false; 879 } 880 case IJavaElementDelta.REMOVED : 881 IJavaElement[] pkgs = this.packageRegion.getElements(); 884 for (int i = 0; i < pkgs.length; i++) { 885 IJavaProject javaProject = pkgs[i].getJavaProject(); 886 if (javaProject != null && javaProject.equals(element)) { 887 return true; 888 } 889 } 890 return false; 891 case IJavaElementDelta.CHANGED : 892 return isAffectedByChildren(delta); 893 } 894 return false; 895 } 896 899 private boolean isAffectedByPackageFragment(IJavaElementDelta delta, PackageFragment element) { 900 switch (delta.getKind()) { 901 case IJavaElementDelta.ADDED : 902 return this.projectRegion.contains(element); 905 case IJavaElementDelta.REMOVED : 906 return packageRegionContainsSamePackageFragment(element); 908 case IJavaElementDelta.CHANGED : 909 return isAffectedByChildren(delta); 911 } 912 return false; 913 } 914 917 private boolean isAffectedByPackageFragmentRoot(IJavaElementDelta delta, IJavaElement element) { 918 switch (delta.getKind()) { 919 case IJavaElementDelta.ADDED : 920 return this.projectRegion.contains(element); 921 case IJavaElementDelta.REMOVED : 922 case IJavaElementDelta.CHANGED : 923 int flags = delta.getFlags(); 924 if ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) { 925 if (this.projectRegion != null) { 927 IPackageFragmentRoot root = (IPackageFragmentRoot)element; 928 IPath rootPath = root.getPath(); 929 IJavaElement[] elements = this.projectRegion.getElements(); 930 for (int i = 0; i < elements.length; i++) { 931 JavaProject javaProject = (JavaProject)elements[i]; 932 try { 933 IClasspathEntry entry = javaProject.getClasspathEntryFor(rootPath); 934 if (entry != null) { 935 return true; 936 } 937 } catch (JavaModelException e) { 938 } 940 } 941 } 942 } 943 if ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0 || (flags & IJavaElementDelta.F_CONTENT) > 0) { 944 IJavaElement[] pkgs = this.packageRegion.getElements(); 949 for (int i = 0; i < pkgs.length; i++) { 950 if (pkgs[i].getParent().equals(element)) { 951 return true; 952 } 953 } 954 return false; 955 } 956 } 957 return isAffectedByChildren(delta); 958 } 959 963 protected boolean isAffectedByOpenable(IJavaElementDelta delta, IJavaElement element) { 964 if (element instanceof CompilationUnit) { 965 CompilationUnit cu = (CompilationUnit)element; 966 ChangeCollector collector = this.changeCollector; 967 if (collector == null) { 968 collector = new ChangeCollector(this); 969 } 970 try { 971 collector.addChange(cu, delta); 972 } catch (JavaModelException e) { 973 if (DEBUG) 974 e.printStackTrace(); 975 } 976 if (cu.isWorkingCopy()) { 977 this.changeCollector = collector; 979 return false; 980 } else { 981 return collector.needsRefresh(); 982 } 983 } else if (element instanceof ClassFile) { 984 switch (delta.getKind()) { 985 case IJavaElementDelta.REMOVED: 986 return this.files.get(element) != null; 987 case IJavaElementDelta.ADDED: 988 IType type = ((ClassFile)element).getType(); 989 String typeName = type.getElementName(); 990 if (hasSupertype(typeName) 991 || subtypesIncludeSupertypeOf(type) 992 || this.missingTypes.contains(typeName)) { 993 994 return true; 995 } 996 break; 997 case IJavaElementDelta.CHANGED: 998 IJavaElementDelta[] children = delta.getAffectedChildren(); 999 for (int i = 0, length = children.length; i < length; i++) { 1000 IJavaElementDelta child = children[i]; 1001 IJavaElement childElement = child.getElement(); 1002 if (childElement instanceof IType) { 1003 type = (IType)childElement; 1004 boolean hasVisibilityChange = (delta.getFlags() & IJavaElementDelta.F_MODIFIERS) > 0; 1005 boolean hasSupertypeChange = (delta.getFlags() & IJavaElementDelta.F_SUPER_TYPES) > 0; 1006 if ((hasVisibilityChange && hasSupertype(type.getElementName())) 1007 || (hasSupertypeChange && includesTypeOrSupertype(type))) { 1008 return true; 1009 } 1010 } 1011 } 1012 break; 1013 } 1014 } 1015 return false; 1016} 1017private boolean isInterface(IType type) { 1018 int flags = this.getCachedFlags(type); 1019 if (flags == -1) { 1020 try { 1021 return type.isInterface(); 1022 } catch (JavaModelException e) { 1023 return false; 1024 } 1025 } else { 1026 return Flags.isInterface(flags); 1027 } 1028} 1029 1032public IJavaProject javaProject() { 1033 return this.focusType.getJavaProject(); 1034} 1035protected static byte[] readUntil(InputStream input, byte separator) throws JavaModelException, IOException { 1036 return readUntil(input, separator, 0); 1037} 1038protected static byte[] readUntil(InputStream input, byte separator, int offset) throws IOException , JavaModelException{ 1039 int length = 0; 1040 byte[] bytes = new byte[SIZE]; 1041 byte b; 1042 while((b = (byte)input.read()) != separator && b != -1) { 1043 if(bytes.length == length) { 1044 System.arraycopy(bytes, 0, bytes = new byte[length*2], 0, length); 1045 } 1046 bytes[length++] = b; 1047 } 1048 if(b == -1) { 1049 throw new JavaModelException(new JavaModelStatus(IStatus.ERROR)); 1050 } 1051 System.arraycopy(bytes, 0, bytes = new byte[length + offset], offset, length); 1052 return bytes; 1053} 1054public static ITypeHierarchy load(IType type, InputStream input, WorkingCopyOwner owner) throws JavaModelException { 1055 try { 1056 TypeHierarchy typeHierarchy = new TypeHierarchy(); 1057 typeHierarchy.initialize(1); 1058 1059 IType[] types = new IType[SIZE]; 1060 int typeCount = 0; 1061 1062 byte version = (byte)input.read(); 1063 1064 if(version != VERSION) { 1065 throw new JavaModelException(new JavaModelStatus(IStatus.ERROR)); 1066 } 1067 byte generalInfo = (byte)input.read(); 1068 if((generalInfo & COMPUTE_SUBTYPES) != 0) { 1069 typeHierarchy.computeSubtypes = true; 1070 } 1071 1072 byte b; 1073 byte[] bytes; 1074 1075 bytes = readUntil(input, SEPARATOR1); 1077 if(bytes.length > 0) { 1078 typeHierarchy.project = (IJavaProject)JavaCore.create(new String (bytes)); 1079 typeHierarchy.scope = SearchEngine.createJavaSearchScope(new IJavaElement[] {typeHierarchy.project}); 1080 } else { 1081 typeHierarchy.project = null; 1082 typeHierarchy.scope = SearchEngine.createWorkspaceScope(); 1083 } 1084 1085 { 1087 bytes = readUntil(input, SEPARATOR1); 1088 byte[] missing; 1089 int j = 0; 1090 int length = bytes.length; 1091 for (int i = 0; i < length; i++) { 1092 b = bytes[i]; 1093 if(b == SEPARATOR2) { 1094 missing = new byte[i - j]; 1095 System.arraycopy(bytes, j, missing, 0, i - j); 1096 typeHierarchy.missingTypes.add(new String (missing)); 1097 j = i + 1; 1098 } 1099 } 1100 System.arraycopy(bytes, j, missing = new byte[length - j], 0, length - j); 1101 typeHierarchy.missingTypes.add(new String (missing)); 1102 } 1103 1104 while((b = (byte)input.read()) != SEPARATOR1 && b != -1) { 1106 bytes = readUntil(input, SEPARATOR4, 1); 1107 bytes[0] = b; 1108 IType element = (IType)JavaCore.create(new String (bytes), owner); 1109 1110 if(types.length == typeCount) { 1111 System.arraycopy(types, 0, types = new IType[typeCount * 2], 0, typeCount); 1112 } 1113 types[typeCount++] = element; 1114 1115 bytes = readUntil(input, SEPARATOR4); 1117 Integer flags = bytesToFlags(bytes); 1118 if(flags != null) { 1119 typeHierarchy.cacheFlags(element, flags.intValue()); 1120 } 1121 1122 byte info = (byte)input.read(); 1124 1125 if((info & INTERFACE) != 0) { 1126 typeHierarchy.addInterface(element); 1127 } 1128 if((info & COMPUTED_FOR) != 0) { 1129 if(!element.equals(type)) { 1130 throw new JavaModelException(new JavaModelStatus(IStatus.ERROR)); 1131 } 1132 typeHierarchy.focusType = element; 1133 } 1134 if((info & ROOT) != 0) { 1135 typeHierarchy.addRootClass(element); 1136 } 1137 } 1138 1139 while((b = (byte)input.read()) != SEPARATOR1 && b != -1) { 1141 bytes = readUntil(input, SEPARATOR3, 1); 1142 bytes[0] = b; 1143 int subClass = new Integer (new String (bytes)).intValue(); 1144 1145 bytes = readUntil(input, SEPARATOR1); 1147 int superClass = new Integer (new String (bytes)).intValue(); 1148 1149 typeHierarchy.cacheSuperclass( 1150 types[subClass], 1151 types[superClass]); 1152 } 1153 1154 while((b = (byte)input.read()) != SEPARATOR1 && b != -1) { 1156 bytes = readUntil(input, SEPARATOR3, 1); 1157 bytes[0] = b; 1158 int subClass = new Integer (new String (bytes)).intValue(); 1159 1160 bytes = readUntil(input, SEPARATOR1); 1162 IType[] superInterfaces = new IType[(bytes.length / 2) + 1]; 1163 int interfaceCount = 0; 1164 1165 int j = 0; 1166 byte[] b2; 1167 for (int i = 0; i < bytes.length; i++) { 1168 if(bytes[i] == SEPARATOR2){ 1169 b2 = new byte[i - j]; 1170 System.arraycopy(bytes, j, b2, 0, i - j); 1171 j = i + 1; 1172 superInterfaces[interfaceCount++] = types[new Integer (new String (b2)).intValue()]; 1173 } 1174 } 1175 b2 = new byte[bytes.length - j]; 1176 System.arraycopy(bytes, j, b2, 0, bytes.length - j); 1177 superInterfaces[interfaceCount++] = types[new Integer (new String (b2)).intValue()]; 1178 System.arraycopy(superInterfaces, 0, superInterfaces = new IType[interfaceCount], 0, interfaceCount); 1179 1180 typeHierarchy.cacheSuperInterfaces( 1181 types[subClass], 1182 superInterfaces); 1183 } 1184 if(b == -1) { 1185 throw new JavaModelException(new JavaModelStatus(IStatus.ERROR)); 1186 } 1187 return typeHierarchy; 1188 } catch(IOException e){ 1189 throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); 1190 } 1191} 1192 1196protected boolean packageRegionContainsSamePackageFragment(PackageFragment element) { 1197 IJavaElement[] pkgs = this.packageRegion.getElements(); 1198 for (int i = 0; i < pkgs.length; i++) { 1199 PackageFragment pkg = (PackageFragment) pkgs[i]; 1200 if (Util.equalArraysOrNull(pkg.names, element.names)) 1201 return true; 1202 } 1203 return false; 1204} 1205 1206 1211public synchronized void refresh(IProgressMonitor monitor) throws JavaModelException { 1212 try { 1213 this.progressMonitor = monitor; 1214 if (monitor != null) { 1215 monitor.beginTask( 1216 this.focusType != null ? 1217 Messages.bind(Messages.hierarchy_creatingOnType, this.focusType.getFullyQualifiedName()) : 1218 Messages.hierarchy_creating, 1219 100); 1220 } 1221 long start = -1; 1222 if (DEBUG) { 1223 start = System.currentTimeMillis(); 1224 if (this.computeSubtypes) { 1225 System.out.println("CREATING TYPE HIERARCHY [" + Thread.currentThread() + "]"); } else { 1227 System.out.println("CREATING SUPER TYPE HIERARCHY [" + Thread.currentThread() + "]"); } 1229 if (this.focusType != null) { 1230 System.out.println(" on type " + ((JavaElement)this.focusType).toStringWithAncestors()); } 1232 } 1233 1234 compute(); 1235 initializeRegions(); 1236 this.needsRefresh = false; 1237 this.changeCollector = null; 1238 1239 if (DEBUG) { 1240 if (this.computeSubtypes) { 1241 System.out.println("CREATED TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); } else { 1243 System.out.println("CREATED SUPER TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); } 1245 System.out.println(this.toString()); 1246 } 1247 } catch (JavaModelException e) { 1248 throw e; 1249 } catch (CoreException e) { 1250 throw new JavaModelException(e); 1251 } finally { 1252 if (monitor != null) { 1253 monitor.done(); 1254 } 1255 this.progressMonitor = null; 1256 } 1257} 1258 1259 1262public synchronized void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) { 1263 ArrayList listeners = this.changeListeners; 1264 if (listeners == null) { 1265 return; 1266 } 1267 listeners.remove(listener); 1268 1269 if (listeners.isEmpty()) { 1271 JavaCore.removeElementChangedListener(this); 1272 } 1273} 1274 1277public void store(OutputStream output, IProgressMonitor monitor) throws JavaModelException { 1278 try { 1279 Hashtable hashtable = new Hashtable (); 1281 Hashtable hashtable2 = new Hashtable (); 1282 int count = 0; 1283 1284 if(this.focusType != null) { 1285 Integer index = new Integer (count++); 1286 hashtable.put(this.focusType, index); 1287 hashtable2.put(index, this.focusType); 1288 } 1289 Object [] types = this.classToSuperclass.entrySet().toArray(); 1290 for (int i = 0; i < types.length; i++) { 1291 Map.Entry entry = (Map.Entry ) types[i]; 1292 Object t = entry.getKey(); 1293 if(hashtable.get(t) == null) { 1294 Integer index = new Integer (count++); 1295 hashtable.put(t, index); 1296 hashtable2.put(index, t); 1297 } 1298 Object superClass = entry.getValue(); 1299 if(superClass != null && hashtable.get(superClass) == null) { 1300 Integer index = new Integer (count++); 1301 hashtable.put(superClass, index); 1302 hashtable2.put(index, superClass); 1303 } 1304 } 1305 types = this.typeToSuperInterfaces.entrySet().toArray(); 1306 for (int i = 0; i < types.length; i++) { 1307 Map.Entry entry = (Map.Entry ) types[i]; 1308 Object t = entry.getKey(); 1309 if(hashtable.get(t) == null) { 1310 Integer index = new Integer (count++); 1311 hashtable.put(t, index); 1312 hashtable2.put(index, t); 1313 } 1314 Object [] sp = (Object []) entry.getValue(); 1315 if(sp != null) { 1316 for (int j = 0; j < sp.length; j++) { 1317 Object superInterface = sp[j]; 1318 if(sp[j] != null && hashtable.get(superInterface) == null) { 1319 Integer index = new Integer (count++); 1320 hashtable.put(superInterface, index); 1321 hashtable2.put(index, superInterface); 1322 } 1323 } 1324 } 1325 } 1326 output.write(VERSION); 1328 1329 byte generalInfo = 0; 1331 if(this.computeSubtypes) { 1332 generalInfo |= COMPUTE_SUBTYPES; 1333 } 1334 output.write(generalInfo); 1335 1336 if(this.project != null) { 1338 output.write(this.project.getHandleIdentifier().getBytes()); 1339 } 1340 output.write(SEPARATOR1); 1341 1342 for (int i = 0; i < this.missingTypes.size(); i++) { 1344 if(i != 0) { 1345 output.write(SEPARATOR2); 1346 } 1347 output.write(((String )this.missingTypes.get(i)).getBytes()); 1348 1349 } 1350 output.write(SEPARATOR1); 1351 1352 for (int i = 0; i < count ; i++) { 1354 IType t = (IType)hashtable2.get(new Integer (i)); 1355 1356 output.write(t.getHandleIdentifier().getBytes()); 1358 output.write(SEPARATOR4); 1359 output.write(flagsToBytes((Integer )this.typeFlags.get(t))); 1360 output.write(SEPARATOR4); 1361 byte info = CLASS; 1362 if(this.focusType != null && this.focusType.equals(t)) { 1363 info |= COMPUTED_FOR; 1364 } 1365 if(this.interfaces.contains(t)) { 1366 info |= INTERFACE; 1367 } 1368 if(this.rootClasses.contains(t)) { 1369 info |= ROOT; 1370 } 1371 output.write(info); 1372 } 1373 output.write(SEPARATOR1); 1374 1375 types = this.classToSuperclass.entrySet().toArray(); 1377 for (int i = 0; i < types.length; i++) { 1378 Map.Entry entry = (Map.Entry ) types[i]; 1379 IJavaElement key = (IJavaElement) entry.getKey(); 1380 IJavaElement value = (IJavaElement) entry.getValue(); 1381 1382 output.write(((Integer )hashtable.get(key)).toString().getBytes()); 1383 output.write('>'); 1384 output.write(((Integer )hashtable.get(value)).toString().getBytes()); 1385 output.write(SEPARATOR1); 1386 } 1387 output.write(SEPARATOR1); 1388 1389 types = this.typeToSuperInterfaces.entrySet().toArray(); 1391 for (int i = 0; i < types.length; i++) { 1392 Map.Entry entry = (Map.Entry ) types[i]; 1393 IJavaElement key = (IJavaElement) entry.getKey(); 1394 IJavaElement[] values = (IJavaElement[]) entry.getValue(); 1395 1396 if(values.length > 0) { 1397 output.write(((Integer )hashtable.get(key)).toString().getBytes()); 1398 output.write(SEPARATOR3); 1399 for (int j = 0; j < values.length; j++) { 1400 IJavaElement value = values[j]; 1401 if(j != 0) output.write(SEPARATOR2); 1402 output.write(((Integer )hashtable.get(value)).toString().getBytes()); 1403 } 1404 output.write(SEPARATOR1); 1405 } 1406 } 1407 output.write(SEPARATOR1); 1408 } catch(IOException e) { 1409 throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); 1410 } 1411} 1412 1417boolean subtypesIncludeSupertypeOf(IType type) { 1418 String superclassName = null; 1420 try { 1421 superclassName = type.getSuperclassName(); 1422 } catch (JavaModelException e) { 1423 if (DEBUG) { 1424 e.printStackTrace(); 1425 } 1426 return false; 1427 } 1428 if (superclassName == null) { 1429 superclassName = "Object"; } 1431 int dot = -1; 1432 String simpleSuper = (dot = superclassName.lastIndexOf('.')) > -1 ? 1433 superclassName.substring(dot + 1) : 1434 superclassName; 1435 if (hasSubtypeNamed(simpleSuper)) { 1436 return true; 1437 } 1438 1439 String [] interfaceNames = null; 1441 try { 1442 interfaceNames = type.getSuperInterfaceNames(); 1443 } catch (JavaModelException e) { 1444 if (DEBUG) 1445 e.printStackTrace(); 1446 return false; 1447 } 1448 for (int i = 0, length = interfaceNames.length; i < length; i++) { 1449 dot = -1; 1450 String interfaceName = interfaceNames[i]; 1451 String simpleInterface = (dot = interfaceName.lastIndexOf('.')) > -1 ? 1452 interfaceName.substring(dot) : 1453 interfaceName; 1454 if (hasSubtypeNamed(simpleInterface)) { 1455 return true; 1456 } 1457 } 1458 1459 return false; 1460} 1461 1464public String toString() { 1465 StringBuffer buffer = new StringBuffer (); 1466 buffer.append("Focus: "); buffer.append(this.focusType == null ? "<NONE>" : ((JavaElement)this.focusType).toStringWithAncestors(false)); buffer.append("\n"); if (exists()) { 1470 if (this.focusType != null) { 1471 buffer.append("Super types:\n"); toString(buffer, this.focusType, 1, true); 1473 buffer.append("Sub types:\n"); toString(buffer, this.focusType, 1, false); 1475 } else { 1476 buffer.append("Sub types of root classes:\n"); IJavaElement[] roots = Util.sortCopy(getRootClasses()); 1478 for (int i= 0; i < roots.length; i++) { 1479 toString(buffer, (IType) roots[i], 1, false); 1480 } 1481 } 1482 if (this.rootClasses.size > 1) { 1483 buffer.append("Root classes:\n"); IJavaElement[] roots = Util.sortCopy(getRootClasses()); 1485 for (int i = 0, length = roots.length; i < length; i++) { 1486 toString(buffer, (IType) roots[i], 1, false); 1487 } 1488 } else if (this.rootClasses.size == 0) { 1489 buffer.append("No root classes"); } 1492 } else { 1493 buffer.append("(Hierarchy became stale)"); } 1495 return buffer.toString(); 1496} 1497 1502private void toString(StringBuffer buffer, IType type, int indent, boolean ascendant) { 1503 IType[] types= ascendant ? getSupertypes(type) : getSubtypes(type); 1504 IJavaElement[] sortedTypes = Util.sortCopy(types); 1505 for (int i= 0; i < sortedTypes.length; i++) { 1506 for (int j= 0; j < indent; j++) { 1507 buffer.append(" "); } 1509 JavaElement element = (JavaElement)sortedTypes[i]; 1510 buffer.append(element.toStringWithAncestors(false)); 1511 buffer.append('\n'); 1512 toString(buffer, types[i], indent + 1, ascendant); 1513 } 1514} 1515 1519boolean hasSupertype(String simpleName) { 1520 for(Iterator iter = this.classToSuperclass.values().iterator(); iter.hasNext();){ 1521 IType superType = (IType)iter.next(); 1522 if (superType.getElementName().equals(simpleName)) { 1523 return true; 1524 } 1525 } 1526 return false; 1527} 1528 1531protected void worked(int work) { 1532 if (this.progressMonitor != null) { 1533 this.progressMonitor.worked(work); 1534 checkCanceled(); 1535 } 1536} 1537} 1538 | Popular Tags |