package jadx.tests.api.compiler; import jadx.core.utils.files.FileUtils; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import static javax.tools.JavaCompiler.CompilationTask; public class StaticCompiler { private static final List<String> COMMON_ARGS = Arrays.asList("-source 1.6 -target 1.6".split(" ")); public static List<File> compile(List<File> files, File outDir, boolean includeDebugInfo) throws IOException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files); StaticFileManager staticFileManager = new StaticFileManager(fileManager, outDir); List<String> options = new ArrayList<String>(); options.add(includeDebugInfo ? "-g" : "-g:none"); options.addAll(COMMON_ARGS); CompilationTask task = compiler.getTask(null, staticFileManager, null, options, null, compilationUnits); Boolean result = task.call(); fileManager.close(); if (Boolean.TRUE.equals(result)) { return staticFileManager.outputFiles(); } return Collections.emptyList(); } private static class StaticFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { private List<File> files = new ArrayList<File>(); private File outDir; protected StaticFileManager(StandardJavaFileManager fileManager, File outDir) { super(fileManager); this.outDir = outDir; } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { if (kind == JavaFileObject.Kind.CLASS) { File file = new File(outDir, className.replace('.', '/') + ".class"); files.add(file); return new ClassFileObject(file, kind); } throw new UnsupportedOperationException("Can't save location with kind: " + kind); } public List<File> outputFiles() { return files; } } private static class ClassFileObject extends SimpleJavaFileObject { private File file; protected ClassFileObject(File file, Kind kind) { super(file.toURI(), kind); this.file = file; } @Override public OutputStream openOutputStream() throws IOException { FileUtils.makeDirsForFile(file); return new FileOutputStream(file); } } }