I have a simple annotation processor that needs to read a configuration file from the same project as the annotated classes. Example structure:
- myproject
- src
- main
- java
- my.package.SourceFile
- resources
- config.json
In the annotation processor, I try to read the file:
FileObject resource = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", "config.json");
but it throws FileNotFoundException
. I also tried other paths, such as ../resources/config.json
, (which throws Invalid relative name: ../resources/config.json
). And I tried putting the config file in src/main/java
(and even src/main/java/my/package
) instead, which I don't like, but that also still throws FileNotFoundException
.
It would already help if I could get filer.getResource()
to tell me where it's looking. To find that out, I tried generating a file:
filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "dummy");
which generated in myproject/build/classes/main/dummy
. Unfortunately, I can't generate in SOURCE_PATH
, so that doesn't help with finding this out.
I'd expect that the stuff from src/main/resources
gets copied to target/classes
during the build (prior to annotation processing). In that case you can open them like this:
ProcessingEnvironment pe = ...;
FileObject fileObject = pe.getFiler()
.getResource( StandardLocation.CLASS_OUTPUT, "", "config.json" );
InputStream jsonStream = fileObject.openInputStream();
I've looked at this with one of the Project Lombok developers. If anyone knows annotation processing, it's them ;)
Our conclusion was, that the JavacFileManager
that handles the request internally, does not have a path to resolve StandardLocation.SOURCE_PATH
to. We're not sure, but it might be related to building with Gradle.
I had the same problem and was searching for solution for a while and found this cool hack that does the trick for Android
And below you can see my solution from pure Java/Kotlin project
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")
}
Following function works for me with annotation processor being triggered by gradle, it's not the pretties one but works:
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()
}
where processingEnv
is a member of AbstractProcessor
If your element is instance of TypeElement
,then you can use these code to find your source code
FileObject fileObject = processingEnv.getFiler().getResource( StandardLocation.SOURCE_PATH, element.getEnclosingElement().toString(), element.getSimpleName() + ".java");
element.getEnclosingElement()
is your class package, eg: com.fool element.getSimpleName()
is your class name, eg: Person then you can print them: CharSequence content = fileObject.getCharContent(true);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.