2626import java .nio .file .SimpleFileVisitor ;
2727import java .nio .file .attribute .BasicFileAttributes ;
2828import java .util .HashSet ;
29- import java .util .Hashtable ;
3029import java .util .List ;
3130import java .util .Map ;
3231import java .util .Set ;
32+ import java .util .concurrent .ConcurrentHashMap ;
3333import java .util .function .Function ;
3434import java .util .stream .Stream ;
3535import org .eclipse .jdt .core .compiler .CharOperation ;
3636import org .eclipse .jdt .internal .compiler .CompilationResult ;
3737import org .eclipse .jdt .internal .compiler .DefaultErrorHandlingPolicies ;
3838import org .eclipse .jdt .internal .compiler .ast .CompilationUnitDeclaration ;
3939import org .eclipse .jdt .internal .compiler .ast .TypeDeclaration ;
40+ import org .eclipse .jdt .internal .compiler .batch .FileSystem .Classpath ;
4041import org .eclipse .jdt .internal .compiler .classfmt .ClassFileReader ;
4142import org .eclipse .jdt .internal .compiler .classfmt .ClassFormatException ;
4243import org .eclipse .jdt .internal .compiler .classfmt .ExternalAnnotationProvider ;
5152import org .eclipse .jdt .internal .compiler .problem .ProblemReporter ;
5253import org .eclipse .jdt .internal .compiler .util .Util ;
5354
54- @ SuppressWarnings ({"rawtypes" , "unchecked" })
5555public class ClasspathDirectory extends ClasspathLocation {
5656
57- private Hashtable directoryCache ;
58- private final String [] missingPackageHolder = new String [1 ];
59- private final int mode ; // ability to only consider one kind of files (source vs. binaries), by default use both
60- private final String encoding ; // only useful if referenced in the source path
61- private Hashtable <String , Hashtable <String , String >> packageSecondaryTypes = null ;
62- Map options ;
57+ private final Map < String , String []> directoryCache = new ConcurrentHashMap <>() ;
58+ private final String [] missingPackageHolder = new String [1 ];
59+ private final int mode ; // ability to only consider one kind of files (source vs. binaries), by default use both
60+ private final String encoding ; // only useful if referenced in the source path
61+ private final Map <String , Map <String , String >> packageSecondaryTypes = new ConcurrentHashMap <>() ;
62+ private final Map < String , String > options ;
6363
6464ClasspathDirectory (File directory , String encoding , int mode ,
65- AccessRuleSet accessRuleSet , String destinationPath , Map options ) {
65+ AccessRuleSet accessRuleSet , String destinationPath , Map < String , String > options ) {
6666 super (accessRuleSet , destinationPath );
6767 this .mode = mode ;
6868 this .options = options ;
@@ -74,43 +74,47 @@ public class ClasspathDirectory extends ClasspathLocation {
7474 }
7575 if (!this .path .endsWith (File .separator ))
7676 this .path += File .separator ;
77- this .directoryCache = new Hashtable (11 );
7877 this .encoding = encoding ;
7978}
80- String [] directoryList (String qualifiedPackageName ) {
81- if (File .separatorChar != '/' && qualifiedPackageName .indexOf ('/' ) != -1 ) {
82- qualifiedPackageName = qualifiedPackageName .replace ('/' , File .separatorChar );
79+
80+ private String [] directoryList (String qualifiedPackageName ) {
81+ String [] cached = this .directoryCache .computeIfAbsent (qualifiedPackageName , this ::computeDirectoryList );
82+ if (cached == this .missingPackageHolder ) {
83+ return null ; // package exists in another classpath directory or jar
8384 }
84- String [] dirList = (String []) this .directoryCache .get (qualifiedPackageName );
85- if (dirList == this .missingPackageHolder ) return null ; // package exists in another classpath directory or jar
86- if (dirList != null ) return dirList ;
85+ return cached ;
86+ }
8787
88- File dir = new File (this .path + qualifiedPackageName );
89- notFound : if (dir .isDirectory ()) {
88+ private String [] computeDirectoryList (String qualifiedPackageName ) {
89+ String qualifiedPackagePath = qualifiedPackageName .replace ('/' , File .separatorChar );
90+ File dir = new File (this .path + qualifiedPackagePath );
91+ String [] dirList = dir .list ();
92+ notFound : if (dirList != null ) { // if isDirectory
9093 // must protect against a case insensitive File call
9194 // walk the qualifiedPackageName backwards looking for an uppercase character before the '/'
92- int index = qualifiedPackageName .length ();
93- int last = qualifiedPackageName .lastIndexOf (File .separatorChar );
94- while (--index > last && !ScannerHelper .isUpperCase (qualifiedPackageName .charAt (index ))){/*empty*/ }
95+ int index = qualifiedPackagePath .length ();
96+ int last = qualifiedPackagePath .lastIndexOf (File .separatorChar );
97+ while (--index > last && !ScannerHelper .isUpperCase (qualifiedPackagePath .charAt (index ))) {
98+ /* empty */ }
9599 if (index > last ) {
96100 if (last == -1 ) {
97- if (!doesFileExist (qualifiedPackageName , Util .EMPTY_STRING ))
101+ if (!doesFileExist (qualifiedPackagePath , Util .EMPTY_STRING ))
98102 break notFound ;
99103 } else {
100- String packageName = qualifiedPackageName .substring (last + 1 );
101- String parentPackage = qualifiedPackageName .substring (0 , last );
104+ String packageName = qualifiedPackagePath .substring (last + 1 );
105+ String parentPackage = qualifiedPackagePath .substring (0 , last );
102106 if (!doesFileExist (packageName , parentPackage ))
103107 break notFound ;
104108 }
105109 }
106- if (( dirList = dir . list ()) == null )
110+ if (dirList . length == 0 ) {
107111 dirList = CharOperation .NO_STRINGS ;
108- this . directoryCache . put ( qualifiedPackageName , dirList );
112+ }
109113 return dirList ;
110114 }
111- this .directoryCache .put (qualifiedPackageName , this .missingPackageHolder );
112- return null ;
115+ return this .missingPackageHolder ;
113116}
117+
114118boolean doesFileExist (String fileName , String qualifiedPackageName ) {
115119 String [] dirList = directoryList (qualifiedPackageName );
116120 if (dirList == null ) return false ; // most common case
@@ -121,7 +125,7 @@ boolean doesFileExist(String fileName, String qualifiedPackageName) {
121125 return false ;
122126}
123127@ Override
124- public List fetchLinkedJars (FileSystem .ClasspathSectionProblemReporter problemReporter ) {
128+ public List < Classpath > fetchLinkedJars (FileSystem .ClasspathSectionProblemReporter problemReporter ) {
125129 return null ;
126130}
127131private NameEnvironmentAnswer findClassInternal (char [] typeName , String qualifiedPackageName , String qualifiedBinaryFileName , boolean asBinaryOnly ) {
@@ -202,10 +206,10 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN
202206/**
203207 * Add all the secondary types in the package
204208 */
205- private Hashtable <String , String > getSecondaryTypes (String qualifiedPackageName ) {
206- Hashtable <String , String > packageEntry = new Hashtable <>();
209+ private Map <String , String > getSecondaryTypes (String qualifiedPackageName ) {
210+ Map <String , String > packageEntry = new ConcurrentHashMap <>();
207211
208- String [] dirList = ( String []) this .directoryCache .get (qualifiedPackageName );
212+ String [] dirList = this .directoryCache .get (qualifiedPackageName );
209213 if (dirList == this .missingPackageHolder // package exists in another classpath directory or jar
210214 || dirList == null )
211215 return packageEntry ;
@@ -241,13 +245,7 @@ private Hashtable<String, String> getSecondaryTypes(String qualifiedPackageName)
241245 return packageEntry ;
242246}
243247private NameEnvironmentAnswer findSourceSecondaryType (String typeName , String qualifiedPackageName , String qualifiedBinaryFileName ) {
244-
245- if (this .packageSecondaryTypes == null ) this .packageSecondaryTypes = new Hashtable <>();
246- Hashtable <String , String > packageEntry = this .packageSecondaryTypes .get (qualifiedPackageName );
247- if (packageEntry == null ) {
248- packageEntry = getSecondaryTypes (qualifiedPackageName );
249- this .packageSecondaryTypes .put (qualifiedPackageName , packageEntry );
250- }
248+ Map <String , String > packageEntry = this .packageSecondaryTypes .computeIfAbsent (qualifiedPackageName , this ::getSecondaryTypes );
251249 String fileName = packageEntry .get (typeName );
252250 return fileName != null ? new NameEnvironmentAnswer (new CompilationUnit (null ,
253251 fileName , this .encoding , this .destinationPath ),
@@ -360,7 +358,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
360358@ Override
361359public void reset () {
362360 super .reset ();
363- this .directoryCache = new Hashtable ( 11 );
361+ this .directoryCache . clear ( );
364362}
365363@ Override
366364public String toString () {
0 commit comments