use of org.revapi.query.Filter in project revapi by revapi.
the class ClasspathScanner method initTree.
void initTree() throws IOException {
List<ArchiveLocation> classPathLocations = classPath.keySet().stream().map(ArchiveLocation::new).collect(toList());
Scanner scanner = new Scanner();
for (ArchiveLocation loc : classPathLocations) {
scanner.scan(loc, classPath.get(loc.getArchive()), true);
}
SyntheticLocation allLoc = new SyntheticLocation();
fileManager.setLocation(allLoc, classPath.values());
Function<String, JavaFileObject> searchHard = className -> Stream.concat(Stream.of(allLoc), Stream.of(POSSIBLE_SYSTEM_CLASS_LOCATIONS)).map(l -> {
try {
return fileManager.getJavaFileForInput(l, className, JavaFileObject.Kind.CLASS);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}).filter(Objects::nonNull).findFirst().orElse(null);
Set<TypeElement> lastUnknowns = Collections.emptySet();
Map<String, ArchiveLocation> cachedArchives = new HashMap<>(additionalClassPath.size());
while (!scanner.requiredTypes.isEmpty() && !lastUnknowns.equals(scanner.requiredTypes.keySet())) {
lastUnknowns = new HashSet<>(scanner.requiredTypes.keySet());
for (TypeElement t : lastUnknowns) {
String name = environment.getElementUtils().getBinaryName(t).toString();
JavaFileObject jfo = searchHard.apply(name);
if (jfo == null) {
// this type is really missing
continue;
}
URI uri = jfo.toUri();
String path;
if ("jar".equals(uri.getScheme())) {
// we pass our archives as jars, so let's dig only into those
path = uri.getSchemeSpecificPart();
// jar:file:/path .. let's get rid of the "file:" part
int colonIdx = path.indexOf(':');
if (colonIdx >= 0) {
path = path.substring(colonIdx + 1);
}
// separate the file path from the in-jar path
path = path.substring(0, path.lastIndexOf('!'));
// remove superfluous forward slashes at the start of the path, if any
int lastSlashIdx = -1;
for (int i = 0; i < path.length() - 1; ++i) {
if (path.charAt(i) == '/' && path.charAt(i + 1) != '/') {
lastSlashIdx = i;
break;
}
}
if (lastSlashIdx > 0) {
path = path.substring(lastSlashIdx);
}
} else {
path = uri.getPath();
}
ArchiveLocation loc = cachedArchives.get(path);
if (loc == null) {
Archive ar = null;
for (Map.Entry<Archive, File> e : additionalClassPath.entrySet()) {
if (e.getValue().getAbsolutePath().equals(path)) {
ar = e.getKey();
break;
}
}
if (ar != null) {
loc = new ArchiveLocation(ar);
cachedArchives.put(path, loc);
}
}
if (loc != null) {
scanner.scanClass(loc, t, false);
}
}
}
// ok, so scanning the archives doesn't give us any new resolved classes that we need in the API...
// let's scan the system classpath. What will be left after this will be the truly missing classes.
// making a copy because the required types might be modified during scanning
Map<TypeElement, Boolean> rts = new HashMap<>(scanner.requiredTypes);
ArchiveLocation systemClassPath = new ArchiveLocation(new Archive() {
@Nonnull
@Override
public String getName() {
return SYSTEM_CLASSPATH_NAME;
}
@Nonnull
@Override
public InputStream openStream() throws IOException {
throw new UnsupportedOperationException();
}
});
for (Map.Entry<TypeElement, Boolean> e : rts.entrySet()) {
scanner.scanClass(systemClassPath, e.getKey(), false);
}
scanner.initEnvironment();
}
Aggregations