我有一个简单的注释处理器,需要从与注释类相同的项目中读取配置文件。结构示例:
- myproject
- src
- main
- java
- my.package.SourceFile
- resources
- config.json
在注释处理器中,我尝试读取文件:
FileObject resource = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", "config.json");
但它会抛出
FileNotFoundException
。我还尝试了其他路径,例如 ../resources/config.json
(会抛出 Invalid relative name: ../resources/config.json
)。我尝试将配置文件放入 src/main/java
(甚至 src/main/java/my/package
)中,我不喜欢,但这仍然会抛出 FileNotFoundException
。
如果我能让
filer.getResource()
告诉我它在哪里,那就已经很有帮助了。为了找出答案,我尝试生成一个文件:
filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "dummy");
在
myproject/build/classes/main/dummy
中生成。不幸的是,我无法在 SOURCE_PATH
中生成,所以这对找出这个问题没有帮助。
我希望在构建期间(在注释处理之前)将
src/main/resources
中的内容复制到 target/classes
。在这种情况下,您可以像这样打开它们:
ProcessingEnvironment pe = ...;
FileObject fileObject = pe.getFiler()
.getResource( StandardLocation.CLASS_OUTPUT, "", "config.json" );
InputStream jsonStream = fileObject.openInputStream();
我和一位 Lombok 项目开发人员一起研究过这个问题。如果有人知道注释处理,那就是他们了;)
我们的结论是,内部处理请求的
JavacFileManager
没有解析 StandardLocation.SOURCE_PATH
的路径。我们不确定,但这可能与使用 Gradle 构建有关。
我遇到了同样的问题,并寻找解决方案一段时间,发现了这个很酷的黑客可以在Android上解决问题
下面你可以看到我的纯 Java/Kotlin 项目的解决方案
fun ProcessingEnvironment.getResourcesDirectory(): File {
val dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis())
var dummySourceFilePath = dummySourceFile.toUri().toString()
if (dummySourceFilePath.startsWith("file:")) {
if (!dummySourceFilePath.startsWith("file://")) {
dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length)
}
} else {
dummySourceFilePath = "file://$dummySourceFilePath"
}
val cleanURI = URI(dummySourceFilePath)
val dummyFile = File(cleanURI)
val projectRoot = dummyFile.parentFile.parentFile.parentFile.parentFile.parentFile
return File(projectRoot.absolutePath + "/resources")
}
以下功能对我有用,注释处理器由 gradle 触发,它不是漂亮的功能,但有效:
private fun resolveApplicationPropertiesFile(): File {
val projectRoot = Path.of(processingEnv.filer.getResource(StandardLocation.CLASS_OUTPUT, "", "doesntmatter")
.toUri())
.parent
.parent
.parent
.parent
.parent
.parent
val properties = Path.of(projectRoot.toString(), "src", "main", "resources", "application.yml")
return properties.toFile()
}
其中
processingEnv
是 AbstractProcessor
的成员
答案可能与某些用例无关。如果您想读取自己的配置/属性文件来处理注释。我在我的注释处理器中找到了解决办法 cURL。
我将
cURL.config
文件放在 src 文件夹的同一级别。然后我使用 System.getProperty("user.dir")
来获取文件夹路径。现在我可以读取该文件了。
my-java-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
├── cURL.config
├── pom.xml (for Maven projects)
└── build.gradle (for Gradle projects)
源代码
private static final String CURRENT_WORKING_DIR = System.getProperty("user.dir");
private static final String CONFIG_FILE = "cURL.config";
File configFile = new File(CURRENT_WORKING_DIR + File.separatorChar + CONFIG_FILE);
if (configFile.exists()) {
try (
FileInputStream fileInputStream = new FileInputStream(configFile)
) {
Properties properties = new Properties();
properties.load(fileInputStream);
String collectionName = properties.getProperty("collection.name");
} catch (Exception ignored) {
}
}
如果您想查看原始源代码,请查看github存储库https://github.com/BytesCraftIO/cURL。
如果您的元素是
TypeElement
的实例,那么您可以使用这些代码来查找您的源代码
FileObject fileObject = processingEnv.getFiler().getResource(
StandardLocation.SOURCE_PATH, element.getEnclosingElement().toString(),
element.getSimpleName() + ".java");
element.getEnclosingElement()
是你的类包,例如:com.foolelement.getSimpleName()
是你的班级名称,例如:Person然后你可以打印它们:
CharSequence content = fileObject.getCharContent(true);