package fr.inria.diversify.sosie.logger; import fr.inria.diversify.factories.SpoonMetaFactory; import fr.inria.diversify.sosie.logger.processor.*; import fr.inria.diversify.transformation.Transformation; import fr.inria.diversify.util.JavaOutputProcessorWithFilter; import org.apache.commons.io.FileUtils; import spoon.compiler.Environment; import spoon.processing.AbstractProcessor; import spoon.processing.ProcessingManager; import spoon.reflect.factory.Factory; import spoon.reflect.visitor.DefaultJavaPrettyPrinter; import spoon.support.QueueProcessingManager; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * Created by Simon on 20/06/14. */ public class Instru { protected String outputDirectory; protected String projectDirectory; protected String srcDirectory; protected String testDirectory; protected List<Transformation> transformations; private int javaVersion; private String logger; //What to instrument? //Instrument method calls private boolean methodCall; //Instrument variables private boolean variable; //Instrument errors private boolean error; //Instrument asserts count private boolean assertCount; //Instrument test count private boolean testCount; //Instrument new test private boolean newTest; private boolean useSourceCodeFragments; //Instrument call counts over transplantation points private boolean transplantationPointCallCount; private TransplantationPointCallCountInstrumenter tpcInstrumenter = null; private Factory sourceFactory = null; private Factory testFactory = null; private boolean onlyCopyLoggerCode; public Instru(String projectDirectory, String srcDirectory, String testDirectory, int javaVersion, String outputDirectory, List<Transformation> transformations) { this.projectDirectory = projectDirectory; this.srcDirectory = srcDirectory; this.testDirectory = testDirectory; this.outputDirectory = outputDirectory; this.transformations = transformations; this.javaVersion = javaVersion; } public void copyLogger() throws IOException { copyLogger(outputDirectory, srcDirectory); } public void instru() throws IOException { if ( onlyCopyLoggerCode ) { copyLogger(outputDirectory, srcDirectory); } initOutputDirectory(); if(methodCall || variable || error || getTransplantationPointCallCount()) instruMainSrc(); if(assertCount || newTest || testCount) instruTestSrc(); writeId(); } protected void initOutputDirectory() throws IOException { File dir = new File(outputDirectory); dir.mkdirs(); FileUtils.copyDirectory(new File(projectDirectory), dir); } protected void writeId() throws IOException { TestLoggingInstrumenter.writeIdFile(outputDirectory); TransplantationPointCallCountInstrumenter.writeIdFile(outputDirectory); if(tpcInstrumenter != null) tpcInstrumenter.writeIdMapToFile(outputDirectory + "/tpcid.json"); VariableLoggingInstrumenter.writeIdFile(outputDirectory); copyLogger(outputDirectory, srcDirectory); FileWriter partialLogging = new FileWriter(outputDirectory + "/log/partialLogging"); if(transformations != null) { partialLogging.write("true"); } else { partialLogging.write("false"); } partialLogging.close(); } protected void instruMainSrc() { String src = projectDirectory + "/" + srcDirectory; if ( sourceFactory == null ) { sourceFactory = initSpoon(src); } if(methodCall) { MethodLoggingInstrumenter m = new MethodLoggingInstrumenter(transformations); m.setLogger(logger); applyProcessor(sourceFactory, m); } if(variable) { // VariableLoggingInstrumenter v = new VariableLoggingInstrumenter(transformations); FieldUsedInstrumenter v = new FieldUsedInstrumenter(transformations); v.setLogger(logger); applyProcessor(sourceFactory, v); } if(error) { ErrorLoggingInstrumenter e = new ErrorLoggingInstrumenter(transformations); e.setLogger(logger); applyProcessor(sourceFactory, e); } if (transplantationPointCallCount) { tpcInstrumenter = new TransplantationPointCallCountInstrumenter(transformations); tpcInstrumenter.setLogger(logger); applyProcessor(sourceFactory, tpcInstrumenter); } File fileFrom = new File(src); File out = new File(outputDirectory + "/" + srcDirectory); writeJavaClass(sourceFactory, out, fileFrom); } protected void instruTestSrc() { String test = projectDirectory + "/" + testDirectory; String main = projectDirectory + "/" + srcDirectory; if ( testFactory == null ) { testFactory = initSpoon(test+":"+main); } if(assertCount) { applyProcessor(testFactory, new AssertCountInstrumenter()); } if(testCount) { applyProcessor(testFactory, new TestCountInstrumenter()); } if(newTest) { applyProcessor(testFactory, new TestLoggingInstrumenter()); } File fileFrom = new File(test); File out = new File(outputDirectory + "/" + testDirectory); writeJavaClass(testFactory, out, fileFrom); } protected void writeJavaClass(Factory factory, File out, File fileFrom) { Environment env = factory.getEnvironment(); AbstractProcessor processor = new JavaOutputProcessorWithFilter(out, new DefaultJavaPrettyPrinter(env), allClassesName(fileFrom)); applyProcessor(factory, processor); } protected void copyLogger(String tmpDir, String src) throws IOException { File dir = new File(tmpDir+"/"+src+ "/fr/inria/diversify/sosie/logger"); FileUtils.forceMkdir(dir); String packagePath = System.getProperty("user.dir")+"/src/main/java/fr/inria/diversify/sosie/logger/"; FileUtils.copyFileToDirectory(new File(packagePath + LogWriter.class.getSimpleName() + ".java"), dir); FileUtils.copyFileToDirectory(new File(packagePath + ShutdownHookLog.class.getSimpleName() + ".java"), dir); FileUtils.copyFileToDirectory(new File(packagePath + BinLogWriter.class.getSimpleName() + ".java"),dir); FileUtils.copyFileToDirectory(new File(packagePath + InstruLogWriter.class.getSimpleName() + ".java"),dir); FileUtils.copyFileToDirectory(new File(packagePath + InstruVerboseLog.class.getSimpleName() + ".java"),dir); FileUtils.copyFileToDirectory(new File(packagePath + InstruBinaryLog.class.getSimpleName() + ".java"),dir); dir = new File(tmpDir+"/"+src+ "/fr/inria/diversify/testamplification/logger"); FileUtils.forceMkdir(dir); packagePath = System.getProperty("user.dir")+"/src/main/java/fr/inria/diversify/testamplification/logger/"; FileUtils.copyFileToDirectory(new File(packagePath + fr.inria.diversify.testamplification.logger.Logger.class.getSimpleName() + ".java"), dir); FileUtils.copyFileToDirectory(new File(packagePath + fr.inria.diversify.testamplification.logger.ShutdownHookLog.class.getSimpleName() + ".java"), dir); FileUtils.copyFileToDirectory(new File(packagePath + fr.inria.diversify.testamplification.logger.LogWriter.class.getSimpleName() + ".java"),dir); FileUtils.copyFileToDirectory(new File(packagePath + fr.inria.diversify.testamplification.logger.VerboseLogWriter.class.getSimpleName() + ".java"),dir); FileUtils.copyFileToDirectory(new File(packagePath + fr.inria.diversify.testamplification.logger.DeepLogWriter.class.getSimpleName() + ".java"),dir); } protected Factory initSpoon(String srcDirectory) { try { return new SpoonMetaFactory().buildNewFactory(srcDirectory, javaVersion); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { throw new RuntimeException(e); } } protected void applyProcessor(Factory factory, AbstractProcessor processor) { ProcessingManager pm = new QueueProcessingManager(factory); processor.setFactory(factory); pm.addProcessor(processor); pm.process(); } protected List<String> allClassesName(File dir) { List<String> list = new ArrayList<>(); for(File file : dir.listFiles()) if(file.isDirectory()) list.addAll(allClassesName(file)); else { String name = file.getName(); if(name.endsWith(".java")) { String[] tmp = name.substring(0, name.length() - 5).split("/"); list.add(tmp[tmp.length - 1]); } } return list; } public void setLogger(String logger) { this.logger = logger; } public boolean getMethodCall() { return methodCall; } public void setMethodCall(boolean methodCall) { this.methodCall = methodCall; } public boolean getVariable() { return variable; } public void setVariable(boolean variable) { this.variable = variable; } public boolean getError() { return error; } public void setError(boolean error) { this.error = error; } public boolean getNewTest() { return newTest; } public void setNewTest(boolean newTest) { this.newTest = newTest; } public boolean getTransplantationPointCallCount() { return transplantationPointCallCount; } public void setTransplantationPointCallCount(boolean transplantationPointCallCount) { this.transplantationPointCallCount = transplantationPointCallCount; } public void setSourceFactory(Factory sourceFactory) { this.sourceFactory = sourceFactory; } public Factory getSourceFactory() { return sourceFactory; } public Factory getTestFactory() { return testFactory; } public void setTestFactory(Factory testFactorty) { this.testFactory = testFactorty; } public void setOnlyCopyLoggerCode(boolean onlyCopyLoggerCode) { this.onlyCopyLoggerCode = onlyCopyLoggerCode; } public boolean isOnlyCopyLoggerCode() { return onlyCopyLoggerCode; } public void setAssertCount(boolean assertCount) { this.assertCount = assertCount; } public void setTestCount(boolean testCount) { this.testCount = testCount; } public void setUseSourceCodeFragments(boolean useSourceCodeFragments) { this.useSourceCodeFragments = useSourceCodeFragments; } }