com.taobao.arthas.compiler.DynamicJavaFileManager Maven / Gradle / Ivy
package com.taobao.arthas.compiler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
public class DynamicJavaFileManager extends ForwardingJavaFileManager {
private static final String[] superLocationNames = { StandardLocation.PLATFORM_CLASS_PATH.name(),
/** JPMS StandardLocation.SYSTEM_MODULES **/
"SYSTEM_MODULES" };
private final PackageInternalsFinder finder;
private final DynamicClassLoader classLoader;
private final List byteCodes = new ArrayList();
public DynamicJavaFileManager(JavaFileManager fileManager, DynamicClassLoader classLoader) {
super(fileManager);
this.classLoader = classLoader;
finder = new PackageInternalsFinder(classLoader);
}
@Override
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className,
JavaFileObject.Kind kind, FileObject sibling) throws IOException {
for (MemoryByteCode byteCode : byteCodes) {
if (byteCode.getClassName().equals(className)) {
return byteCode;
}
}
MemoryByteCode innerClass = new MemoryByteCode(className);
byteCodes.add(innerClass);
classLoader.registerCompiledSource(innerClass);
return innerClass;
}
@Override
public ClassLoader getClassLoader(JavaFileManager.Location location) {
return classLoader;
}
@Override
public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof CustomJavaFileObject) {
return ((CustomJavaFileObject) file).binaryName();
} else {
/**
* if it's not CustomJavaFileObject, then it's coming from standard file manager
* - let it handle the file
*/
return super.inferBinaryName(location, file);
}
}
@Override
public Iterable list(Location location, String packageName, Set kinds,
boolean recurse) throws IOException {
if (location instanceof StandardLocation) {
String locationName = ((StandardLocation) location).name();
for (String name : superLocationNames) {
if (name.equals(locationName)) {
return super.list(location, packageName, kinds, recurse);
}
}
}
// merge JavaFileObjects from specified ClassLoader
if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) {
return new IterableJoin(super.list(location, packageName, kinds, recurse),
finder.find(packageName));
}
return super.list(location, packageName, kinds, recurse);
}
static class IterableJoin implements Iterable {
private final Iterable first, next;
public IterableJoin(Iterable first, Iterable next) {
this.first = first;
this.next = next;
}
@Override
public Iterator iterator() {
return new IteratorJoin(first.iterator(), next.iterator());
}
}
static class IteratorJoin implements Iterator {
private final Iterator first, next;
public IteratorJoin(Iterator first, Iterator next) {
this.first = first;
this.next = next;
}
@Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
@Override
public T next() {
if (first.hasNext()) {
return first.next();
}
return next.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
}
}