package generic; import java.io.File; import org.apache.commons.io.FileUtils; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.Vector; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; /** * \brief Uses the CommandExecutor to compile java files and build .jar files<br> * * This class add support for compiling .java files and manipulating .jar files. * bugs: none found<br> */ public class JavaCompiler extends CommandExecutor { public class CompileUnit { public boolean active = true; public boolean packToJar = true; public String loc_input = "src"; public String loc_base_input = ""; public String loc_output = "build"; public String mainClass = ""; public Boolean runnableJar = false; public String customJarName = ""; public Vector<String> loc_class = new Vector<String>(); // Compilation unit defaults to building src/ into build/ public CompileUnit() { } // Compilation unit defaults to building src/ into build/ public CompileUnit(String src_path, String out_path) { loc_input = src_path; loc_output = out_path; } // Compilation unit defaults to building src/ into build/ public CompileUnit(String src_path, String out_path, String[] deps) { this(src_path, out_path); addDependencies(deps); } // Compilation unit defaults to building src/ into build/ public CompileUnit(String src_path, String out_path, String[] deps, String mainClass) { this(src_path, out_path, deps); setMainClass(mainClass); } // Adds a dependancy *.jar files will be re packed into 1 single jar // Can also be used to make out of source builds for packages public void addDependency(String path) { loc_class.add(path); } // Adds a list of dependancies public void addDependencies(String[] path) { for (String p : path) { addDependency(p); } } // getJarName get the output jar name public String getJarName() { if (customJarName != "") { return customJarName + ".jar"; } else { if (loc_input.contains(File.separator)) { return loc_input.substring(loc_input.lastIndexOf(File.separator) + 1) + ".jar"; } return loc_input + ".jar"; } } // Get the dependencies string we can use on the javac classpath public String getDependencies() { String input = loc_base_input + File.separator + loc_input; input = input.startsWith(File.separator) ? input.substring(1) : input; String out = loc_output + ";" + input; for (String d : loc_class) { out = out + ";" + (d.startsWith(File.separator) ? d.substring(1) : d); } return out; } // Set the base baseDir for compilation (Easier out of source ?) public void setBaseDir(String baseDir) { loc_base_input = baseDir; } // Sets the main class name for the Manifest public void setMainClass(String name) { mainClass = name; runnableJar = true; } public void setCustomJarName(String name) { customJarName = name; } public Boolean isRunnableJar() { return runnableJar; } } CompileUnit tocompile = new CompileUnit(); ArrayList<Thread> running_tasks = new ArrayList<Thread>(); public JavaCompiler() { super(); } public JavaCompiler(CompileUnit u) { super(); tocompile = u; } public void CompileTarget(CompileUnit c) { Utils.console("Active compile target: " + c.loc_input); c = addCompileTarget(c, ((!c.loc_base_input.equals("")) ? c.loc_base_input + File.separator : "") + c.loc_input); addtask(new Thread(this)); if (c.active) { tocompile = c; waitForFinish(); cleartasks(); } else { Utils.console("Inactive compile target"); } } private CompileUnit addCompileTarget(CompileUnit c, String inputlocation) { File path = new File(inputlocation); if (path.exists()) { File[] files = path.listFiles(); for (int i = 0; i < files.length; i++) { if (!files[i].isDirectory()) { if (files[i].getName().endsWith("java")) { String command = "javac " + files[i].getAbsolutePath() + " -d " + c.loc_output + " -cp " + c.getDependencies(); addCommand(command); } else { File d = new File(inputlocation.replace(c.loc_input, c.loc_output)); d.mkdirs(); addCommand("copy " + files[i].getAbsolutePath() + " " + d.getAbsolutePath() + " /Y"); } } else { c = addCompileTarget(c, files[i].getAbsolutePath()); } } } else { System.err.println("No such path: " + inputlocation + "Compilation Unit DISABLED"); c.active = false; } return c; } void toJarFile(String jarfilepath) { try { File tofp = new File(jarfilepath); File fromfp = new File(tocompile.loc_output); if (tofp.exists()) { System.err.println("Overwriting old jar: " + jarfilepath); tofp.delete(); } File f = new File(tocompile.loc_output + File.separator + "/MANIFEST.MF"); JarOutputStream zos; FileOutputStream fos; if (f.exists()) { FileInputStream i = new FileInputStream(f); Manifest manifest = new Manifest(i); fos = new FileOutputStream(tofp); zos = new JarOutputStream(fos, manifest); } else { fos = new FileOutputStream(tofp); zos = new JarOutputStream(fos); } File[] files = fromfp.listFiles(); generic.FileUtils.writeInJar(zos, files, "", true); zos.close(); System.out.println("Build a JAR: " + jarfilepath); } catch (Exception e) { Utils.log("Something wrong: ", e); } } public void run() { if (!tocompile.active) return; File f = new File(tocompile.loc_output); FileUtils.deleteQuietly(f); f.mkdirs(); for (String location : tocompile.loc_class) { generic.FileUtils.unJar(location, tocompile.loc_output, false); } super.run(); if (tocompile.packToJar) { if (tocompile.isRunnableJar()) { generic.FileUtils.createManifestFile(tocompile.loc_output, tocompile.mainClass, "Danny Arends"); } toJarFile(tocompile.getJarName()); FileUtils.deleteQuietly(f); } } public void addtask(Thread task) { running_tasks.add(task); } public void cleartasks() { running_tasks.clear(); } public void waitForFinish() { for (Thread task : running_tasks) { try { task.start(); } catch (Exception e) { System.err.println("Error starting job is the JavaCompiler Cleared (cleartasks())? "); } } boolean process_done = false; while (!process_done) { process_done = true; for (Thread task : running_tasks) { if (task.isAlive()) { process_done = false; } try { Thread.sleep(100); } catch (Exception ie) { } } } } public CompileUnit newCompileUnit() { return new CompileUnit(); } public CompileUnit newCompileUnit(String src_path, String out_path) { return new CompileUnit(src_path, out_path); } }