18
18
*/
19
19
package co .elastic .apm .agent .util ;
20
20
21
+ import javax .annotation .Nullable ;
21
22
import java .io .File ;
22
23
import java .io .IOException ;
23
24
import java .net .URI ;
24
25
import java .net .URISyntaxException ;
25
26
import java .net .URL ;
26
27
import java .nio .channels .ClosedByInterruptException ;
27
28
import java .nio .file .FileSystem ;
29
+ import java .nio .file .FileSystemAlreadyExistsException ;
28
30
import java .nio .file .FileSystems ;
29
31
import java .nio .file .FileVisitResult ;
30
32
import java .nio .file .Files ;
@@ -86,9 +88,8 @@ private static List<String> doGetClassNames(String basePackage, ClassLoader clas
86
88
URI uri = resource .toURI ();
87
89
List <String > result ;
88
90
if (uri .getScheme ().equals ("jar" )) {
89
- // avoids FileSystemAlreadyExistsException
90
91
synchronized (PackageScanner .class ) {
91
- try (FileSystem fileSystem = FileSystems . newFileSystem (uri , Collections .< String , Object > emptyMap () )) {
92
+ try (FileSystem fileSystem = getFileSystem (uri )) {
92
93
Path basePath = fileSystem .getPath (baseFolderResource ).toAbsolutePath ();
93
94
if (!Files .exists (basePath )) { // called in a privileged action, thus no need to deal with security manager
94
95
basePath = fileSystem .getPath ("agent/" + baseFolderResource ).toAbsolutePath ();
@@ -104,6 +105,21 @@ private static List<String> doGetClassNames(String basePackage, ClassLoader clas
104
105
return classNames ;
105
106
}
106
107
108
+ @ Nullable
109
+ private static FileSystem getFileSystem (URI uri ) throws IOException {
110
+ FileSystem fileSystem ;
111
+ // FileSystemAlreadyExistsException is thrown when FS has already been opened
112
+ // FileSystemNotFoundException is thrown when FS has not already been opened
113
+ // thus we can't avoid throwing exceptions, but we can use them for transparent fallback
114
+ // multiple calls for equivalent URIs is expected with "fat jar" that have nested paths with "!/../path/within/jar"
115
+ try {
116
+ fileSystem = FileSystems .newFileSystem (uri , Collections .<String , Object >emptyMap ());
117
+ } catch (FileSystemAlreadyExistsException e ) {
118
+ fileSystem = FileSystems .getFileSystem (uri );
119
+ }
120
+ return fileSystem ;
121
+ }
122
+
107
123
/**
108
124
* Lists all classes in the provided path, as part of the provided base package
109
125
* @param basePackage the package to prepend to all class files found in the relative path
0 commit comments