<s> package org . eclipse . jdt . internal . core . hierarchy ; import java . util . * ; import org . eclipse . core . resources . IFile ; import org . eclipse . core . resources . IResource ; import org . eclipse . core . runtime . IPath ; import org . eclipse . core . runtime . IProgressMonitor ; import org . eclipse . core . runtime . NullProgressMonitor ; import org . eclipse . core . runtime . SubProgressMonitor ; import org . eclipse . jdt . core . * ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . core . search . * ; import org . eclipse . jdt . internal . compiler . env . AccessRuleSet ; import org . eclipse . jdt . internal . compiler . env . IBinaryType ; import org . eclipse . jdt . internal . compiler . env . ICompilationUnit ; import org . eclipse . jdt . internal . compiler . problem . DefaultProblemFactory ; import org . eclipse . jdt . internal . compiler . util . HashtableOfObject ; import org . eclipse . jdt . internal . compiler . util . HashtableOfObjectToInt ; import org . eclipse . jdt . internal . compiler . util . SuffixConstants ; import org . eclipse . jdt . internal . core . * ; import org . eclipse . jdt . internal . core . search . IndexQueryRequestor ; import org . eclipse . jdt . internal . core . search . JavaSearchParticipant ; import org . eclipse . jdt . internal . core . search . SubTypeSearchJob ; import org . eclipse . jdt . internal . core . search . indexing . IIndexConstants ; import org . eclipse . jdt . internal . core . search . indexing . IndexManager ; import org . eclipse . jdt . internal . core . search . matching . MatchLocator ; import org . eclipse . jdt . internal . core . search . matching . SuperTypeReferencePattern ; import org . eclipse . jdt . internal . core . util . HandleFactory ; import org . eclipse . jdt . internal . core . util . Util ; public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants { public static final int MAXTICKS = 800 ; protected Map cuToHandle ; protected IJavaSearchScope scope ; protected Map binariesFromIndexMatches ; static class Queue { public char [ ] [ ] names = new char [ 10 ] [ ] ; public int start = 0 ; public int end = - 1 ; public void add ( char [ ] name ) { if ( ++ this . end == this . names . length ) { this . end -= this . start ; System . arraycopy ( this . names , this . start , this . names = new char [ this . end * 2 ] [ ] , 0 , this . end ) ; this . start = 0 ; } this . names [ this . end ] = name ; } public char [ ] retrieve ( ) { if ( this . start > this . end ) return null ; char [ ] name = this . names [ this . start ++ ] ; if ( this . start > this . end ) { this . start = 0 ; this . end = - 1 ; } return name ; } public String toString ( ) { StringBuffer buffer = new StringBuffer ( "Queue:n" ) ; for ( int i = this . start ; i <= this . end ; i ++ ) { buffer . append ( this . names [ i ] ) . append ( '\n' ) ; } return buffer . toString ( ) ; } } public IndexBasedHierarchyBuilder ( TypeHierarchy hierarchy , IJavaSearchScope scope ) throws JavaModelException { super ( hierarchy ) ; this . cuToHandle = new HashMap ( 5 ) ; this . binariesFromIndexMatches = new HashMap ( 10 ) ; this . scope = scope ; } public void build ( boolean computeSubtypes ) { JavaModelManager manager = JavaModelManager . getJavaModelManager ( ) ; try { manager . cacheZipFiles ( this ) ; if ( computeSubtypes ) { IType focusType = getType ( ) ; boolean focusIsObject = focusType . getElementName ( ) . equals ( new String ( IIndexConstants . OBJECT ) ) ; int amountOfWorkForSubtypes = focusIsObject ? 5 : 80 ; IProgressMonitor possibleSubtypesMonitor = this . hierarchy . progressMonitor == null ? null : new SubProgressMonitor ( this . hierarchy . progressMonitor , amountOfWorkForSubtypes ) ; HashSet localTypes = new HashSet ( 10 ) ; String [ ] allPossibleSubtypes ; if ( ( ( Member ) focusType ) . getOuterMostLocalContext ( ) == null ) { allPossibleSubtypes = determinePossibleSubTypes ( localTypes , possibleSubtypesMonitor ) ; } else { allPossibleSubtypes = CharOperation . NO_STRINGS ; } if ( allPossibleSubtypes != null ) { IProgressMonitor buildMonitor = this . hierarchy . progressMonitor == null ? null : new SubProgressMonitor ( this . hierarchy . progressMonitor , 100 - amountOfWorkForSubtypes ) ; this . hierarchy . initialize ( allPossibleSubtypes . length ) ; buildFromPotentialSubtypes ( allPossibleSubtypes , localTypes , buildMonitor ) ; } } else { this . hierarchy . initialize ( 1 ) ; buildSupertypes ( ) ; } } finally { manager . flushZipFiles ( this ) ; } } private void buildForProject ( JavaProject project , ArrayList potentialSubtypes , org . eclipse . jdt . core . ICompilationUnit [ ] workingCopies , HashSet localTypes , IProgressMonitor monitor ) throws JavaModelException { int openablesLength = potentialSubtypes . size ( ) ; if ( openablesLength > 0 ) { Openable [ ] openables = new Openable [ openablesLength ] ; potentialSubtypes . toArray ( openables ) ; IPackageFragmentRoot [ ] roots = project . getPackageFragmentRoots ( ) ; int rootsLength = roots . length ; final HashtableOfObjectToInt indexes = new HashtableOfObjectToInt ( openablesLength ) ; for ( int i = 0 ; i < openablesLength ; i ++ ) { IJavaElement root = openables [ i ] . getAncestor ( IJavaElement . PACKAGE_FRAGMENT_ROOT ) ; int index ; for ( index = 0 ; index < rootsLength ; index ++ ) { if ( roots [ index ] . equals ( root ) ) break ; } indexes . put ( openables [ i ] , index ) ; } Arrays . sort ( openables , new Comparator ( ) { public int compare ( Object a , Object b ) { int aIndex = indexes . get ( a ) ; int bIndex = indexes . get ( b ) ; if ( aIndex != bIndex ) return aIndex - bIndex ; return ( ( Openable ) b ) . getElementName ( ) . compareTo ( ( ( Openable ) a ) . getElementName ( ) ) ; } } ) ; IType focusType = getType ( ) ; boolean inProjectOfFocusType = focusType != null && focusType . getJavaProject ( ) . equals ( project ) ; org . eclipse . jdt . core . ICompilationUnit [ ] unitsToLookInside = null ; if ( inProjectOfFocusType ) { org . eclipse . jdt . core . ICompilationUnit unitToLookInside = focusType . getCompilationUnit ( ) ; if ( unitToLookInside != null ) { int wcLength = workingCopies == null ? 0 : workingCopies . length ; if ( wcLength == 0 ) { unitsToLookInside = new org . eclipse . jdt . core . ICompilationUnit [ ] { unitToLookInside } ; } else { unitsToLookInside = new org . eclipse . jdt . core . ICompilationUnit [ wcLength + 1 ] ; unitsToLookInside [ 0 ] = unitToLookInside ; System . arraycopy ( workingCopies , 0 , unitsToLookInside , 1 , wcLength ) ; } } else { unitsToLookInside = workingCopies ; } } SearchableEnvironment searchableEnvironment = project . newSearchableNameEnvironment ( unitsToLookInside ) ; this . nameLookup = searchableEnvironment . nameLookup ; Map options = project . getOptions ( true ) ; options . put ( JavaCore . COMPILER_TASK_TAGS , "" ) ; this . hierarchyResolver = new HierarchyResolver ( searchableEnvironment , options , this , new DefaultProblemFactory ( ) ) ; if ( focusType != null ) { Member declaringMember = ( ( Member ) focusType ) . getOuterMostLocalContext ( ) ; if ( declaringMember == null ) { if ( ! inProjectOfFocusType ) { char [ ] typeQualifiedName = focusType . getTypeQualifiedName ( '.' ) . toCharArray ( ) ; String [ ] packageName = ( ( PackageFragment ) focusType . getPackageFragment ( ) ) . names ; if ( searchableEnvironment . findType ( typeQualifiedName , Util . toCharArrays ( packageName ) ) == null ) { return ; } } } else { Openable openable ; if ( declaringMember . isBinary ( ) ) { openable = ( Openable ) declaringMember . getClassFile ( ) ; } else { openable = ( Openable ) declaringMember . getCompilationUnit ( ) ; } localTypes = new HashSet ( ) ; localTypes . add ( openable . getPath ( ) . toString ( ) ) ; this . hierarchyResolver . resolve ( new Openable [ ] { openable } , localTypes , monitor ) ; return ; } } this . hierarchyResolver . resolve ( openables , localTypes , monitor ) ; } } private void buildFromPotentialSubtypes ( String [ ] allPotentialSubTypes , HashSet localTypes , IProgressMonitor monitor ) { IType focusType = getType ( ) ; HashMap wcPaths = new HashMap ( ) ; int wcLength ; org . eclipse . jdt . core . ICompilationUnit [ ] workingCopies = this . hierarchy . workingCopies ; if ( workingCopies != null && ( wcLength = workingCopies . length ) > 0 ) { String [ ] newPaths = new String [ wcLength ] ; for ( int i = 0 ; i < wcLength ; i ++ ) { org . eclipse . jdt . core . ICompilationUnit workingCopy = workingCopies [ i ] ; String path = workingCopy . getPath ( ) . toString ( ) ; wcPaths . put ( path , workingCopy ) ; newPaths [ i ] = path ; } int potentialSubtypesLength = allPotentialSubTypes . length ; System . arraycopy ( allPotentialSubTypes , 0 , allPotentialSubTypes = new String [ potentialSubtypesLength + wcLength ] , 0 , potentialSubtypesLength ) ; System . arraycopy ( newPaths , 0 , allPotentialSubTypes , potentialSubtypesLength , wcLength ) ; } int length = allPotentialSubTypes . length ; Openable focusCU = ( Openable ) focusType . getCompilationUnit ( ) ; String focusPath = null ; if ( focusCU != null ) { focusPath = focusCU . getPath ( ) . toString ( ) ; if ( length > 0 ) { System . arraycopy ( allPotentialSubTypes , 0 , allPotentialSubTypes = new String [ length + 1 ] , 0 , length ) ; allPotentialSubTypes [ length ] = focusPath ; } else { allPotentialSubTypes = new String [ ] { focusPath } ; } length ++ ; } Arrays . sort ( allPotentialSubTypes ) ; ArrayList potentialSubtypes = new ArrayList ( ) ; try { HandleFactory factory = new HandleFactory ( ) ; IJavaProject currentProject = null ; if ( monitor != null ) monitor . beginTask ( "" , length * 2 ) ; for ( int i = 0 ; i < length ; i ++ ) { try { String resourcePath = allPotentialSubTypes [ i ] ; if ( i > 0 && resourcePath . equals ( allPotentialSubTypes [ i - 1 ] ) ) continue ; Openable handle ; org . eclipse . jdt . core . ICompilationUnit workingCopy = ( org . eclipse . jdt . core . ICompilationUnit ) wcPaths . get ( resourcePath ) ; if ( workingCopy != null ) { handle = ( Openable ) workingCopy ; } else { handle = resourcePath . equals ( focusPath ) ? focusCU : factory . createOpenable ( resourcePath , this . scope ) ; if ( handle == null ) continue ; } IJavaProject project = handle . getJavaProject ( ) ; if ( currentProject == null ) { currentProject = project ; potentialSubtypes = new ArrayList ( 5 ) ; } else if ( ! currentProject . equals ( project ) ) { buildForProject ( ( JavaProject ) currentProject , potentialSubtypes , workingCopies , localTypes , monitor ) ; currentProject = project ; potentialSubtypes = new ArrayList ( 5 ) ; } potentialSubtypes . add ( handle ) ; } catch ( JavaModelException e ) { continue ; } } try { if ( currentProject == null ) { currentProject = focusType . getJavaProject ( ) ; if ( focusType . isBinary ( ) ) { potentialSubtypes . add ( focusType . getClassFile ( ) ) ; } else { potentialSubtypes . add ( focusType . getCompilationUnit ( ) ) ; } } buildForProject ( ( JavaProject ) currentProject , potentialSubtypes , workingCopies , localTypes , monitor ) ; } catch ( JavaModelException e ) { } if ( ! this . hierarchy . contains ( focusType ) ) { try { currentProject = focusType . getJavaProject ( ) ; potentialSubtypes = new ArrayList ( ) ; if ( focusType . isBinary ( ) ) { potentialSubtypes . add ( focusType . getClassFile ( ) ) ; } else { potentialSubtypes . add ( focusType . getCompilationUnit ( ) ) ; } buildForProject ( ( JavaProject ) currentProject , potentialSubtypes , workingCopies , localTypes , monitor ) ; } catch ( JavaModelException e ) { } } if ( ! this . hierarchy . contains ( focusType ) ) { this . hierarchy . addRootClass ( focusType ) ; } } finally { if ( monitor != null ) monitor . done ( ) ; } } protected ICompilationUnit createCompilationUnitFromPath ( Openable handle , IFile file ) { ICompilationUnit unit = super . createCompilationUnitFromPath ( handle , file ) ; this . cuToHandle . put ( unit , handle ) ; return unit ; } protected IBinaryType createInfoFromClassFile ( Openable classFile , IResource file ) { String documentPath = classFile . getPath ( ) . toString ( ) ; IBinaryType binaryType = ( IBinaryType ) this . binariesFromIndexMatches . get ( documentPath ) ; if ( binaryType != null ) { this . infoToHandle . put ( binaryType , classFile ) ; return binaryType ; } else { return super . createInfoFromClassFile ( classFile , file ) ; } } protected IBinaryType createInfoFromClassFileInJar ( Openable classFile ) { String filePath = ( ( ( ClassFile ) classFile ) . getType ( ) . getFullyQualifiedName ( '$' ) ) . replace ( '.' , '/' ) + SuffixConstants . SUFFIX_STRING_class ; IPackageFragmentRoot root = classFile . getPackageFragmentRoot ( ) ; IPath path = root . getPath ( ) ; String rootPath = path . getDevice ( ) == null ? path . toString ( ) : path . toOSString ( ) ; String documentPath = rootPath + IJavaSearchScope . JAR_FILE_ENTRY_SEPARATOR + filePath ; IBinaryType binaryType = ( IBinaryType ) this . binariesFromIndexMatches . get ( documentPath ) ; if ( binaryType != null ) { this . infoToHandle . put ( binaryType , classFile ) ; return binaryType ; } else { return super . createInfoFromClassFileInJar ( classFile ) ; } } private String [ ] determinePossibleSubTypes ( final HashSet localTypes , IProgressMonitor monitor ) { class PathCollector implements IPathRequestor { HashSet paths = new HashSet ( 10 ) ; public void acceptPath ( String path , boolean containsLocalTypes ) { this . paths . add ( path ) ; if ( containsLocalTypes ) { localTypes . add ( path ) ; } } } PathCollector collector = new PathCollector ( ) ; try { if ( monitor != null ) monitor . beginTask ( "" , MAXTICKS ) ; searchAllPossibleSubTypes ( getType ( ) , this . scope , this . binariesFromIndexMatches , collector , IJavaSearchConstants . WAIT_UNTIL_READY_TO_SEARCH , monitor ) ; } finally { if ( monitor != null ) monitor . done ( ) ; } HashSet paths = collector . paths ; int length = paths . size ( ) ; String [ ] result = new String [ length ] ; int count = 0 ; for ( Iterator iter = paths . iterator ( ) ; iter . hasNext ( ) ; ) { result [ count ++ ] = ( String ) iter . next ( ) ; } return result ; } public static void searchAllPossibleSubTypes ( IType type , IJavaSearchScope scope , final Map binariesFromIndexMatches , final IPathRequestor pathRequestor , int waitingPolicy , final IProgressMonitor progressMonitor ) { final Queue queue = new Queue ( ) ; final HashtableOfObject foundSuperNames = new HashtableOfObject ( 5 ) ; IndexManager indexManager = JavaModelManager . getIndexManager ( ) ; IndexQueryRequestor searchRequestor = new IndexQueryRequestor ( ) { public boolean acceptIndexMatch ( String documentPath , SearchPattern indexRecord , SearchParticipant participant , AccessRuleSet access ) { SuperTypeReferencePattern record = ( SuperTypeReferencePattern ) indexRecord ; boolean isLocalOrAnonymous = record . enclosingTypeName == IIndexConstants . ONE_ZERO ; pathRequestor . acceptPath ( documentPath , isLocalOrAnonymous ) ; char [ ] typeName = record . simpleName ; if ( documentPath . toLowerCase ( ) . endsWith ( SUFFIX_STRING_class ) ) { int suffix = documentPath . length ( ) - SUFFIX_STRING_class . length ( ) ; HierarchyBinaryType binaryType = ( HierarchyBinaryType ) binariesFromIndexMatches . get ( documentPath ) ; if ( binaryType == null ) { char [ ] enclosingTypeName = record . enclosingTypeName ; if ( isLocalOrAnonymous ) { int lastSlash = documentPath . lastIndexOf ( '/' ) ; int lastDollar = documentPath . lastIndexOf ( '$' ) ; if ( lastDollar == - 1 ) { enclosingTypeName = null ; typeName = documentPath . substring ( lastSlash + 1 , suffix ) . toCharArray ( ) ; } else { enclosingTypeName = documentPath . substring ( lastSlash + 1 , lastDollar ) . toCharArray ( ) ; typeName = documentPath . substring ( lastDollar + 1 , suffix ) . toCharArray ( ) ; } } binaryType = new HierarchyBinaryType ( record . modifiers , record . pkgName , typeName , enclosingTypeName , record . typeParameterSignatures , record . classOrInterface ) ; binariesFromIndexMatches . put ( documentPath , binaryType ) ; } binaryType . recordSuperType ( record . superSimpleName , record . superQualification , record . superClassOrInterface ) ; } if ( ! isLocalOrAnonymous && ! foundSuperNames . containsKey ( typeName ) ) { foundSuperNames . put ( typeName , typeName ) ; queue . add ( typeName ) ; } return true ; } } ; int superRefKind ; try { superRefKind = type . isClass ( ) ? SuperTypeReferencePattern . ONLY_SUPER_CLASSES : SuperTypeReferencePattern . ALL_SUPER_TYPES ; } catch ( JavaModelException e ) { superRefKind = SuperTypeReferencePattern . ALL_SUPER_TYPES ; } SuperTypeReferencePattern pattern = new SuperTypeReferencePattern ( null , null , superRefKind , SearchPattern . R_EXACT_MATCH | SearchPattern . R_CASE_SENSITIVE ) ; MatchLocator . setFocus ( pattern , type ) ; SubTypeSearchJob job = new SubTypeSearchJob ( pattern , new JavaSearchParticipant ( ) , scope , searchRequestor ) ; int ticks = 0 ; queue . add ( type . getElementName ( ) . toCharArray ( ) ) ; try { while ( queue . start <= queue . end ) { if ( progressMonitor != null && progressMonitor . isCanceled ( ) ) return ; char [ ] currentTypeName = queue . retrieve ( ) ; if ( CharOperation . equals ( currentTypeName , IIndexConstants . OBJECT ) ) currentTypeName = null ; pattern . superSimpleName = currentTypeName ; indexManager . performConcurrentJob ( job , waitingPolicy , progressMonitor == null ? null : new NullProgressMonitor ( ) { public void setCanceled ( boolean value ) { progressMonitor . setCanceled ( value ) ; } public boolean isCanceled ( ) { return progressMonitor . isCanceled ( ) ; } public void subTask ( String name ) { progressMonitor . subTask ( name ) ; } } ) ; if ( progressMonitor != null && ++ ticks <= MAXTICKS ) progressMonitor . worked ( 1 ) ; if ( currentTypeName == null ) break ; } } finally { job . finished ( ) ; } } } </s>