package org.smoothbuild.builtin.java.javac;
import static org.smoothbuild.io.fs.base.Path.path;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import org.smoothbuild.io.fs.base.Path;
import org.smoothbuild.lang.plugin.Container;
import org.smoothbuild.lang.value.Array;
import org.smoothbuild.lang.value.ArrayBuilder;
import org.smoothbuild.lang.value.SFile;
public class SandboxedJavaFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private final Container container;
private final Map<String, Set<JavaFileObject>> packageToJavaFileObjects;
private final ArrayBuilder<SFile> resultClassFiles;
SandboxedJavaFileManager(StandardJavaFileManager fileManager, Container container,
Iterable<InputClassFile> objects) {
super(fileManager);
this.container = container;
this.packageToJavaFileObjects = groupIntoPackages(objects);
this.resultClassFiles = container.create().arrayBuilder(SFile.class);
}
private static Map<String, Set<JavaFileObject>> groupIntoPackages(
Iterable<InputClassFile> objects) {
HashMap<String, Set<JavaFileObject>> result = new HashMap<>();
for (InputClassFile object : objects) {
String packageName = object.aPackage();
Set<JavaFileObject> aPackage = result.get(packageName);
if (aPackage == null) {
aPackage = new HashSet<>();
result.put(packageName, aPackage);
}
aPackage.add(object);
}
return result;
}
public Array<SFile> resultClassfiles() {
return resultClassFiles.build();
}
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind,
FileObject sibling) throws IOException {
if (location == StandardLocation.CLASS_OUTPUT && kind == Kind.CLASS) {
Path classFilePath = path(className.replace('.', '/') + ".class");
return new OutputClassFile(resultClassFiles, classFilePath, container);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof InputClassFile) {
return ((InputClassFile) file).binaryName();
} else {
return super.inferBinaryName(location, file);
}
}
public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds,
boolean recurse) throws IOException {
if (location == StandardLocation.CLASS_PATH) {
if (recurse) {
throw new UnsupportedOperationException(
"recurse is not supported by SandboxedJavaFileManager.list()");
}
Set<JavaFileObject> result = packageToJavaFileObjects.get(packageName);
if (result == null) {
return new ArrayList<>();
} else {
return result;
}
} else {
return super.list(location, packageName, kinds, recurse);
}
}
}