All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ideaaedi.component.compile.DynamicJavaFileManager Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
package com.ideaaedi.component.compile;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自定义{@link JavaFileManager}文件管理器,用于管.java文件、.class文件
 * 

* 为什么要重写{@link JavaFileManager}? *

* * @author JustryDeng * @since 2021/9/20 16:44:07 */ public class DynamicJavaFileManager extends ForwardingJavaFileManager { private final Map javaFileObjectMap = new ConcurrentHashMap<>(16); private final DynamicClassLoader classLoader; public DynamicJavaFileManager(JavaFileManager fileManager, DynamicClassLoader classLoader) { super(fileManager); this.classLoader = classLoader; } @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { JavaFileObject javaFileObject = javaFileObjectMap.get(determineKey(location, packageName, relativeName)); if (javaFileObject != null) { return javaFileObject; } return super.getFileForInput(location, packageName, relativeName); } /** * 这里是编译器返回的同(源)Java文件对象,替换为CharSequenceJavaFileObject实现 */ @Override public JavaFileObject getJavaFileForOutput(Location location, String classLongName, JavaFileObject.Kind kind, FileObject sibling) throws IOException { CharSequenceJavaFileObject javaFileObject = new CharSequenceJavaFileObject(classLongName, (InputStream) null); classLoader.registerCompiledSource(classLongName, javaFileObject); return javaFileObject; } @Override public ClassLoader getClassLoader(Location location) { // 使用自定义的类加载器 return classLoader; } @Override public String inferBinaryName(Location location, JavaFileObject file) { if (file instanceof CharSequenceJavaFileObject) { return file.getName(); } return super.inferBinaryName(location, file); } /** * 寻找JavaFileObject *

* 注:这个方法很关键,一个.java文件,可能依赖了很多其他依赖,此时,如果只对这个文件编译,那么会报错提示找不到对应的依赖, * 而通过这个方法就可以解决这个问题的 *

*/ @Override public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { List result = new ArrayList<>(16); // 先将原来的也加入进来 for (JavaFileObject javaFileObject : super.list(location, packageName, kinds, recurse)) { result.add(javaFileObject); } // 这里要区分编译的Location以及编译的Kind if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) { // .class文件以及classPath下, 这里需要额外添加类加载器加载的JavaFileObject for (JavaFileObject file : classLoader.listCharSequenceJavaFileObject()) { if (file.getName().startsWith(packageName)) { result.add(file); } } } else if (location == StandardLocation.SOURCE_PATH && kinds.contains(JavaFileObject.Kind.SOURCE)) { // .java文件以及编译路径下 for (JavaFileObject file : javaFileObjectMap.values()) { if (file.getName().startsWith(packageName)) { result.add(file); } } } return result; } /** * 自定义方法,用于添加和缓存待编译的源文件对象 */ public void addCharSequenceJavaFileObject(Location location, String packageName, String relativeName, CharSequenceJavaFileObject javaFileObject) { javaFileObjectMap.put(determineKey(location, packageName, relativeName), javaFileObject); } /** * 得到唯一key */ private static String determineKey(Location location, String packageName, String relativeName) { return location.getName() + '/' + packageName + '/' + relativeName; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy