package com.ruoyi.buss.common.liquor; import javax.tools.*; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; /** * This code mainly from: Arthas project * */ 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; this.finder = new PackageInternalsFinder(classLoader); } @Override public JavaFileObject getJavaFileForOutput(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(Location location) { return classLoader; } @Override public String inferBinaryName(Location location, JavaFileObject file) { if (file instanceof CustomJavaFileObject) { return ((CustomJavaFileObject) file).getClassName(); } 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"); } } }