ar.edu.taco.TacoMain.java Source code

Java tutorial

Introduction

Here is the source code for ar.edu.taco.TacoMain.java

Source

/*
 * TACO: Translation of Annotated COde
 * Copyright (c) 2010 Universidad de Buenos Aires
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA,
 * 02110-1301, USA
 */
package ar.edu.taco;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.multijava.mjc.JCompilationUnitType;

import ar.edu.jdynalloy.JDynAlloyConfig;
import ar.edu.jdynalloy.MethodToCheckNotFoundException;
import ar.edu.jdynalloy.ast.JDynAlloyModule;
import ar.edu.jdynalloy.xlator.JType;
import ar.edu.taco.engine.AlloyStage;
import ar.edu.taco.engine.DynalloyStage;
import ar.edu.taco.engine.JDynAlloyParsingStage;
import ar.edu.taco.engine.JDynAlloyPrinterStage;
import ar.edu.taco.engine.JDynAlloyStage;
import ar.edu.taco.engine.JUnitStage;
import ar.edu.taco.engine.JavaTraceStage;
import ar.edu.taco.engine.JmlStage;
import ar.edu.taco.engine.PrecompiledModules;
import ar.edu.taco.engine.SimpleJmlStage;
import ar.edu.taco.engine.SnapshotStage;
import ar.edu.taco.engine.StrykerStage;
import ar.edu.taco.jfsl.JfslStage;
import ar.edu.taco.jml.JmlToSimpleJmlContext;
import ar.edu.taco.jml.parser.JmlParser;
import ar.edu.taco.junit.RecoveredInformation;
import ar.edu.taco.simplejml.SimpleJmlToJDynAlloyContext;
import ar.uba.dc.rfm.alloy.AlloyTyping;
import ar.uba.dc.rfm.alloy.ast.expressions.ExprVariable;
import ar.uba.dc.rfm.alloy.ast.formulas.AlloyFormula;
import ar.uba.dc.rfm.dynalloy.DynAlloyCompiler;
import ar.uba.dc.rfm.dynalloy.analyzer.AlloyAnalysisResult;

/**
 * <p>Runs the TACO analysis.</p>
 * <p>The configuration options must be stated through the configuration file
 * whose name expects the methods <code>ar.edu.taco.TacoMain.run</code>.
 * Those configurations can be overridden by the sencond argument of 
 * <code>ar.edu.taco.TacoMain.run(String, Properties)</code>.</p>
 * <h3>Integers</h3>
 * <p>TACO can analyse code using Alloy integers or Java-like Integers.
 * In either case, the meaning of the bitwidth value is the same: a bound 
 * in the count of numbers TACO will deal with. In particular, it states that 
 * the range of integers used in the analysis include from -2^{bitwidth-1} 
 * to 2^{bitwidth-1}-1.</p>
 * <p>Besides that, TACO can try to infer the value of the scopes to be used
 * for the analysis. If the bitwidth is setted to a non positive integer 
 * <b>and</b> the scope inferring feature is activated, the bitwidth is also 
 * inferred. Otherwise, the bitwidth value setted is used.</p>
 * 
 * @author unknown (jgaleotti?)
 *
 */
public class TacoMain {

    private static Logger log = Logger.getLogger(TacoMain.class);

    private static final String CMD = "Taco";
    private static final String HEADER = "Taco static analysis tool.";
    private static final String FOOTER = "For questions and comments please write to jgaleotti AT dc DOT uba DOT ar";
    public static final String PATH_SEP = System.getProperty("path.separator");
    public static final String FILE_SEP = System.getProperty("file.separator");

    /**
     * @param args
     */
    @SuppressWarnings({ "static-access" })
    public static void main(String[] args) {
        @SuppressWarnings("unused")
        int loopUnrolling = 3;

        String tacoVersion = getManifestAttribute(Attributes.Name.IMPLEMENTATION_VERSION);
        String tacoCreatedBy = getManifestAttribute(new Name("Created-By"));

        System.out.println("TACO: Taco static analysis tool.");
        System.out.println("Created By: " + tacoCreatedBy);
        System.out.println("Version: " + tacoVersion);
        System.out.println("");
        System.out.println("");

        Option helpOption = new Option("h", "help", false, "print this message");
        Option versionOption = new Option("v", "version", false, "shows version");

        Option configFileOption = OptionBuilder.withArgName("path").withLongOpt("configFile").hasArg()
                .withDescription("set the configuration file").create("cf");
        Option classToCheckOption = OptionBuilder.withArgName("classname").withLongOpt("classToCheck").hasArg()
                .withDescription("set the class to be checked").create('c');
        Option methodToCheckOption = OptionBuilder.withArgName("methodname").withLongOpt("methodToCheck").hasArg()
                .withDescription("set the method to be checked").create('m');
        Option dependenciesOption = OptionBuilder.withArgName("classname").withLongOpt("dependencies").hasArgs()
                .withDescription("additional sources to be parsed").create('d');
        Option relevantClassesOption = OptionBuilder.withArgName("classname").withLongOpt("relevantClasses")
                .hasArgs().withDescription("Set the relevant classes to be used").create("rd");
        Option loopsOptions = OptionBuilder.withArgName("integer").withLongOpt("unroll").hasArg()
                .withDescription("set number of loop unrollings").create('u');
        Option bitOptions = OptionBuilder.withArgName("integer").withLongOpt("width").hasArg()
                .withDescription("set bit width").create('w');
        Option instOptions = OptionBuilder.withArgName("integer").withLongOpt("bound").hasArg()
                .withDescription("set class bound").create('b');
        Option skolemizeOption = OptionBuilder.withLongOpt("skolemize")
                .withDescription("set whether or not skolemize").create("sk");
        Option simulateOption = OptionBuilder.withLongOpt("simulate")
                .withDescription("run method instead of checking").create("r");
        Option modularReasoningOption = OptionBuilder.withLongOpt("modularReasoning")
                .withDescription("check method using modular reasoning").create("mr");
        Option relevancyAnalysisOption = OptionBuilder.withLongOpt("relevancyAnalysis")
                .withDescription("calculate the needed relevantClasses").create("ra");
        Option scopeRestrictionOption = OptionBuilder.withLongOpt("scopeRestriction")
                .withDescription("restrict signature scope to value set in -b option").create("sr");
        /*
         * Option noVerifyOption = OptionBuilder.withLongOpt(
         * "noVerify").withDescription(
         * "builds output but does not invoke verification engine").create(
         * "nv");
         */
        Options options = new Options();
        options.addOption(helpOption);
        options.addOption(versionOption);
        options.addOption(configFileOption);
        options.addOption(classToCheckOption);
        options.addOption(methodToCheckOption);
        options.addOption(dependenciesOption);
        options.addOption(relevantClassesOption);
        options.addOption(loopsOptions);
        options.addOption(bitOptions);
        options.addOption(instOptions);
        options.addOption(skolemizeOption);
        options.addOption(simulateOption);
        options.addOption(modularReasoningOption);
        options.addOption(relevancyAnalysisOption);
        options.addOption(scopeRestrictionOption);
        // options.addOption(noVerifyOption)

        String configFileArgument = null;
        Properties overridingProperties = new Properties();
        TacoCustomScope tacoScope = new TacoCustomScope();

        // create the parser
        CommandLineParser parser = new PosixParser();

        try {
            // parse the command line arguments
            CommandLine line = parser.parse(options, args);

            // help
            if (line.hasOption(helpOption.getOpt())) {
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp(120, CMD, HEADER, options, FOOTER, true);
                return;
            }

            // version
            if (line.hasOption(versionOption.getOpt())) {
                System.out.println(FOOTER);
                System.out.println("");
                return;
            }

            // Configuration file
            if (line.hasOption(configFileOption.getOpt())) {
                configFileArgument = line.getOptionValue(configFileOption.getOpt());
            }

            // class to check
            if (line.hasOption(classToCheckOption.getOpt())) {
                overridingProperties.put(TacoConfigurator.CLASS_TO_CHECK_FIELD,
                        line.getOptionValue(classToCheckOption.getOpt()));
            }

            // method to check
            if (line.hasOption(methodToCheckOption.getOpt())) {
                String methodtoCheck = line.getOptionValue(methodToCheckOption.getOpt());

                if (!methodtoCheck.matches("^[A-Za-z0-9_-]+_[0-9]")) {
                    methodtoCheck = methodtoCheck + "_0";
                }
                overridingProperties.put(TacoConfigurator.METHOD_TO_CHECK_FIELD, methodtoCheck);
            }

            // Dependencies classes
            if (line.hasOption(dependenciesOption.getOpt())) {
                String dependenciesClasses = "";
                for (String aDependencyClass : line.getOptionValues(dependenciesOption.getOpt())) {
                    dependenciesClasses += aDependencyClass;
                }
                overridingProperties.put(TacoConfigurator.CLASSES_FIELD, dependenciesClasses);
            }

            // Relevant classes
            if (line.hasOption(relevantClassesOption.getOpt())) {
                String relevantClasses = "";
                for (String aRelevantClass : line.getOptionValues(relevantClassesOption.getOpt())) {
                    relevantClasses += aRelevantClass;
                }
                overridingProperties.put(TacoConfigurator.RELEVANT_CLASSES, relevantClasses);
            }

            // Loop unrolling
            if (line.hasOption(loopsOptions.getOpt())) {
                loopUnrolling = Integer.parseInt(line.getOptionValue(loopsOptions.getOpt()));
            }

            // Int bitwidth
            if (line.hasOption(bitOptions.getOpt())) {
                String alloy_bitwidth_str = line.getOptionValue(bitOptions.getOpt());
                overridingProperties.put(TacoConfigurator.BITWIDTH, alloy_bitwidth_str);
                int alloy_bitwidth = new Integer(alloy_bitwidth_str);
                tacoScope.setAlloyBitwidth(alloy_bitwidth);
            }

            // instances scope
            if (line.hasOption(instOptions.getOpt())) {
                String assertionsArguments = "for " + line.getOptionValue(instOptions.getOpt());
                overridingProperties.put(TacoConfigurator.ASSERTION_ARGUMENTS, assertionsArguments);
            }

            // Skolemize
            if (line.hasOption(skolemizeOption.getOpt())) {
                overridingProperties.put(TacoConfigurator.SKOLEMIZE_INSTANCE_INVARIANT, false);
                overridingProperties.put(TacoConfigurator.SKOLEMIZE_INSTANCE_ABSTRACTION, false);
            }

            // Simulation
            if (line.hasOption(simulateOption.getOpt())) {
                overridingProperties.put(TacoConfigurator.INCLUDE_SIMULATION_PROGRAM_DECLARATION, true);
                overridingProperties.put(TacoConfigurator.GENERATE_CHECK, false);
                overridingProperties.put(TacoConfigurator.GENERATE_RUN, false);
            }

            // Modular Reasoning
            if (line.hasOption(modularReasoningOption.getOpt())) {
                overridingProperties.put(TacoConfigurator.MODULAR_REASONING, true);
            }

            // Relevancy Analysis
            if (line.hasOption(relevancyAnalysisOption.getOpt())) {
                overridingProperties.put(TacoConfigurator.RELEVANCY_ANALYSIS, true);
            }

        } catch (ParseException e) {
            System.err.println("Command line parsing failed: " + e.getMessage());
        }

        try {

            System.out.println("****** Starting Taco (version. " + tacoVersion + ") ****** ");
            System.out.println("");

            File file = new File("config/log4j.xml");
            if (file.exists()) {
                DOMConfigurator.configure("config/log4j.xml");
            } else {
                System.err.println("log4j:WARN File config/log4j.xml not found");
            }

            TacoMain main = new TacoMain();

            // BUILD TacoScope 

            //
            main.run(configFileArgument, overridingProperties);

        } catch (IllegalArgumentException e) {
            System.err.println("Error found:");
            System.err.println(e.getMessage());
        } catch (MethodToCheckNotFoundException e) {
            System.err.println("Error found:");
            System.err.println("Method to check was not found. Please verify config file, or add -m option");
        } catch (TacoException e) {
            System.err.println("Error found:");
            System.err.println(e.getMessage());
        }
    }

    public void run(String configFile) throws IllegalArgumentException {
        this.run(configFile, new Properties());
    }

    /**
     * 
     * @param configFile
     * @param overridingProperties
     *            Properties that overrides properties file's values
     */

    public TacoAnalysisResult run(String configFile, Properties overridingProperties)
            throws IllegalArgumentException {

        AlloyTyping varsEncodingValueOfArithmeticOperationsInObjectInvariants = new AlloyTyping();
        List<AlloyFormula> predsEncodingValueOfArithmeticOperationsInObjectInvariants = new ArrayList<AlloyFormula>();

        if (configFile == null) {
            throw new IllegalArgumentException("Config file not found, please verify option -cf");
        }

        List<JCompilationUnitType> compilation_units = null;
        String classToCheck = null;
        String methodToCheck = null;

        // Start configurator
        JDynAlloyConfig.reset();
        JDynAlloyConfig.buildConfig(configFile, overridingProperties);

        List<JDynAlloyModule> jdynalloy_modules = new ArrayList<JDynAlloyModule>();
        SimpleJmlToJDynAlloyContext simpleJmlToJDynAlloyContext;
        if (TacoConfigurator.getInstance().getBoolean(TacoConfigurator.JMLPARSER_ENABLED,
                TacoConfigurator.JMLPARSER_ENABLED_DEFAULT)) {
            // JAVA PARSING
            String sourceRootDir = TacoConfigurator.getInstance()
                    .getString(TacoConfigurator.JMLPARSER_SOURCE_PATH_STR);

            if (TacoConfigurator.getInstance().getString(TacoConfigurator.CLASS_TO_CHECK_FIELD) == null) {
                throw new TacoException(
                        "Config key 'CLASS_TO_CHECK_FIELD' is mandatory. Please check your config file or add the -c parameter");
            }
            List<String> files = new ArrayList<String>(Arrays.asList(JDynAlloyConfig.getInstance().getClasses()));

            classToCheck = TacoConfigurator.getInstance().getString(TacoConfigurator.CLASS_TO_CHECK_FIELD);
            String[] splitName = classToCheck.split("_");
            classToCheck = "";
            for (int idx = 0; idx < splitName.length - 2; idx++) {
                classToCheck += splitName[idx] + "_";
            }

            if (splitName.length >= 2)
                classToCheck += splitName[splitName.length - 2] + "Instrumented_";
            classToCheck += splitName[splitName.length - 1];

            if (!files.contains(classToCheck)) {
                files.add(classToCheck);
            }

            List<String> processedFileNames = new ArrayList<String>();
            for (String file : files) {
                String begin = file.substring(0, file.lastIndexOf('.'));
                String end = file.substring(file.lastIndexOf('.'), file.length());
                processedFileNames.add(begin + "Instrumented" + end);
            }

            files = processedFileNames;

            JmlParser.getInstance().initialize(sourceRootDir,
                    System.getProperty("user.dir") + System.getProperty("file.separator") + "bin" /* Unused */,
                    files);
            compilation_units = JmlParser.getInstance().getCompilationUnits();
            // END JAVA PARSING

            // SIMPLIFICATION
            JmlStage aJavaCodeSimplifier = new JmlStage(compilation_units);
            aJavaCodeSimplifier.execute();
            JmlToSimpleJmlContext jmlToSimpleJmlContext = aJavaCodeSimplifier.getJmlToSimpleJmlContext();
            List<JCompilationUnitType> simplified_compilation_units = aJavaCodeSimplifier
                    .get_simplified_compilation_units();
            // END SIMPLIFICATION

            // JAVA TO JDYNALLOY TRANSLATION
            SimpleJmlStage aJavaToDynJAlloyTranslator = new SimpleJmlStage(simplified_compilation_units);
            aJavaToDynJAlloyTranslator.execute();
            // END JAVA TO JDYNALLOY TRANSLATION
            simpleJmlToJDynAlloyContext = aJavaToDynJAlloyTranslator.getSimpleJmlToJDynAlloyContext();
            varsEncodingValueOfArithmeticOperationsInObjectInvariants = aJavaToDynJAlloyTranslator
                    .getVarsEncodingValueOfArithmeticOperationsInInvariants();
            predsEncodingValueOfArithmeticOperationsInObjectInvariants = aJavaToDynJAlloyTranslator
                    .getPredsEncodingValueOfArithmeticOperationsInInvariants();

            // JFSL TO JDYNALLOY TRANSLATION
            JfslStage aJfslToDynJAlloyTranslator = new JfslStage(simplified_compilation_units,
                    aJavaToDynJAlloyTranslator.getModules(), jmlToSimpleJmlContext, simpleJmlToJDynAlloyContext);
            aJfslToDynJAlloyTranslator.execute();
            /**/ aJfslToDynJAlloyTranslator = null;
            // END JFSL TO JDYNALLOY TRANSLATION

            // PRINT JDYNALLOY
            JDynAlloyPrinterStage printerStage = new JDynAlloyPrinterStage(aJavaToDynJAlloyTranslator.getModules());
            printerStage.execute();
            /**/ printerStage = null;
            // END PRINT JDYNALLOY

            jdynalloy_modules.addAll(aJavaToDynJAlloyTranslator.getModules());

        } else {
            simpleJmlToJDynAlloyContext = null;
        }

        // JDYNALLOY BUILT-IN MODULES
        PrecompiledModules precompiledModules = new PrecompiledModules();
        precompiledModules.execute();
        jdynalloy_modules.addAll(precompiledModules.getModules());
        // END JDYNALLOY BUILT-IN MODULES

        // JDYNALLOY STATIC FIELDS CLASS
        JDynAlloyModule staticFieldsModule = precompiledModules.generateStaticFieldsModule();
        jdynalloy_modules.add(staticFieldsModule);
        /**/ staticFieldsModule = null;
        // END JDYNALLOY STATIC FIELDS CLASS

        // JDYNALLOY PARSING
        if (TacoConfigurator.getInstance().getBoolean(TacoConfigurator.JDYNALLOY_PARSER_ENABLED,
                TacoConfigurator.JDYNALLOY_PARSER_ENABLED_DEFAULT)) {
            log.info("****** START: Parsing JDynAlloy files ****** ");
            JDynAlloyParsingStage jDynAlloyParser = new JDynAlloyParsingStage(jdynalloy_modules);
            jDynAlloyParser.execute();
            jdynalloy_modules.addAll(jDynAlloyParser.getParsedModules());
            /**/ jDynAlloyParser = null;
            log.info("****** END: Parsing JDynAlloy files ****** ");
        } else {
            log.info(
                    "****** INFO: Parsing JDynAlloy is disabled (hint enablet it using 'jdynalloy.parser.enabled') ****** ");
        }
        // END JDYNALLOY PARSING

        // JDYNALLOY TO DYNALLOY TRANSLATION
        JDynAlloyStage dynJAlloyToDynAlloyTranslator = new JDynAlloyStage(jdynalloy_modules);
        /**/ jdynalloy_modules = null;
        dynJAlloyToDynAlloyTranslator.execute();
        // BEGIN JDYNALLOY TO DYNALLOY TRANSLATION

        AlloyAnalysisResult alloy_analysis_result = null;
        DynalloyStage dynalloyToAlloy = null;

        // DYNALLOY TO ALLOY TRANSLATION
        if (TacoConfigurator.getInstance().getBoolean(TacoConfigurator.DYNALLOY_TO_ALLOY_ENABLE)) {

            dynalloyToAlloy = new DynalloyStage(dynJAlloyToDynAlloyTranslator.getOutputFileNames());
            dynalloyToAlloy.setSourceJDynAlloy(dynJAlloyToDynAlloyTranslator.getPrunedModules());
            /**/ dynJAlloyToDynAlloyTranslator = null;
            dynalloyToAlloy.execute();
            // DYNALLOY TO ALLOY TRANSLATION

            log.info("****** Transformation process finished ****** ");

            if (TacoConfigurator.getInstance().getNoVerify() == false) {
                // Starts dynalloy to alloy tranlation and alloy verification

                AlloyStage alloy_stage = new AlloyStage(dynalloyToAlloy.get_alloy_filename());
                /**/ dynalloyToAlloy = null;

                alloy_stage.execute();

                alloy_analysis_result = alloy_stage.get_analysis_result();
                /**/ alloy_stage = null;
            }
        }

        TacoAnalysisResult tacoAnalysisResult = new TacoAnalysisResult(alloy_analysis_result);

        String junitFile = null;

        if (TacoConfigurator.getInstance().getGenerateUnitTestCase()
                || TacoConfigurator.getInstance().getAttemptToCorrectBug()) {
            // Begin JUNIT Generation Stage
            methodToCheck = overridingProperties.getProperty(TacoConfigurator.METHOD_TO_CHECK_FIELD);

            SnapshotStage snapshotStage = new SnapshotStage(compilation_units, tacoAnalysisResult, classToCheck,
                    methodToCheck);
            snapshotStage.execute();

            RecoveredInformation recoveredInformation = snapshotStage.getRecoveredInformation();
            recoveredInformation.setFileNameSuffix(StrykerStage.fileSuffix);
            JUnitStage jUnitStage = new JUnitStage(recoveredInformation);
            jUnitStage.execute();
            junitFile = jUnitStage.getJunitFileName();
            //         StrykerStage.fileSuffix++;
            // End JUNIT Generation Stage
        } else {
            log.info("****** JUnit with counterexample values will not be generated. ******* ");
            if (!TacoConfigurator.getInstance().getGenerateUnitTestCase()) {
                log.info("****** generateUnitTestCase=false ******* ");
            }

        }

        if (TacoConfigurator.getInstance().getBuildJavaTrace()) {
            if (tacoAnalysisResult.get_alloy_analysis_result().isSAT()) {
                log.info("****** START: Java Trace Generation ****** ");
                DynAlloyCompiler compiler = dynalloyToAlloy.getDynAlloyCompiler();
                JavaTraceStage javaTraceStage = new JavaTraceStage(compiler.getSpecContext(), alloy_analysis_result,
                        false);
                javaTraceStage.execute();
                //            DynAlloySolution dynAlloySolution = javaTraceStage.getDynAlloySolution();
                //            List<TraceStep> trace = dynAlloySolution.getTrace();

                log.info("****** FINISH: Java Trace Generation ****** ");
            }
        } else {
            log.info("****** Java Trace will not be generated. ******* ");
            log.info("****** generateJavaTrace=false ******* ");
        }

        if (TacoConfigurator.getInstance().getAttemptToCorrectBug()) {
            if (tacoAnalysisResult.get_alloy_analysis_result().isSAT() && tacoAnalysisResult
                    .get_alloy_analysis_result().getAlloy_solution().getOriginalCommand().startsWith("Check")) {
                log.info("****** START: Stryker ****** ");
                methodToCheck = overridingProperties.getProperty(TacoConfigurator.METHOD_TO_CHECK_FIELD);
                String sourceRootDir = TacoConfigurator.getInstance()
                        .getString(TacoConfigurator.JMLPARSER_SOURCE_PATH_STR);
                StrykerStage strykerStage = new StrykerStage(compilation_units, sourceRootDir, classToCheck,
                        methodToCheck, configFile, overridingProperties,
                        TacoConfigurator.getInstance().getMaxStrykerMethodsForFile());
                StrykerStage.junitInputs = new Class<?>[50];

                try {
                    String currentJunit = null;

                    String tempFilename = junitFile.substring(0,
                            junitFile.lastIndexOf(FILE_SEP) + 1) /*+ FILE_SEP*/;
                    String packageToWrite = "ar.edu.output.junit";
                    String fileClasspath = tempFilename.substring(0, tempFilename
                            .lastIndexOf(new String("ar.edu.generated.junit").replaceAll("\\.", FILE_SEP)));
                    fileClasspath = fileClasspath.replaceFirst("generated", "output");
                    //               String currentClasspath = System.getProperty("java.class.path")+PATH_SEP+fileClasspath/*+PATH_SEP+System.getProperty("user.dir")+FILE_SEP+"generated"*/;
                    currentJunit = editTestFileToCompile(junitFile, classToCheck, packageToWrite, methodToCheck);

                    File[] file1 = new File[] { new File(currentJunit) };
                    JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
                    StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);
                    Iterable<? extends JavaFileObject> compilationUnit1 = fileManager
                            .getJavaFileObjectsFromFiles(Arrays.asList(file1));
                    javaCompiler.getTask(null, fileManager, null, null, null, compilationUnit1).call();
                    fileManager.close();
                    javaCompiler = null;
                    file1 = null;
                    fileManager = null;

                    ///*mfrias*/      int compilationResult =   javaCompiler.run(null, null, null /*new NullOutputStream()*/, new String[]{"-classpath", currentClasspath, currentJunit});
                    ///**/            javaCompiler = null;
                    //               if(compilationResult == 0) {
                    log.warn("junit counterexample compilation succeded");
                    ClassLoader cl = ClassLoader.getSystemClassLoader();
                    @SuppressWarnings("resource")
                    ClassLoader cl2 = new URLClassLoader(new URL[] { new File(fileClasspath).toURI().toURL() }, cl);
                    //                  ClassLoaderTools.addFile(fileClasspath);
                    Class<?> clazz = cl2.loadClass(packageToWrite + "." + obtainClassNameFromFileName(junitFile));
                    //                  Method[] meth = clazz.getMethods();
                    //                  log.info("preparing to add a class containing a test input to the pool... "+packageToWrite+"."+MuJavaController.obtainClassNameFromFileName(junitFile));
                    //                  Result result = null;
                    //                  final Object oToRun = clazz.newInstance();
                    StrykerStage.junitInputs[StrykerStage.indexToLastJUnitInput] = clazz;
                    StrykerStage.indexToLastJUnitInput++;
                    cl = null;
                    cl2 = null;

                    //               
                    //               } else {
                    //                  log.warn("compilation failed");
                    //               }
                    //                     File originalFile = new File(tempFilename);
                    //                     originalFile.delete();

                } catch (ClassNotFoundException e) {
                    //                     e.printStackTrace();
                } catch (IOException e) {
                    //                     e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    //                     e.printStackTrace();
                } catch (Exception e) {
                    //                     e.printStackTrace();
                }

                strykerStage.execute();

                log.info("****** FINISH: Stryker ****** ");
            }
        } else {
            log.info("****** BugFix will not be generated. ******* ");
            log.info("****** attemptToCorrectBug=false ******* ");
        }

        return tacoAnalysisResult;
    }

    /**
     * 
     */
    private static String getManifestAttribute(Name name) {
        String manifestAttributeValue = "Undefined";
        try {

            String jarFileName = System.getProperty("java.class.path")
                    .split(System.getProperty("path.separator"))[0];
            JarFile jar = new JarFile(jarFileName);
            Manifest manifest = jar.getManifest();

            Attributes mainAttributes = manifest.getMainAttributes();
            manifestAttributeValue = mainAttributes.getValue(name);
            jar.close();
        } catch (IOException e) {
        }

        return manifestAttributeValue;
    }

    public static String editTestFileToCompile(String junitFile, String sourceClassName, String classPackage,
            String methodName) {
        String tmpDir = junitFile.substring(0, junitFile.lastIndexOf(FILE_SEP));
        tmpDir = tmpDir.replaceAll("generated", "output");
        File destFile = new File(tmpDir, obtainClassNameFromFileName(junitFile) + /*"_temp" +*/ ".java");
        String packageSentence = "package " + classPackage + ";\n";
        int posLastUnderscore = methodName.lastIndexOf("_");
        methodName = methodName.substring(0, posLastUnderscore);
        try {
            destFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(destFile);
            boolean packageAlreadyWritten = false;
            Scanner scan = new Scanner(new File(junitFile));
            scan.useDelimiter("\n");
            boolean nextToTest = false;
            String str = null;
            while (scan.hasNext()) {
                str = scan.next();
                if (nextToTest) {
                    str = str.replace("()",
                            "(String fileClasspath, String className, String methodName) throws IllegalAccessException, InvocationTargetException, ClassNotFoundException, InstantiationException, MalformedURLException");
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    nextToTest = false;
                    //            } else if (str.contains("public class")){
                    //               int posOpeningBrace = str.indexOf("{");
                    //               str = str.substring(0, posOpeningBrace-1);
                    //               str = str + "_temp {";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.contains("package") && !packageAlreadyWritten) {
                    fos.write(packageSentence.getBytes(Charset.forName("UTF-8")));
                    str = "           import java.net.URL;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           import java.net.URLClassLoader;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           import java.net.MalformedURLException;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           import java.io.File;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           import java.lang.reflect.InvocationTargetException;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    packageAlreadyWritten = true;
                } else if (str.contains("import") && !packageAlreadyWritten) {
                    fos.write(packageSentence.getBytes(Charset.forName("UTF-8")));
                    fos.write((scan.next() + "\n").getBytes(Charset.forName("UTF-8")));
                    packageAlreadyWritten = true;
                } else if (str.contains("new " + sourceClassName + "(")) {
                    //               str = "        try {";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           ClassLoader cl = ClassLoader.getSystemClassLoader();";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           ClassLoader cl2 = new URLClassLoader(new URL[]{new File(fileClasspath).toURI().toURL()}, cl);";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    //               str = "           ClassLoaderTools.addFile(fileClasspath);";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           Class<?> clazz = cl2.loadClass(className);";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           Object instance = clazz.newInstance();";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           cl2 = null;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));

                } else if (str.contains("Class<?> clazz;")) {
                } else if (str.contains("} catch (ClassNotFoundException e) {")) {
                    str = str.replace("ClassNotFoundException", "Exception");
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.matches(".*(?i)[\\.a-z0-9\\_]*" + sourceClassName + "(?=[^a-z0-9\\_\\.]).*")) {
                    str = str.replaceAll("(?i)[\\.a-z0-9\\_]*" + sourceClassName + "(?=[^a-z0-9\\_\\.])",
                            /*classPackage+"."+*/sourceClassName);
                    str = str.replace("\"" + methodName + "\"", "methodName");
                    str = str.replace("\"" + sourceClassName + "\"", "clazz");
                    //               str = str.replace("(", "(fileClasspath, ");
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.contains("e.printStackTrace();")) {
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    fos.write(("           throw(new java.lang.RuntimeException(e));" + "\n")
                            .getBytes(Charset.forName("UTF-8")));
                    //               fos.write(("throw e;" + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.contains("private Method getAccessibleMethod")) {
                    str = str.replace("(String className, ", "(Class<?> clazz, ");
                    //               str = str.replace(") {", ") throws MalformedURLException {");
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.contains("method.invoke(instance,")) {
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           instance = null;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    str = "           method = null;";
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));

                } else if (str.contains("methodToCheck = clazz.getDeclaredMethod(methodName, parameterTypes);")) {
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else if (str.contains("clazz = Class.forName(className);")) {
                    //               str = "           ClassLoader cl = ClassLoader.getSystemClassLoader();";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    //               str = "           final ClassLoader cl2 = new URLClassLoader(new URL[]{new File(fileClasspath).toURI().toURL()}, cl);";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    //               str = "           clazz = cl2.loadClass(className);";               
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                    //               str = "           System.out.println(\"actual class inside method: \"+clazz.getName());";
                    //               fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                } else {
                    if (str.contains("@Test")) {
                        nextToTest = true;
                    }
                    //               if (!scan.hasNext()){
                    //                  String s = "        } catch (ClassNotFoundException e){";
                    //                  fos.write((s + "\n").getBytes(Charset.forName("UTF-8")));
                    //                  s = "        } catch (InstantiationException e){}";
                    //                  fos.write((s + "\n").getBytes(Charset.forName("UTF-8")));
                    //               }
                    fos.write((str + "\n").getBytes(Charset.forName("UTF-8")));
                }
            }
            fos.close();
            scan.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return destFile.toString();

    }

    private static final int NOT_PRESENT = -1;

    public static String obtainClassNameFromFileName(String fileName) {
        int lastBackslash = fileName.lastIndexOf("/");
        int lastDot = fileName.lastIndexOf(".");

        if (lastBackslash == NOT_PRESENT) {
            lastBackslash = 0;
        } else {
            lastBackslash += 1;
        }
        if (lastDot == NOT_PRESENT) {
            lastDot = fileName.length();
        }

        return fileName.substring(lastBackslash, lastDot);
    }

}