<s> package org . eclipse . jdt . internal . core . hierarchy ; import java . io . IOException ; import java . io . InputStream ; import java . io . OutputStream ; import java . util . ArrayList ; import java . util . HashMap ; import java . util . Hashtable ; import java . util . Iterator ; import java . util . Map ; import org . eclipse . core . runtime . CoreException ; import org . eclipse . core . runtime . IPath ; import org . eclipse . core . runtime . IProgressMonitor ; import org . eclipse . core . runtime . ISafeRunnable ; import org . eclipse . core . runtime . IStatus ; import org . eclipse . core . runtime . OperationCanceledException ; import org . eclipse . core . runtime . SafeRunner ; import org . eclipse . jdt . core . * ; import org . eclipse . jdt . core . search . IJavaSearchScope ; import org . eclipse . jdt . core . search . SearchEngine ; import org . eclipse . jdt . internal . core . * ; import org . eclipse . jdt . internal . core . util . Messages ; import org . eclipse . jdt . internal . core . util . Util ; public class TypeHierarchy implements ITypeHierarchy , IElementChangedListener { public static boolean DEBUG = false ; static final byte VERSION = 0x0000 ; static final byte SEPARATOR1 = '\n' ; static final byte SEPARATOR2 = ',' ; static final byte SEPARATOR3 = '>' ; static final byte SEPARATOR4 = '\r' ; static final byte COMPUTE_SUBTYPES = 0x0001 ; static final byte CLASS = 0x0000 ; static final byte INTERFACE = 0x0001 ; static final byte COMPUTED_FOR = 0x0002 ; static final byte ROOT = 0x0004 ; static final byte [ ] NO_FLAGS = new byte [ ] { } ; static final int SIZE = 10 ; protected IJavaProject project ; protected IType focusType ; protected ICompilationUnit [ ] workingCopies ; protected Map classToSuperclass ; protected Map typeToSuperInterfaces ; protected Map typeToSubtypes ; protected Map typeFlags ; protected TypeVector rootClasses = new TypeVector ( ) ; protected ArrayList interfaces = new ArrayList ( 10 ) ; public ArrayList missingTypes = new ArrayList ( 4 ) ; protected static final IType [ ] NO_TYPE = new IType [ 0 ] ; protected IProgressMonitor progressMonitor = null ; protected ArrayList changeListeners = null ; public Map files = null ; protected Region packageRegion = null ; protected Region projectRegion = null ; protected boolean computeSubtypes ; IJavaSearchScope scope ; public boolean needsRefresh = true ; protected ChangeCollector changeCollector ; public TypeHierarchy ( ) { } public TypeHierarchy ( IType type , ICompilationUnit [ ] workingCopies , IJavaProject project , boolean computeSubtypes ) { this ( type , workingCopies , SearchEngine . createJavaSearchScope ( new IJavaElement [ ] { project } ) , computeSubtypes ) ; this . project = project ; } public TypeHierarchy ( IType type , ICompilationUnit [ ] workingCopies , IJavaSearchScope scope , boolean computeSubtypes ) { this . focusType = type == null ? null : ( IType ) ( ( JavaElement ) type ) . unresolved ( ) ; this . workingCopies = workingCopies ; this . computeSubtypes = computeSubtypes ; this . scope = scope ; } protected void initializeRegions ( ) { IType [ ] allTypes = getAllTypes ( ) ; for ( int i = 0 ; i < allTypes . length ; i ++ ) { IType type = allTypes [ i ] ; Openable o = ( Openable ) ( ( JavaElement ) type ) . getOpenableParent ( ) ; if ( o != null ) { ArrayList types = ( ArrayList ) this . files . get ( o ) ; if ( types == null ) { types = new ArrayList ( ) ; this . files . put ( o , types ) ; } types . add ( type ) ; } IPackageFragment pkg = type . getPackageFragment ( ) ; this . packageRegion . add ( pkg ) ; IJavaProject declaringProject = type . getJavaProject ( ) ; if ( declaringProject != null ) { this . projectRegion . add ( declaringProject ) ; } checkCanceled ( ) ; } } private void addAllCheckingDuplicates ( ArrayList list , IType [ ] collection ) { for ( int i = 0 ; i < collection . length ; i ++ ) { IType element = collection [ i ] ; if ( ! list . contains ( element ) ) { list . add ( element ) ; } } } protected void addInterface ( IType type ) { this . interfaces . add ( type ) ; } protected void addRootClass ( IType type ) { if ( this . rootClasses . contains ( type ) ) return ; this . rootClasses . add ( type ) ; } protected void addSubtype ( IType type , IType subtype ) { TypeVector subtypes = ( TypeVector ) this . typeToSubtypes . get ( type ) ; if ( subtypes == null ) { subtypes = new TypeVector ( ) ; this . typeToSubtypes . put ( type , subtypes ) ; } if ( ! subtypes . contains ( subtype ) ) { subtypes . add ( subtype ) ; } } public synchronized void addTypeHierarchyChangedListener ( ITypeHierarchyChangedListener listener ) { ArrayList listeners = this . changeListeners ; if ( listeners == null ) { this . changeListeners = listeners = new ArrayList ( ) ; } if ( listeners . size ( ) == 0 ) { JavaCore . addElementChangedListener ( this ) ; } if ( listeners . indexOf ( listener ) == - 1 ) { listeners . add ( listener ) ; } } private static Integer bytesToFlags ( byte [ ] bytes ) { if ( bytes != null && bytes . length > 0 ) { return new Integer ( new String ( bytes ) ) ; } else { return null ; } } public void cacheFlags ( IType type , int flags ) { this . typeFlags . put ( type , new Integer ( flags ) ) ; } protected void cacheSuperclass ( IType type , IType superclass ) { if ( superclass != null ) { this . classToSuperclass . put ( type , superclass ) ; addSubtype ( superclass , type ) ; } } protected void cacheSuperInterfaces ( IType type , IType [ ] superinterfaces ) { this . typeToSuperInterfaces . put ( type , superinterfaces ) ; for ( int i = 0 ; i < superinterfaces . length ; i ++ ) { IType superinterface = superinterfaces [ i ] ; if ( superinterface != null ) { addSubtype ( superinterface , type ) ; } } } protected void checkCanceled ( ) { if ( this . progressMonitor != null && this . progressMonitor . isCanceled ( ) ) { throw new OperationCanceledException ( ) ; } } protected void compute ( ) throws JavaModelException , CoreException { if ( this . focusType != null ) { HierarchyBuilder builder = new IndexBasedHierarchyBuilder ( this , this . scope ) ; builder . build ( this . computeSubtypes ) ; } } public boolean contains ( IType type ) { if ( this . classToSuperclass . get ( type ) != null ) { return true ; } if ( this . rootClasses . contains ( type ) ) return true ; if ( this . interfaces . contains ( type ) ) return true ; return false ; } public void elementChanged ( ElementChangedEvent event ) { if ( this . needsRefresh ) return ; if ( isAffected ( event . getDelta ( ) , event . getType ( ) ) ) { this . needsRefresh = true ; fireChange ( ) ; } } public boolean exists ( ) { if ( ! this . needsRefresh ) return true ; return ( this . focusType == null || this . focusType . exists ( ) ) && javaProject ( ) . exists ( ) ; } public void fireChange ( ) { ArrayList listeners = getClonedChangeListeners ( ) ; if ( listeners == null ) { return ; } if ( DEBUG ) { System . out . println ( "" + Thread . currentThread ( ) + "]" ) ; if ( this . focusType != null ) { System . out . println ( "" + ( ( JavaElement ) this . focusType ) . toStringWithAncestors ( ) ) ; } } for ( int i = 0 ; i < listeners . size ( ) ; i ++ ) { final ITypeHierarchyChangedListener listener = ( ITypeHierarchyChangedListener ) listeners . get ( i ) ; SafeRunner . run ( new ISafeRunnable ( ) { public void handleException ( Throwable exception ) { Util . log ( exception , "" ) ; } public void run ( ) throws Exception { listener . typeHierarchyChanged ( TypeHierarchy . this ) ; } } ) ; } } private synchronized ArrayList getClonedChangeListeners ( ) { ArrayList listeners = this . changeListeners ; if ( listeners == null ) { return null ; } return ( ArrayList ) listeners . clone ( ) ; } private static byte [ ] flagsToBytes ( Integer flags ) { if ( flags != null ) { return flags . toString ( ) . getBytes ( ) ; } else { return NO_FLAGS ; } } public IType [ ] getAllClasses ( ) { TypeVector classes = this . rootClasses . copy ( ) ; for ( Iterator iter = this . classToSuperclass . keySet ( ) . iterator ( ) ; iter . hasNext ( ) ; ) { classes . add ( ( IType ) iter . next ( ) ) ; } return classes . elements ( ) ; } public IType [ ] getAllInterfaces ( ) { IType [ ] collection = new IType [ this . interfaces . size ( ) ] ; this . interfaces . toArray ( collection ) ; return collection ; } public IType [ ] getAllSubtypes ( IType type ) { return getAllSubtypesForType ( type ) ; } private IType [ ] getAllSubtypesForType ( IType type ) { ArrayList subTypes = new ArrayList ( ) ; getAllSubtypesForType0 ( type , subTypes ) ; IType [ ] subClasses = new IType [ subTypes . size ( ) ] ; subTypes . toArray ( subClasses ) ; return subClasses ; } private void getAllSubtypesForType0 ( IType type , ArrayList subs ) { IType [ ] subTypes = getSubtypesForType ( type ) ; if ( subTypes . length != 0 ) { for ( int i = 0 ; i < subTypes . length ; i ++ ) { IType subType = subTypes [ i ] ; subs . add ( subType ) ; getAllSubtypesForType0 ( subType , subs ) ; } } } public IType [ ] getAllSuperclasses ( IType type ) { IType superclass = getSuperclass ( type ) ; TypeVector supers = new TypeVector ( ) ; while ( superclass != null ) { supers . add ( superclass ) ; superclass = getSuperclass ( superclass ) ; } return supers . elements ( ) ; } public IType [ ] getAllSuperInterfaces ( IType type ) { ArrayList supers = getAllSuperInterfaces0 ( type , null ) ; if ( supers == null ) return NO_TYPE ; IType [ ] superinterfaces = new IType [ supers . size ( ) ] ; supers . toArray ( superinterfaces ) ; return superinterfaces ; } private ArrayList getAllSuperInterfaces0 ( IType type , ArrayList supers ) { IType [ ] superinterfaces = ( IType [ ] ) this . typeToSuperInterfaces . get ( type ) ; if ( superinterfaces == null ) return supers ; if ( superinterfaces . length != 0 ) { if ( supers == null ) supers = new ArrayList ( ) ; addAllCheckingDuplicates ( supers , superinterfaces ) ; for ( int i = 0 ; i < superinterfaces . length ; i ++ ) { supers = getAllSuperInterfaces0 ( superinterfaces [ i ] , supers ) ; } } IType superclass = ( IType ) this . classToSuperclass . get ( type ) ; if ( superclass != null ) { supers = getAllSuperInterfaces0 ( superclass , supers ) ; } return supers ; } public IType [ ] getAllSupertypes ( IType type ) { ArrayList supers = getAllSupertypes0 ( type , null ) ; if ( supers == null ) return NO_TYPE ; IType [ ] supertypes = new IType [ supers . size ( ) ] ; supers . toArray ( supertypes ) ; return supertypes ; } private ArrayList getAllSupertypes0 ( IType type , ArrayList supers ) { IType [ ] superinterfaces = ( IType [ ] ) this . typeToSuperInterfaces . get ( type ) ; if ( superinterfaces == null ) return supers ; if ( superinterfaces . length != 0 ) { if ( supers == null ) supers = new ArrayList ( ) ; addAllCheckingDuplicates ( supers , superinterfaces ) ; for ( int i = 0 ; i < superinterfaces . length ; i ++ ) { supers = getAllSuperInterfaces0 ( superinterfaces [ i ] , supers ) ; } } IType superclass = ( IType ) this . classToSuperclass . get ( type ) ; if ( superclass != null ) { if ( supers == null ) supers = new ArrayList ( ) ; supers . add ( superclass ) ; supers = getAllSupertypes0 ( superclass , supers ) ; } return supers ; } public IType [ ] getAllTypes ( ) { IType [ ] classes = getAllClasses ( ) ; int classesLength = classes . length ; IType [ ] allInterfaces = getAllInterfaces ( ) ; int interfacesLength = allInterfaces . length ; IType [ ] all = new IType [ classesLength + interfacesLength ] ; System . arraycopy ( classes , 0 , all , 0 , classesLength ) ; System . arraycopy ( allInterfaces , 0 , all , classesLength , interfacesLength ) ; return all ; } public int getCachedFlags ( IType type ) { Integer flagObject = ( Integer ) this . typeFlags . get ( type ) ; if ( flagObject != null ) { return flagObject . intValue ( ) ; } return - 1 ; } public IType [ ] getExtendingInterfaces ( IType type ) { if ( ! isInterface ( type ) ) return NO_TYPE ; return getExtendingInterfaces0 ( type ) ; } private IType [ ] getExtendingInterfaces0 ( IType extendedInterface ) { Iterator iter = this . typeToSuperInterfaces . entrySet ( ) . iterator ( ) ; ArrayList interfaceList = new ArrayList ( ) ; while ( iter . hasNext ( ) ) { Map . Entry entry = ( Map . Entry ) iter . next ( ) ; IType type = ( IType ) entry . getKey ( ) ; if ( ! isInterface ( type ) ) { continue ; } IType [ ] superInterfaces = ( IType [ ] ) entry . getValue ( ) ; if ( superInterfaces != null ) { for ( int i = 0 ; i < superInterfaces . length ; i ++ ) { IType superInterface = superInterfaces [ i ] ; if ( superInterface . equals ( extendedInterface ) ) { interfaceList . add ( type ) ; } } } } IType [ ] extendingInterfaces = new IType [ interfaceList . size ( ) ] ; interfaceList . toArray ( extendingInterfaces ) ; return extendingInterfaces ; } public IType [ ] getImplementingClasses ( IType type ) { if ( ! isInterface ( type ) ) { return NO_TYPE ; } return getImplementingClasses0 ( type ) ; } private IType [ ] getImplementingClasses0 ( IType interfce ) { Iterator iter = this . typeToSuperInterfaces . entrySet ( ) . iterator ( ) ; ArrayList iMenters = new ArrayList ( ) ; while ( iter . hasNext ( ) ) { Map . Entry entry = ( Map . Entry ) iter . next ( ) ; IType type = ( IType ) entry . getKey ( ) ; if ( isInterface ( type ) ) { continue ; } IType [ ] types = ( IType [ ] ) entry . getValue ( ) ; for ( int i = 0 ; i < types . length ; i ++ ) { IType iFace = types [ i ] ; if ( iFace . equals ( interfce ) ) { iMenters . add ( type ) ; } } } IType [ ] implementers = new IType [ iMenters . size ( ) ] ; iMenters . toArray ( implementers ) ; return implementers ; } public IType [ ] getRootClasses ( ) { return this . rootClasses . elements ( ) ; } public IType [ ] getRootInterfaces ( ) { IType [ ] allInterfaces = getAllInterfaces ( ) ; IType [ ] roots = new IType [ allInterfaces . length ] ; int rootNumber = 0 ; for ( int i = 0 ; i < allInterfaces . length ; i ++ ) { IType [ ] superInterfaces = getSuperInterfaces ( allInterfaces [ i ] ) ; if ( superInterfaces == null || superInterfaces . length == 0 ) { roots [ rootNumber ++ ] = allInterfaces [ i ] ; } } IType [ ] result = new IType [ rootNumber ] ; if ( result . length > 0 ) { System . arraycopy ( roots , 0 , result , 0 , rootNumber ) ; } return result ; } public IType [ ] getSubclasses ( IType type ) { if ( isInterface ( type ) ) { return NO_TYPE ; } TypeVector vector = ( TypeVector ) this . typeToSubtypes . get ( type ) ; if ( vector == null ) return NO_TYPE ; else return vector . elements ( ) ; } public IType [ ] getSubtypes ( IType type ) { return getSubtypesForType ( type ) ; } private IType [ ] getSubtypesForType ( IType type ) { TypeVector vector = ( TypeVector ) this . typeToSubtypes . get ( type ) ; if ( vector == null ) return NO_TYPE ; else return vector . elements ( ) ; } public IType getSuperclass ( IType type ) { if ( isInterface ( type ) ) { return null ; } return ( IType ) this . classToSuperclass . get ( type ) ; } public IType [ ] getSuperInterfaces ( IType type ) { IType [ ] types = ( IType [ ] ) this . typeToSuperInterfaces . get ( type ) ; if ( types == null ) { return NO_TYPE ; } return types ; } public IType [ ] getSupertypes ( IType type ) { IType superclass = getSuperclass ( type ) ; if ( superclass == null ) { return getSuperInterfaces ( type ) ; } else { TypeVector superTypes = new TypeVector ( getSuperInterfaces ( type ) ) ; superTypes . add ( superclass ) ; return superTypes . elements ( ) ; } } public IType getType ( ) { return this . focusType ; } protected IType [ ] growAndAddToArray ( IType [ ] array , IType [ ] additions ) { if ( array == null || array . length == 0 ) { return additions ; } IType [ ] old = array ; array = new IType [ old . length + additions . length ] ; System . arraycopy ( old , 0 , array , 0 , old . length ) ; System . arraycopy ( additions , 0 , array , old . length , additions . length ) ; return array ; } protected IType [ ] growAndAddToArray ( IType [ ] array , IType addition ) { if ( array == null || array . length == 0 ) { return new IType [ ] { addition } ; } IType [ ] old = array ; array = new IType [ old . length + 1 ] ; System . arraycopy ( old , 0 , array , 0 , old . length ) ; array [ old . length ] = addition ; return array ; } public boolean hasFineGrainChanges ( ) { ChangeCollector collector = this . changeCollector ; return collector != null && collector . needsRefresh ( ) ; } private boolean hasSubtypeNamed ( String simpleName ) { if ( this . focusType != null && this . focusType . getElementName ( ) . equals ( simpleName ) ) { return true ; } IType [ ] types = this . focusType == null ? getAllTypes ( ) : getAllSubtypes ( this . focusType ) ; for ( int i = 0 , length = types . length ; i < length ; i ++ ) { if ( types [ i ] . getElementName ( ) . equals ( simpleName ) ) { return true ; } } return false ; } private boolean hasTypeNamed ( String simpleName ) { IType [ ] types = getAllTypes ( ) ; for ( int i = 0 , length = types . length ; i < length ; i ++ ) { if ( types [ i ] . getElementName ( ) . equals ( simpleName ) ) { return true ; } } return false ; } boolean includesTypeOrSupertype ( IType type ) { try { if ( hasTypeNamed ( type . getElementName ( ) ) ) return true ; String superclassName = type . getSuperclassName ( ) ; if ( superclassName != null ) { int lastSeparator = superclassName . lastIndexOf ( '.' ) ; String simpleName = superclassName . substring ( lastSeparator + 1 ) ; if ( hasTypeNamed ( simpleName ) ) return true ; } String [ ] superinterfaceNames = type . getSuperInterfaceNames ( ) ; if ( superinterfaceNames != null ) { for ( int i = 0 , length = superinterfaceNames . length ; i < length ; i ++ ) { String superinterfaceName = superinterfaceNames [ i ] ; int lastSeparator = superinterfaceName . lastIndexOf ( '.' ) ; String simpleName = superinterfaceName . substring ( lastSeparator + 1 ) ; if ( hasTypeNamed ( simpleName ) ) return true ; } } } catch ( JavaModelException e ) { } return false ; } protected void initialize ( int size ) { if ( size < 10 ) { size = 10 ; } int smallSize = ( size / 2 ) ; this . classToSuperclass = new HashMap ( size ) ; this . interfaces = new ArrayList ( smallSize ) ; this . missingTypes = new ArrayList ( smallSize ) ; this . rootClasses = new TypeVector ( ) ; this . typeToSubtypes = new HashMap ( smallSize ) ; this . typeToSuperInterfaces = new HashMap ( smallSize ) ; this . typeFlags = new HashMap ( smallSize ) ; this . projectRegion = new Region ( ) ; this . packageRegion = new Region ( ) ; this . files = new HashMap ( 5 ) ; } public synchronized boolean isAffected ( IJavaElementDelta delta , int eventType ) { IJavaElement element = delta . getElement ( ) ; switch ( element . getElementType ( ) ) { case IJavaElement . JAVA_MODEL : return isAffectedByJavaModel ( delta , element , eventType ) ; case IJavaElement . JAVA_PROJECT : return isAffectedByJavaProject ( delta , element , eventType ) ; case IJavaElement . PACKAGE_FRAGMENT_ROOT : return isAffectedByPackageFragmentRoot ( delta , element , eventType ) ; case IJavaElement . PACKAGE_FRAGMENT : return isAffectedByPackageFragment ( delta , ( PackageFragment ) element , eventType ) ; case IJavaElement . CLASS_FILE : case IJavaElement . COMPILATION_UNIT : return isAffectedByOpenable ( delta , element , eventType ) ; } return false ; } private boolean isAffectedByChildren ( IJavaElementDelta delta , int eventType ) { if ( ( delta . getFlags ( ) & IJavaElementDelta . F_CHILDREN ) > 0 ) { IJavaElementDelta [ ] children = delta . getAffectedChildren ( ) ; for ( int i = 0 ; i < children . length ; i ++ ) { if ( isAffected ( children [ i ] , eventType ) ) { return true ; } } } return false ; } private boolean isAffectedByJavaModel ( IJavaElementDelta delta , IJavaElement element , int eventType ) { switch ( delta . getKind ( ) ) { case IJavaElementDelta . ADDED : case IJavaElementDelta . REMOVED : return element . equals ( javaProject ( ) . getJavaModel ( ) ) ; case IJavaElementDelta . CHANGED : return isAffectedByChildren ( delta , eventType ) ; } return false ; } private boolean isAffectedByJavaProject ( IJavaElementDelta delta , IJavaElement element , int eventType ) { int kind = delta . getKind ( ) ; int flags = delta . getFlags ( ) ; if ( ( flags & IJavaElementDelta . F_OPENED ) != 0 ) { kind = IJavaElementDelta . ADDED ; } if ( ( flags & IJavaElementDelta . F_CLOSED ) != 0 ) { kind = IJavaElementDelta . REMOVED ; } switch ( kind ) { case IJavaElementDelta . ADDED : try { IClasspathEntry [ ] classpath = ( ( JavaProject ) javaProject ( ) ) . getExpandedClasspath ( ) ; for ( int i = 0 ; i < classpath . length ; i ++ ) { if ( classpath [ i ] . getEntryKind ( ) == IClasspathEntry . CPE_PROJECT && classpath [ i ] . getPath ( ) . equals ( element . getPath ( ) ) ) { return true ; } } if ( this . focusType != null ) { classpath = ( ( JavaProject ) element ) . getExpandedClasspath ( ) ; IPath hierarchyProject = javaProject ( ) . getPath ( ) ; for ( int i = 0 ; i < classpath . length ; i ++ ) { if ( classpath [ i ] . getEntryKind ( ) == IClasspathEntry . CPE_PROJECT && classpath [ i ] . getPath ( ) . equals ( hierarchyProject ) ) { return true ; } } } return false ; } catch ( JavaModelException e ) { return false ; } case IJavaElementDelta . REMOVED : IJavaElement [ ] pkgs = this . packageRegion . getElements ( ) ; for ( int i = 0 ; i < pkgs . length ; i ++ ) { IJavaProject javaProject = pkgs [ i ] . getJavaProject ( ) ; if ( javaProject != null && javaProject . equals ( element ) ) { return true ; } } return false ; case IJavaElementDelta . CHANGED : return isAffectedByChildren ( delta , eventType ) ; } return false ; } private boolean isAffectedByPackageFragment ( IJavaElementDelta delta , PackageFragment element , int eventType ) { switch ( delta . getKind ( ) ) { case IJavaElementDelta . ADDED : return this . projectRegion . contains ( element ) ; case IJavaElementDelta . REMOVED : return packageRegionContainsSamePackageFragment ( element ) ; case IJavaElementDelta . CHANGED : return isAffectedByChildren ( delta , eventType ) ; } return false ; } private boolean isAffectedByPackageFragmentRoot ( IJavaElementDelta delta , IJavaElement element , int eventType ) { switch ( delta . getKind ( ) ) { case IJavaElementDelta . ADDED : return this . projectRegion . contains ( element ) ; case IJavaElementDelta . REMOVED : case IJavaElementDelta . CHANGED : int flags = delta . getFlags ( ) ; if ( ( flags & IJavaElementDelta . F_ADDED_TO_CLASSPATH ) > 0 ) { if ( this . projectRegion != null ) { IPackageFragmentRoot root = ( IPackageFragmentRoot ) element ; IPath rootPath = root . getPath ( ) ; IJavaElement [ ] elements = this . projectRegion . getElements ( ) ; for ( int i = 0 ; i < elements . length ; i ++ ) { JavaProject javaProject = ( JavaProject ) elements [ i ] ; try { IClasspathEntry entry = javaProject . getClasspathEntryFor ( rootPath ) ; if ( entry != null ) { return true ; } } catch ( JavaModelException e ) { } } } } if ( ( flags & IJavaElementDelta . F_REMOVED_FROM_CLASSPATH ) > 0 || ( flags & IJavaElementDelta . F_ARCHIVE_CONTENT_CHANGED ) > 0 ) { IJavaElement [ ] pkgs = this . packageRegion . getElements ( ) ; for ( int i = 0 ; i < pkgs . length ; i ++ ) { if ( pkgs [ i ] . getParent ( ) . equals ( element ) ) { return true ; } } return false ; } } return isAffectedByChildren ( delta , eventType ) ; } protected boolean isAffectedByOpenable ( IJavaElementDelta delta , IJavaElement element , int eventType ) { if ( element instanceof CompilationUnit ) { CompilationUnit cu = ( CompilationUnit ) element ; ICompilationUnit focusCU = this . focusType != null ? this . focusType . getCompilationUnit ( ) : null ; if ( focusCU != null && focusCU . getOwner ( ) != cu . getOwner ( ) ) return false ; if ( eventType != ElementChangedEvent . POST_RECONCILE && ! cu . isPrimary ( ) && delta . getKind ( ) == IJavaElementDelta . ADDED ) return false ; ChangeCollector collector = this . changeCollector ; if ( collector == null ) { collector = new ChangeCollector ( this ) ; } try { collector . addChange ( cu , delta ) ; } catch ( JavaModelException e ) { if ( DEBUG ) e . printStackTrace ( ) ; } if ( cu . isWorkingCopy ( ) && eventType == ElementChangedEvent . POST_RECONCILE ) { this . changeCollector = collector ; return false ; } else { return collector . needsRefresh ( ) ; } } else if ( element instanceof ClassFile ) { switch ( delta . getKind ( ) ) { case IJavaElementDelta . REMOVED : return this . files . get ( element ) != null ; case IJavaElementDelta . ADDED : IType type = ( ( ClassFile ) element ) . getType ( ) ; String typeName = type . getElementName ( ) ; if ( hasSupertype ( typeName ) || subtypesIncludeSupertypeOf ( type ) || this . missingTypes . contains ( typeName ) ) { return true ; } break ; case IJavaElementDelta . CHANGED : IJavaElementDelta [ ] children = delta . getAffectedChildren ( ) ; for ( int i = 0 , length = children . length ; i < length ; i ++ ) { IJavaElementDelta child = children [ i ] ; IJavaElement childElement = child . getElement ( ) ; if ( childElement instanceof IType ) { type = ( IType ) childElement ; boolean hasVisibilityChange = ( delta . getFlags ( ) & IJavaElementDelta . F_MODIFIERS ) > 0 ; boolean hasSupertypeChange = ( delta . getFlags ( ) & IJavaElementDelta . F_SUPER_TYPES ) > 0 ; if ( ( hasVisibilityChange && hasSupertype ( type . getElementName ( ) ) ) || ( hasSupertypeChange && includesTypeOrSupertype ( type ) ) ) { return true ; } } } break ; } } return false ; } private boolean isInterface ( IType type ) { int flags = getCachedFlags ( type ) ; if ( flags == - 1 ) { try { return type . isInterface ( ) ; } catch ( JavaModelException e ) { return false ; } } else { return Flags . isInterface ( flags ) ; } } public IJavaProject javaProject ( ) { return this . focusType . getJavaProject ( ) ; } protected static byte [ ] readUntil ( InputStream input , byte separator ) throws JavaModelException , IOException { return readUntil ( input , separator , 0 ) ; } protected static byte [ ] readUntil ( InputStream input , byte separator , int offset ) throws IOException , JavaModelException { int length = 0 ; byte [ ] bytes = new byte [ SIZE ] ; byte b ; while ( ( b = ( byte ) input . read ( ) ) != separator && b != - 1 ) { if ( bytes . length == length ) { System . arraycopy ( bytes , 0 , bytes = new byte [ length * 2 ] , 0 , length ) ; } bytes [ length ++ ] = b ; } if ( b == - 1 ) { throw new JavaModelException ( new JavaModelStatus ( IStatus . ERROR ) ) ; } System . arraycopy ( bytes , 0 , bytes = new byte [ length + offset ] , offset , length ) ; return bytes ; } public static ITypeHierarchy load ( IType type , InputStream input , WorkingCopyOwner owner ) throws JavaModelException { try { TypeHierarchy typeHierarchy = new TypeHierarchy ( ) ; typeHierarchy . initialize ( 1 ) ; IType [ ] types = new IType [ SIZE ] ; int typeCount = 0 ; byte version = ( byte ) input . read ( ) ; if ( version != VERSION ) { throw new JavaModelException ( new JavaModelStatus ( IStatus . ERROR ) ) ; } byte generalInfo = ( byte ) input . read ( ) ; if ( ( generalInfo & COMPUTE_SUBTYPES ) != 0 ) { typeHierarchy . computeSubtypes = true ; } byte b ; byte [ ] bytes ; bytes = readUntil ( input , SEPARATOR1 ) ; if ( bytes . length > 0 ) { typeHierarchy . project = ( IJavaProject ) JavaCore . create ( new String ( bytes ) ) ; typeHierarchy . scope = SearchEngine . createJavaSearchScope ( new IJavaElement [ ] { typeHierarchy . project } ) ; } else { typeHierarchy . project = null ; typeHierarchy . scope = SearchEngine . createWorkspaceScope ( ) ; } { bytes = readUntil ( input , SEPARATOR1 ) ; byte [ ] missing ; int j = 0 ; int length = bytes . length ; for ( int i = 0 ; i < length ; i ++ ) { b = bytes [ i ] ; if ( b == SEPARATOR2 ) { missing = new byte [ i - j ] ; System . arraycopy ( bytes , j , missing , 0 , i - j ) ; typeHierarchy . missingTypes . add ( new String ( missing ) ) ; j = i + 1 ; } } System . arraycopy ( bytes , j , missing = new byte [ length - j ] , 0 , length - j ) ; typeHierarchy . missingTypes . add ( new String ( missing ) ) ; } while ( ( b = ( byte ) input . read ( ) ) != SEPARATOR1 && b != - 1 ) { bytes = readUntil ( input , SEPARATOR4 , 1 ) ; bytes [ 0 ] = b ; IType element = ( IType ) JavaCore . create ( new String ( bytes ) , owner ) ; if ( types . length == typeCount ) { System . arraycopy ( types , 0 , types = new IType [ typeCount * 2 ] , 0 , typeCount ) ; } types [ typeCount ++ ] = element ; bytes = readUntil ( input , SEPARATOR4 ) ; Integer flags = bytesToFlags ( bytes ) ; if ( flags != null ) { typeHierarchy . cacheFlags ( element , flags . intValue ( ) ) ; } byte info = ( byte ) input . read ( ) ; if ( ( info & INTERFACE ) != 0 ) { typeHierarchy . addInterface ( element ) ; } if ( ( info & COMPUTED_FOR ) != 0 ) { if ( ! element . equals ( type ) ) { throw new JavaModelException ( new JavaModelStatus ( IStatus . ERROR ) ) ; } typeHierarchy . focusType = element ; } if ( ( info & ROOT ) != 0 ) { typeHierarchy . addRootClass ( element ) ; } } while ( ( b = ( byte ) input . read ( ) ) != SEPARATOR1 && b != - 1 ) { bytes = readUntil ( input , SEPARATOR3 , 1 ) ; bytes [ 0 ] = b ; int subClass = new Integer ( new String ( bytes ) ) . intValue ( ) ; bytes = readUntil ( input , SEPARATOR1 ) ; int superClass = new Integer ( new String ( bytes ) ) . intValue ( ) ; typeHierarchy . cacheSuperclass ( types [ subClass ] , types [ superClass ] ) ; } while ( ( b = ( byte ) input . read ( ) ) != SEPARATOR1 && b != - 1 ) { bytes = readUntil ( input , SEPARATOR3 , 1 ) ; bytes [ 0 ] = b ; int subClass = new Integer ( new String ( bytes ) ) . intValue ( ) ; bytes = readUntil ( input , SEPARATOR1 ) ; IType [ ] superInterfaces = new IType [ ( bytes . length / 2 ) + 1 ] ; int interfaceCount = 0 ; int j = 0 ; byte [ ] b2 ; for ( int i = 0 ; i < bytes . length ; i ++ ) { if ( bytes [ i ] == SEPARATOR2 ) { b2 = new byte [ i - j ] ; System . arraycopy ( bytes , j , b2 , 0 , i - j ) ; j = i + 1 ; superInterfaces [ interfaceCount ++ ] = types [ new Integer ( new String ( b2 ) ) . intValue ( ) ] ; } } b2 = new byte [ bytes . length - j ] ; System . arraycopy ( bytes , j , b2 , 0 , bytes . length - j ) ; superInterfaces [ interfaceCount ++ ] = types [ new Integer ( new String ( b2 ) ) . intValue ( ) ] ; System . arraycopy ( superInterfaces , 0 , superInterfaces = new IType [ interfaceCount ] , 0 , interfaceCount ) ; typeHierarchy . cacheSuperInterfaces ( types [ subClass ] , superInterfaces ) ; } if ( b == - 1 ) { throw new JavaModelException ( new JavaModelStatus ( IStatus . ERROR ) ) ; } return typeHierarchy ; } catch ( IOException e ) { throw new JavaModelException ( e , IJavaModelStatusConstants . IO_EXCEPTION ) ; } } protected boolean packageRegionContainsSamePackageFragment ( PackageFragment element ) { IJavaElement [ ] pkgs = this . packageRegion . getElements ( ) ; for ( int i = 0 ; i < pkgs . length ; i ++ ) { PackageFragment pkg = ( PackageFragment ) pkgs [ i ] ; if ( Util . equalArraysOrNull ( pkg . names , element . names ) ) return true ; } return false ; } public synchronized void refresh ( IProgressMonitor monitor ) throws JavaModelException { try { this . progressMonitor = monitor ; if ( monitor != null ) { monitor . beginTask ( this . focusType != null ? Messages . bind ( Messages . hierarchy_creatingOnType , this . focusType . getFullyQualifiedName ( ) ) : Messages . hierarchy_creating , 100 ) ; } long start = - 1 ; if ( DEBUG ) { start = System . currentTimeMillis ( ) ; if ( this . computeSubtypes ) { System . out . println ( "" + Thread . currentThread ( ) + "]" ) ; } else { System . out . println ( "" + Thread . currentThread ( ) + "]" ) ; } if ( this . focusType != null ) { System . out . println ( " on type " + ( ( JavaElement ) this . focusType ) . toStringWithAncestors ( ) ) ; } } compute ( ) ; initializeRegions ( ) ; this . needsRefresh = false ; this . changeCollector = null ; if ( DEBUG ) { if ( this . computeSubtypes ) { System . out . println ( "" + ( System . currentTimeMillis ( ) - start ) + "ms" ) ; } else { System . out . println ( "" + ( System . currentTimeMillis ( ) - start ) + "ms" ) ; } System . out . println ( this . toString ( ) ) ; } } catch ( JavaModelException e ) { throw e ; } catch ( CoreException e ) { throw new JavaModelException ( e ) ; } finally { if ( monitor != null ) { monitor . done ( ) ; } this . progressMonitor = null ; } } public synchronized void removeTypeHierarchyChangedListener ( ITypeHierarchyChangedListener listener ) { ArrayList listeners = this . changeListeners ; if ( listeners == null ) { return ; } listeners . remove ( listener ) ; if ( listeners . isEmpty ( ) ) { JavaCore . removeElementChangedListener ( this ) ; } } public void store ( OutputStream output , IProgressMonitor monitor ) throws JavaModelException { try { Hashtable hashtable = new Hashtable ( ) ; Hashtable hashtable2 = new Hashtable ( ) ; int count = 0 ; if ( this . focusType != null ) { Integer index = new Integer ( count ++ ) ; hashtable . put ( this . focusType , index ) ; hashtable2 . put ( index , this . focusType ) ; } Object [ ] types = this . classToSuperclass . entrySet ( ) . toArray ( ) ; for ( int i = 0 ; i < types . length ; i ++ ) { Map . Entry entry = ( Map . Entry ) types [ i ] ; Object t = entry . getKey ( ) ; if ( hashtable . get ( t ) == null ) { Integer index = new Integer ( count ++ ) ; hashtable . put ( t , index ) ; hashtable2 . put ( index , t ) ; } Object superClass = entry . getValue ( ) ; if ( superClass != null && hashtable . get ( superClass ) == null ) { Integer index = new Integer ( count ++ ) ; hashtable . put ( superClass , index ) ; hashtable2 . put ( index , superClass ) ; } } types = this . typeToSuperInterfaces . entrySet ( ) . toArray ( ) ; for ( int i = 0 ; i < types . length ; i ++ ) { Map . Entry entry = ( Map . Entry ) types [ i ] ; Object t = entry . getKey ( ) ; if ( hashtable . get ( t ) == null ) { Integer index = new Integer ( count ++ ) ; hashtable . put ( t , index ) ; hashtable2 . put ( index , t ) ; } Object [ ] sp = ( Object [ ] ) entry . getValue ( ) ; if ( sp != null ) { for ( int j = 0 ; j < sp . length ; j ++ ) { Object superInterface = sp [ j ] ; if ( sp [ j ] != null && hashtable . get ( superInterface ) == null ) { Integer index = new Integer ( count ++ ) ; hashtable . put ( superInterface , index ) ; hashtable2 . put ( index , superInterface ) ; } } } } output . write ( VERSION ) ; byte generalInfo = 0 ; if ( this . computeSubtypes ) { generalInfo |= COMPUTE_SUBTYPES ; } output . write ( generalInfo ) ; if ( this . project != null ) { output . write ( this . project . getHandleIdentifier ( ) . getBytes ( ) ) ; } output . write ( SEPARATOR1 ) ; for ( int i = 0 ; i < this . missingTypes . size ( ) ; i ++ ) { if ( i != 0 ) { output . write ( SEPARATOR2 ) ; } output . write ( ( ( String ) this . missingTypes . get ( i ) ) . getBytes ( ) ) ; } output . write ( SEPARATOR1 ) ; for ( int i = 0 ; i < count ; i ++ ) { IType t = ( IType ) hashtable2 . get ( new Integer ( i ) ) ; output . write ( t . getHandleIdentifier ( ) . getBytes ( ) ) ; output . write ( SEPARATOR4 ) ; output . write ( flagsToBytes ( ( Integer ) this . typeFlags . get ( t ) ) ) ; output . write ( SEPARATOR4 ) ; byte info = CLASS ; if ( this . focusType != null && this . focusType . equals ( t ) ) { info |= COMPUTED_FOR ; } if ( this . interfaces . contains ( t ) ) { info |= INTERFACE ; } if ( this . rootClasses . contains ( t ) ) { info |= ROOT ; } output . write ( info ) ; } output . write ( SEPARATOR1 ) ; types = this . classToSuperclass . entrySet ( ) . toArray ( ) ; for ( int i = 0 ; i < types . length ; i ++ ) { Map . Entry entry = ( Map . Entry ) types [ i ] ; IJavaElement key = ( IJavaElement ) entry . getKey ( ) ; IJavaElement value = ( IJavaElement ) entry . getValue ( ) ; output . write ( ( ( Integer ) hashtable . get ( key ) ) . toString ( ) . getBytes ( ) ) ; output . write ( '>' ) ; output . write ( ( ( Integer ) hashtable . get ( value ) ) . toString ( ) . getBytes ( ) ) ; output . write ( SEPARATOR1 ) ; } output . write ( SEPARATOR1 ) ; types = this . typeToSuperInterfaces . entrySet ( ) . toArray ( ) ; for ( int i = 0 ; i < types . length ; i ++ ) { Map . Entry entry = ( Map . Entry ) types [ i ] ; IJavaElement key = ( IJavaElement ) entry . getKey ( ) ; IJavaElement [ ] values = ( IJavaElement [ ] ) entry . getValue ( ) ; if ( values . length > 0 ) { output . write ( ( ( Integer ) hashtable . get ( key ) ) . toString ( ) . getBytes ( ) ) ; output . write ( SEPARATOR3 ) ; for ( int j = 0 ; j < values . length ; j ++ ) { IJavaElement value = values [ j ] ; if ( j != 0 ) output . write ( SEPARATOR2 ) ; output . write ( ( ( Integer ) hashtable . get ( value ) ) . toString ( ) . getBytes ( ) ) ; } output . write ( SEPARATOR1 ) ; } } output . write ( SEPARATOR1 ) ; } catch ( IOException e ) { throw new JavaModelException ( e , IJavaModelStatusConstants . IO_EXCEPTION ) ; } } boolean subtypesIncludeSupertypeOf ( IType type ) { String superclassName = null ; try { superclassName = type . getSuperclassName ( ) ; } catch ( JavaModelException e ) { if ( DEBUG ) { e . printStackTrace ( ) ; } return false ; } if ( superclassName == null ) { superclassName = "Object" ; } int dot = - 1 ; String simpleSuper = ( dot = superclassName . lastIndexOf ( '.' ) ) > - 1 ? superclassName . substring ( dot + 1 ) : superclassName ; if ( hasSubtypeNamed ( simpleSuper ) ) { return true ; } String [ ] interfaceNames = null ; try { interfaceNames = type . getSuperInterfaceNames ( ) ; } catch ( JavaModelException e ) { if ( DEBUG ) e . printStackTrace ( ) ; return false ; } for ( int i = 0 , length = interfaceNames . length ; i < length ; i ++ ) { dot = - 1 ; String interfaceName = interfaceNames [ i ] ; String simpleInterface = ( dot = interfaceName . lastIndexOf ( '.' ) ) > - 1 ? interfaceName . substring ( dot ) : interfaceName ; if ( hasSubtypeNamed ( simpleInterface ) ) { return true ; } } return false ; } public String toString ( ) { StringBuffer buffer = new StringBuffer ( ) ; buffer . append ( "Focus: " ) ; if ( this . focusType == null ) { buffer . append ( "<NONE>n" ) ; } else { toString ( buffer , this . focusType , 0 ) ; } if ( exists ( ) ) { if ( this . focusType != null ) { buffer . append ( "" ) ; toString ( buffer , this . focusType , 0 , true ) ; buffer . append ( "Sub types:n" ) ; toString ( buffer , this . focusType , 0 , false ) ; } else { if ( this . rootClasses . size > 0 ) { IJavaElement [ ] roots = Util . sortCopy ( getRootClasses ( ) ) ; buffer . append ( "" ) ; int length = roots . length ; for ( int i = 0 ; i < length ; i ++ ) { IJavaElement root = roots [ i ] ; toString ( buffer , root , 1 ) ; toString ( buffer , root , 1 , true ) ; } buffer . append ( "" ) ; for ( int i = 0 ; i < length ; i ++ ) { IJavaElement root = roots [ i ] ; toString ( buffer , root , 1 ) ; toString ( buffer , root , 1 , false ) ; } } else if ( this . rootClasses . size == 0 ) { buffer . append ( "" ) ; } } } else { buffer . append ( "" ) ; } return buffer . toString ( ) ; } private void toString ( StringBuffer buffer , IJavaElement type , int indent , boolean ascendant ) { IType [ ] types = ascendant ? getSupertypes ( ( IType ) type ) : getSubtypes ( ( IType ) type ) ; IJavaElement [ ] sortedTypes = Util . sortCopy ( types ) ; for ( int i = 0 ; i < sortedTypes . length ; i ++ ) { toString ( buffer , sortedTypes [ i ] , indent + 1 ) ; toString ( buffer , sortedTypes [ i ] , indent + 1 , ascendant ) ; } } private void toString ( StringBuffer buffer , IJavaElement type , int indent ) { for ( int j = 0 ; j < indent ; j ++ ) { buffer . append ( " " ) ; } buffer . append ( ( ( JavaElement ) type ) . toStringWithAncestors ( false ) ) ; buffer . append ( '\n' ) ; } boolean hasSupertype ( String simpleName ) { for ( Iterator iter = this . classToSuperclass . values ( ) . iterator ( ) ; iter . hasNext ( ) ; ) { IType superType = ( IType ) iter . next ( ) ; if ( superType . getElementName ( ) . equals ( simpleName ) ) { return true ; } } return false ; } protected void worked ( int work ) { if ( this . progressMonitor != null ) { this . progressMonitor . worked ( work ) ; checkCanceled ( ) ; } } } </s>