package fr.inria.diversify.buildSystem; import fr.inria.diversify.util.Log; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * User: Simon * Date: 02/12/13 * Time: 14:12 */ public abstract class AbstractBuilder { //Directory where the builder is going to be saved in case the user requested private String saveOutputDir; protected String directory; //Was there a compile error? protected boolean compileError; //Did all the test run protected boolean allTestRun; //Goals of the compiler protected String[] goals; //setting file for the compiler protected File setting; //Errors that we are OK with... protected List<String> acceptedErrors; //-3 nothing //-2 not compile //-1 compile, error in test //0 compile, all test green protected Integer status = -3; //Time out in milliseconds to stop the compiler protected int timeOut = -1; protected boolean clojureTest; protected Set<Thread> threadSet; //Number of time the run builder has been called protected int runCount; //Save the output to file for further analysis? private boolean saveOutputToFile; public void setSaveOutputToFile(boolean value) { saveOutputToFile = value; } /** * Gets wheter output to file for further analysis or not * * @return */ public boolean getSaveOutputToFile() { return saveOutputToFile; } protected List<String> failedTests; public List<String> getFailedTests() { return failedTests; } // /** // * Resettable latch to wait for the builder // */ // protected CountDownLatch latch; public AbstractBuilder(String directory) { this.directory = directory; failedTests = new ArrayList<>(); acceptedErrors = new ArrayList<>(); runCount = 0; saveOutputToFile = false; saveOutputDir = "buildoutput"; // latch = new CountDownLatch(1); } protected void reset() { compileError = false; allTestRun = false; status = -3; failedTests = new ArrayList<>(); } public void runBuilder() throws InterruptedException { runBuilder(null); } public void runBuilder(final String[] goals) throws InterruptedException { initThreadGroup(); reset(); Thread thread = new Thread() { public void run() { runPrivate(goals, true); } }; thread.start(); thread.join(1000 * timeOut); thread.interrupt(); killUselessThread(); } public void initTimeOut() throws InterruptedException { timeOut = runGoals(goals, true) * 4; Log.debug("timeOut init: " + timeOut); } public void startAndroidEmulation() throws InterruptedException { Log.debug("start android emulator"); runGoals(new String[]{"android:emulator-start", "-Dandroid.emulator.avd=myandroid", "-Dandroid.emulator.options=\"-no-window -no-audio -no-boot-anim -wipe-data\"", "-Dandroid.emulator.wait=100000"}, false); } public void stopAndroidEmulation() throws InterruptedException { Log.debug("stop android emulator"); runGoals(new String[]{"android:emulator-stop-all"}, false); } public int runGoals(final String[] goals, final boolean verbose) throws InterruptedException { initThreadGroup(); reset(); Thread thread = new Thread() { public void run() { runPrivate(goals, verbose); } }; thread.start(); int time = 0; while (status == -3) { time++; Thread.sleep(1000); } Log.debug("timeOut init: " + time); thread.interrupt(); //See if we are in windows and not call this killUselessThread(); return time; } public void copyClasses(String classes) throws IOException { String[] tmp = classes.split("target"); File destDir = new File(directory+"/"+tmp[0]+"/classes2"); File classesDir = new File(directory+"/"+classes); FileUtils.deleteDirectory(destDir); FileUtils.copyDirectory(classesDir, destDir); } public void initPom(String newPomFile) throws Exception { if (timeOut == -1) throw new Exception("timeout not set"); FileUtils.copyFile(new File(newPomFile), new File(directory + "/pom.xml")); } /** * Method to run in the compiler's thread */ protected abstract void runPrivate(String[] goals, boolean verbose); protected void initThreadGroup() { threadSet = Thread.getAllStackTraces().keySet(); } /** * Kill the maven thread that may be hang in Linux */ protected void killUselessThread() { if (!System.getProperty("os.name").contains("Windows")) { killAllChildrenProcess(); for (Thread thread : Thread.getAllStackTraces().keySet()) { if (!threadSet.contains(thread)) { thread.interrupt(); } } } } protected void killAllChildrenProcess() { String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; Runtime r = Runtime.getRuntime(); try { r.exec("pkill -P " + pid); Thread.sleep(1000); } catch (Exception e) { Log.error("killallchildren ", e); } Log.debug("all children process kill (pid: {})", pid); } protected void saveOutputToFile(String output) { try { if (saveOutputToFile) { File f = new File(getSaveOutputDir()); if (!f.exists()) { f.mkdirs(); } File newTextFile = new File(getSaveOutputDir() + "/buidOutput" + runCount + ".txt"); FileWriter fileWriter = new FileWriter(newTextFile); fileWriter.write(output); fileWriter.close(); } } catch (IOException e) { throw new RuntimeException(e); //Log.warn("Cannot save output for run " + runCount); } } public Integer getStatus() { return status; } public List<String> getTestFail() { return failedTests; } public boolean allTestRun() { return allTestRun; } public boolean getCompileError() { return compileError; } public void setTimeOut(int timeOut) { this.timeOut = timeOut; } public void setClojureTest(boolean clojureTest) { this.clojureTest = clojureTest; } public void setGoals(String[] goals) { this.goals = goals; } public void setDirectory(String directory) { this.directory = directory; } public void setAcceptedErrors(List<String> ae) { acceptedErrors = ae; } /** * Resets the locate count */ public void resetRunCount() { } /** * Number of times the locate has been run * * @return */ public int getRunCount() { return runCount; } /** * Directory where the builder is going to be saved in case the user request so * * @return */ public String getSaveOutputDir() { return saveOutputDir; } public void setSaveOutputDir(String saveOutputDir) { this.saveOutputDir = saveOutputDir; } public void setSetting(File setting) { this.setting = setting; } // public void setStatus(int status) { // this.status = status; // } public String getDirectory() { return directory; } }