This content has been marked as final. Show 5 replies
You don't need a File to do what you want. Even if you could, it would be wrong to use a file.
It would be wrong, because the compiler might not by using a JavaFileManager that is actually backed by a filesystem. It could be backed by some form of repository such as a database, or it could be backed by a transient in memory file system ( An example of the latter is the [annotation processor test framework|https://hickory.dev.java.net/nonav/apidocs/index.html?net/java/dev/hickory/testing/package-summary.html] in hickory)
But probably of more interest to you, you don't need to because you can simply [get an InputStream|http://java.sun.com/javase/6/docs/api/javax/tools/FileObject.html#openInputStream()] from the FileObject returned from [filer.getResource(...)|http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Filer.html#getResource(javax.tools.JavaFileManager.Location,%20java.lang.CharSequence,%20java.lang.CharSequence)] and read it.
You might also find the [Compiler Tree API|http://java.sun.com/javase/6/docs/jdk/api/javac/tree/index.html] useful. The Compiler Tree API is available to annotation processors running in Oracle's (Sun's) javac, but not in other compilers (possibly limiting portability).
With this API you can [convert |http://java.sun.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/util/Trees.html#getPath(javax.lang.model.element.Element)] the Element representing the annotation to a Treepath then [get the leaf node|http://java.sun.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/util/TreePath.html#getLeaf()] and from that tree [obtain its offsets|http://java.sun.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/util/Trees.html#getSourcePositions()] within the source file.
Hi Bruce, thanks for the reply. I've tried the Complier Tree API as you suggested and that works fine. However I would prefer to use the filer#getResource(...) and that's the core of the problem. I don't know how to create the parameters correctly without embedding a hardwired string, representing the source files root folder, as a prefix to the package string in the second parameter of the getResource(...) method.
I'd try [StandardLocation.SOURCE_PATH|http://java.sun.com/javase/6/docs/api/javax/tools/StandardLocation.html#SOURCE_PATH] as first argument to getResource()
The second argument is simply the package name with dots. from the Element recursively call getEnclosingElement until element.getKind() returns ElementKind.PACKAGE, , thats the PackageElement - gets its qualified name - second arg done.
The third argument is the filename which you have to (in theory) guess. In the above recursion the element you had before the package is the outermost TypeElement (class, interface, enum or annotation type).
You have to assume there is only one type element per file (which is not necessarily the case, but for a system following conventions it will be - and even for an unconventional system it will be if the top level element is public).
So get the simple name of this top level type element, and append ".java" to it. That will probably be the file name of the source file relative to the package - 3rd arg done.
Get the resource, get the input stream.
Possibly use the tree APIs CompilationUnitTree.getSourceMap() to convert to TreePositions to line numbers and work out which line you want to index to, and work out the offset in the file of the start of that line. Index through the stream and start reading.
If you are using Tree API, you could just bypass Filer.getResource() and simply convert your Element to a TreePath, gets its CompilationUnitTree (1st item in TreePath), and from there getSourceFile() and thence the InputStream, and proceed with ofset calculations.