Yes, this is totally possible as long as you properly implement the ForwardingJavaFileManager. The two most important methods are inferBinaryName() and list(). If you set these two up properly, the compiler will be able to resolve classes that you've previously compiled.
inferBinaryName() must return the class' simple name (e.g. the inferred binary name for com.test.Test would be just Test). Here is my implementation (my subclass of JavaFileObject is called InAppJavaFileObject):
@Override
public String inferBinaryName(Location location, JavaFileObject javaFileObject) {
if(location == StandardLocation.CLASS_PATH && javaFileObject instanceof InAppJavaFileObject) {
return StringUtils.substringBeforeLast(javaFileObject.getName(), ".java");
}
return super.inferBinaryName(location, javaFileObject);
}
Note that I'm stripping off ".java" from the end. When constructing a JavaFileObject, the file name must end in ".java", but if you don't strip the suffix later, the compiler won't find your class.
list() is a little bit more complicated because you have to be careful to play along nicely with your delegate file manager. In my implementation, I keep a map of fully-qualified class name to my subclass of JavaFileObject that I can iterate over:
@Override
public Iterable<JavaFileObject> list(Location action, String pkg, Set<JavaFileObject.Kind> kind, boolean recurse) throws IOException {
Iterable<JavaFileObject> superFiles = super.list(action, pkg, kind, recurse);
// see if there's anything in our cache that matches the criteria.
if(action == StandardLocation.CLASS_PATH && (kind.contains(JavaFileObject.Kind.CLASS) || kind.contains(JavaFileObject.Kind.SOURCE))) {
List<JavaFileObject> ourFiles = new ArrayList<JavaFileObject>();
for(Map.Entry<String,InAppJavaFileObject> entry : files.entrySet()) {
String className = entry.getKey();
if(className.startsWith(pkg) && ("".equals(pkg) || pkg.equals(className.substring(0, className.lastIndexOf('.'))))) {
ourFiles.add(entry.getValue());
}
}
if(ourFiles.size() > 0) {
for(JavaFileObject javaFileObject : superFiles) {
ourFiles.add(javaFileObject);
}
return ourFiles;
}
}
// nothing found in our hash map that matches the criteria... return
// whatever super came up with.
return superFiles;
}
Once you have those methods properly implemented, the rest just works. Enjoy!