edu.ksu.cis.indus.staticanalyses.dependency.DependencyXMLizerCLI.java Source code

Java tutorial

Introduction

Here is the source code for edu.ksu.cis.indus.staticanalyses.dependency.DependencyXMLizerCLI.java

Source

/*******************************************************************************
 * Indus, a program analysis and transformation toolkit for Java.
 * Copyright (c) 2001, 2007 Venkatesh Prasad Ranganath
 * 
 * All rights reserved.  This program and the accompanying materials are made 
 * available under the terms of the Eclipse Public License v1.0 which accompanies 
 * the distribution containing this program, and is available at 
 * http://www.opensource.org/licenses/eclipse-1.0.php.
 * 
 * For questions about the license, copyright, and software, contact 
 *    Venkatesh Prasad Ranganath at venkateshprasad.ranganath@gmail.com
 *                                 
 * This software was developed by Venkatesh Prasad Ranganath in SAnToS Laboratory 
 * at Kansas State University.
 *******************************************************************************/

package edu.ksu.cis.indus.staticanalyses.dependency;

import edu.ksu.cis.indus.common.collections.MapUtils;
import edu.ksu.cis.indus.common.collections.SetUtils;
import edu.ksu.cis.indus.common.datastructures.Pair.PairManager;
import edu.ksu.cis.indus.common.soot.BasicBlockGraphMgr;
import edu.ksu.cis.indus.common.soot.IStmtGraphFactory;
import edu.ksu.cis.indus.common.soot.MetricsProcessor;
import edu.ksu.cis.indus.common.soot.SootBasedDriver;
import edu.ksu.cis.indus.interfaces.ICallGraphInfo;
import edu.ksu.cis.indus.interfaces.IEnvironment;
import edu.ksu.cis.indus.interfaces.IEscapeInfo;
import edu.ksu.cis.indus.interfaces.IExceptionRaisingInfo;
import edu.ksu.cis.indus.interfaces.IMonitorInfo;
import edu.ksu.cis.indus.interfaces.IThreadGraphInfo;
import edu.ksu.cis.indus.interfaces.IUseDefInfo;
import edu.ksu.cis.indus.processing.IProcessor;
import edu.ksu.cis.indus.processing.OneAllStmtSequenceRetriever;
import edu.ksu.cis.indus.processing.ProcessingController;
import edu.ksu.cis.indus.processing.TagBasedProcessingFilter;
import edu.ksu.cis.indus.staticanalyses.callgraphs.CGBasedXMLizingProcessingFilter;
import edu.ksu.cis.indus.staticanalyses.callgraphs.CallGraphInfo;
import edu.ksu.cis.indus.staticanalyses.callgraphs.OFABasedCallInfoCollector;
import edu.ksu.cis.indus.staticanalyses.cfg.CFGAnalysis;
import edu.ksu.cis.indus.staticanalyses.cfg.ExceptionRaisingAnalysis;
import edu.ksu.cis.indus.staticanalyses.cfg.StaticFieldUseDefInfo;
import edu.ksu.cis.indus.staticanalyses.concurrency.MonitorAnalysis;
import edu.ksu.cis.indus.staticanalyses.concurrency.SafeLockAnalysis;
import edu.ksu.cis.indus.staticanalyses.concurrency.escape.EquivalenceClassBasedEscapeAnalysis;
import edu.ksu.cis.indus.staticanalyses.dependency.IDependencyAnalysis.DependenceSort;
import edu.ksu.cis.indus.staticanalyses.flow.instances.ofa.OFAnalyzer;
import edu.ksu.cis.indus.staticanalyses.flow.processors.AliasedUseDefInfo;
import edu.ksu.cis.indus.staticanalyses.flow.processors.AliasedUseDefInfov2;
import edu.ksu.cis.indus.staticanalyses.flow.processors.ThreadGraph;
import edu.ksu.cis.indus.staticanalyses.interfaces.IValueAnalyzer;
import edu.ksu.cis.indus.staticanalyses.processing.AnalysesController;
import edu.ksu.cis.indus.staticanalyses.processing.CGBasedProcessingFilter;
import edu.ksu.cis.indus.staticanalyses.processing.ValueAnalyzerBasedProcessingController;
import edu.ksu.cis.indus.staticanalyses.tokens.ITokens;
import edu.ksu.cis.indus.staticanalyses.tokens.TokenUtil;
import edu.ksu.cis.indus.staticanalyses.tokens.soot.SootValueTypeManager;
import edu.ksu.cis.indus.xmlizer.UniqueJimpleIDGenerator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import soot.Type;
import soot.Value;

/**
 * This class provides a command-line interface to xmlize dependence information. Refer to <code>SootBasedDriver</code> for
 * more configuration infomration.
 * 
 * @author <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
 * @author $Author: rvprasad $
 * @version $Revision: 1.90 $ $Date: 2007/03/08 16:32:18 $
 */
public class DependencyXMLizerCLI extends SootBasedDriver {

    /**
     * The logger used by instances of this class to log messages.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DependencyXMLizerCLI.class);

    /**
     * This is the flow analyser used by the analyses being tested.
     */
    protected IValueAnalyzer<Value> aa;

    /**
     * A collection of dependence analyses.
     */
    protected List<IDependencyAnalysis> das = new ArrayList<IDependencyAnalysis>();

    /**
     * This is a map from interface IDs to interface implementations that are required by the analyses being driven.
     * 
     * @invariant info.oclIsKindOf(Map(String, Object))
     */
    protected final Map info = new HashMap();

    /**
     * This indicates if common unchecked exceptions should be considered.
     */
    private boolean commonUncheckedException;

    /**
     * This flag indicates if jimple should be dumped.
     */
    private boolean dumpJimple;

    /**
     * This indicates if exceptional exits should be considered.
     */
    private boolean exceptionalExits;

    /**
     * This flag indicates if the simple version of aliased use-def information should be used.
     */
    private boolean useAliasedUseDefv1;

    /**
     * This indicates if safe lock should be used.
     */
    private boolean useSafeLockAnalysis;

    /**
     * The xmlizer used to xmlize dependence information.
     */
    private final DependencyXMLizer xmlizer = new DependencyXMLizer();

    /**
     * This is the entry point via command-line.
     * 
     * @param args is the command line arguments.
     * @throws RuntimeException when an Throwable exception beyond our control occurs.
     * @pre args != null
     */
    public static void main(final String[] args) {
        final Options _options = new Options();
        Option _option = new Option("o", "output", true,
                "Directory into which xml files will be written into.  Defaults to current directory if omitted");
        _option.setArgs(1);
        _option.setArgName("output-directory");
        _options.addOption(_option);
        _option = new Option("j", "jimple", false, "Dump xmlized jimple.");
        _options.addOption(_option);

        final DivergenceDA _fidda = DivergenceDA.getDivergenceDA(IDependencyAnalysis.Direction.FORWARD_DIRECTION);
        _fidda.setConsiderCallSites(true);

        final DivergenceDA _bidda = DivergenceDA.getDivergenceDA(IDependencyAnalysis.Direction.BACKWARD_DIRECTION);
        _bidda.setConsiderCallSites(true);

        final NonTerminationSensitiveEntryControlDA _ncda = new NonTerminationSensitiveEntryControlDA();
        final Object[][] _dasOptions = {
                { "ibdda1", "Identifier based data dependence (Soot)", new IdentifierBasedDataDA() },
                { "ibdda2", "Identifier based data dependence (Indus)", new IdentifierBasedDataDAv2() },
                { "ibdda3", "Identifier based data dependence (Indus Optimized)", new IdentifierBasedDataDAv3() },
                { "rbdda", "Reference based data dependence", new ReferenceBasedDataDA() },
                { "nscda", "Non-termination sensitive Entry control dependence", _ncda },
                { "nicda", "Non-termination insensitive Entry control dependence",
                        new NonTerminationInsensitiveEntryControlDA(), },
                { "xcda", "Exit control dependence", new ExitControlDA() },
                { "sda", "Synchronization dependence", new SynchronizationDA() },
                { "frda1", "Forward Ready dependence v1", ReadyDAv1.getForwardReadyDA() },
                { "brda1", "Backward Ready dependence v1", ReadyDAv1.getBackwardReadyDA() },
                { "frda2", "Forward Ready dependence v2", ReadyDAv2.getForwardReadyDA() },
                { "brda2", "Backward Ready dependence v2", ReadyDAv2.getBackwardReadyDA() },
                { "frda3", "Forward Ready dependence v3", ReadyDAv3.getForwardReadyDA() },
                { "brda3", "Backward Ready dependence v3", ReadyDAv3.getBackwardReadyDA() },
                { "ida1", "Interference dependence v1", new InterferenceDAv1() },
                { "ida2", "Interference dependence v2", new InterferenceDAv2() },
                { "ida3", "Interference dependence v3", new InterferenceDAv3() },
                { "fdda", "Forward Intraprocedural Divergence dependence",
                        DivergenceDA.getDivergenceDA(IDependencyAnalysis.Direction.FORWARD_DIRECTION), },
                { "bdda", "Backward Intraprocedural Divergence dependence",
                        DivergenceDA.getDivergenceDA(IDependencyAnalysis.Direction.BACKWARD_DIRECTION), },
                { "fidda", "Forward Intra+Interprocedural Divergence dependence", _fidda },
                { "bidda", "Backward Intra+Interprocedural Divergence dependence", _bidda },
                { "fpidda", "Forward Interprocedural Divergence dependence",
                        InterProceduralDivergenceDA
                                .getDivergenceDA(IDependencyAnalysis.Direction.FORWARD_DIRECTION), },
                { "bpidda", "Backward Interprocedural Divergence dependence", InterProceduralDivergenceDA
                        .getDivergenceDA(IDependencyAnalysis.Direction.BACKWARD_DIRECTION), }, };
        _option = new Option("h", "help", false, "Display message.");
        _option.setOptionalArg(false);
        _options.addOption(_option);
        _option = new Option("p", "soot-classpath", false, "Prepend this to soot class path.");
        _option.setArgs(1);
        _option.setArgName("classpath");
        _option.setOptionalArg(false);
        _options.addOption(_option);
        _option = new Option("aliasedusedefv1", false, "Use version 1 of aliased use-def info.");
        _options.addOption(_option);
        _option = new Option("safelockanalysis", false, "Use safe-lock-analysis for ready dependence.");
        _options.addOption(_option);
        _option = new Option("ofaforinterference", false, "Use OFA for interference dependence.");
        _options.addOption(_option);
        _option = new Option("ofaforready", false, "Use OFA for ready dependence.");
        _options.addOption(_option);
        _option = new Option("exceptionalexits", false, "Consider exceptional exits for control dependence.");
        _options.addOption(_option);
        _option = new Option("commonuncheckedexceptions", false, "Consider common unchecked exceptions.");
        _options.addOption(_option);
        _option = new Option("S", "scope", true, "The scope that should be analyzed.");
        _option.setArgs(1);
        _option.setArgName("scope");
        _option.setRequired(false);
        _options.addOption(_option);

        for (int _i = 0; _i < _dasOptions.length; _i++) {
            final String _shortOption = _dasOptions[_i][0].toString();
            final String _description = _dasOptions[_i][1].toString();
            _option = new Option(_shortOption, false, _description);
            _options.addOption(_option);
        }

        final CommandLineParser _parser = new GnuParser();

        try {
            final CommandLine _cl = _parser.parse(_options, args);

            if (_cl.hasOption("h")) {
                printUsage(_options);
                System.exit(1);
            }

            final DependencyXMLizerCLI _xmlizerCLI = new DependencyXMLizerCLI();
            String _outputDir = _cl.getOptionValue('o');

            if (_outputDir == null) {
                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn("Defaulting to current directory for output.");
                }
                _outputDir = ".";
            }

            _xmlizerCLI.xmlizer.setXmlOutputDir(_outputDir);

            if (_cl.hasOption('p')) {
                _xmlizerCLI.addToSootClassPath(_cl.getOptionValue('p'));
            }

            if (_cl.hasOption('S')) {
                _xmlizerCLI.setScopeSpecFile(_cl.getOptionValue('S'));
            }

            _xmlizerCLI.dumpJimple = _cl.hasOption('j');
            _xmlizerCLI.useAliasedUseDefv1 = _cl.hasOption("aliasedusedefv1");
            _xmlizerCLI.useSafeLockAnalysis = _cl.hasOption("safelockanalysis");
            _xmlizerCLI.exceptionalExits = _cl.hasOption("exceptionalexits");
            _xmlizerCLI.commonUncheckedException = _cl.hasOption("commonuncheckedexceptions");

            final List<String> _classNames = _cl.getArgList();

            if (_classNames.isEmpty()) {
                throw new MissingArgumentException("Please specify atleast one class.");
            }
            _xmlizerCLI.setClassNames(_classNames);

            final int _exitControlDAIndex = 6;

            if (_cl.hasOption(_dasOptions[_exitControlDAIndex][0].toString())) {
                _xmlizerCLI.das.add(_ncda);

                for (final Iterator<DependenceSort> _i = _ncda.getIds().iterator(); _i.hasNext();) {
                    final DependenceSort _id = _i.next();
                    MapUtils.putIntoCollectionInMapUsingFactory(_xmlizerCLI.info, _id, _ncda,
                            SetUtils.getFactory());
                }
            }

            if (!parseForDependenceOptions(_dasOptions, _cl, _xmlizerCLI)) {
                throw new ParseException("Atleast one dependence analysis must be requested.");
            }

            _xmlizerCLI.<ITokens>execute();
        } catch (final ParseException _e) {
            LOGGER.error("Error while parsing command line.", _e);
            System.out.println("Error while parsing command line." + _e);
            printUsage(_options);
        } catch (final Throwable _e) {
            LOGGER.error("Beyond our control. May day! May day!", _e);
            throw new RuntimeException(_e);
        }
    }

    /**
     * Parses command line for dependence analysis options.
     * 
     * @param dependenceOptions supported by this CLI.
     * @param cmdLine provided by the user.
     * @param xmlizerCLI that will be influenced by the provided dependence analysis options.
     * @return <code>false</code> if no dependence options were parsed; <code>true</code>, otherwise.
     */
    private static boolean parseForDependenceOptions(final Object[][] dependenceOptions, final CommandLine cmdLine,
            final DependencyXMLizerCLI xmlizerCLI) {
        boolean _flag = false;

        for (int _i = 0; _i < dependenceOptions.length; _i++) {
            if (cmdLine.hasOption(dependenceOptions[_i][0].toString())) {
                final IDependencyAnalysis _da = (IDependencyAnalysis) dependenceOptions[_i][2];
                xmlizerCLI.das.add(_da);
                _flag = true;

                if (_da instanceof InterferenceDAv1) {
                    ((InterferenceDAv1) _da).setUseOFA(cmdLine.hasOption("ofaforinterference"));
                }

                if (_da instanceof ReadyDAv1) {
                    ((ReadyDAv1) _da).setUseOFA(cmdLine.hasOption("ofaforready"));
                    ((ReadyDAv1) _da).setUseSafeLockAnalysis(xmlizerCLI.useSafeLockAnalysis);
                }
            }
        }
        return _flag;
    }

    /**
     * Prints the help/usage info for this class.
     * 
     * @param options is the command line option.
     * @pre options != null
     */
    private static void printUsage(final Options options) {
        final String _cmdLineSyn = "java " + DependencyXMLizerCLI.class.getName() + " <options> <classnames>";
        (new HelpFormatter()).printHelp(_cmdLineSyn, "Options are: ", options, "");
    }

    /**
     * Drives the analyses.
     * 
     * @param <T> dummy type parameter.
     */
    private <T extends ITokens<T, Value>> void execute() {
        setInfoLogger(LOGGER);

        final String _tagName = "DependencyXMLizer:FA";
        aa = OFAnalyzer.getFSOSAnalyzer(_tagName,
                TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());

        final ValueAnalyzerBasedProcessingController _pc = new ValueAnalyzerBasedProcessingController();
        final Collection<IProcessor> _processors = new ArrayList<IProcessor>();
        final PairManager _pairManager = new PairManager(false, true);
        final CallGraphInfo _cgi = new CallGraphInfo(new PairManager(false, true));
        final IThreadGraphInfo _tgi = new ThreadGraph(_cgi, new CFGAnalysis(_cgi, getBbm()), _pairManager);
        final IExceptionRaisingInfo _eti = new ExceptionRaisingAnalysis(getStmtGraphFactory(), _cgi,
                aa.getEnvironment());
        final ProcessingController _xmlcgipc = new ProcessingController();
        final ValueAnalyzerBasedProcessingController _cgipc = new ValueAnalyzerBasedProcessingController();
        final MetricsProcessor _countingProcessor = new MetricsProcessor();
        final OFABasedCallInfoCollector _callGraphInfoCollector = new OFABasedCallInfoCollector();
        final OneAllStmtSequenceRetriever _ssr = new OneAllStmtSequenceRetriever();
        _ssr.setStmtGraphFactory(getStmtGraphFactory());
        _pc.setStmtSequencesRetriever(_ssr);
        _pc.setAnalyzer(aa);
        _pc.setProcessingFilter(new TagBasedProcessingFilter(_tagName));

        _cgipc.setAnalyzer(aa);
        _cgipc.setProcessingFilter(new CGBasedProcessingFilter(_cgi));
        _cgipc.setStmtSequencesRetriever(_ssr);

        _xmlcgipc.setEnvironment(aa.getEnvironment());
        _xmlcgipc.setProcessingFilter(new CGBasedXMLizingProcessingFilter(_cgi));
        _xmlcgipc.setStmtSequencesRetriever(_ssr);

        final StaticFieldUseDefInfo _staticFieldUD = new StaticFieldUseDefInfo();
        final AliasedUseDefInfo _aliasUD;

        if (useAliasedUseDefv1) {
            _aliasUD = new AliasedUseDefInfo(aa, bbm, _pairManager, new CFGAnalysis(_cgi, bbm));
        } else {
            _aliasUD = new AliasedUseDefInfov2(aa, _cgi, _tgi, bbm, _pairManager);
        }
        info.put(ICallGraphInfo.ID, _cgi);
        info.put(IThreadGraphInfo.ID, _tgi);
        info.put(PairManager.ID, _pairManager);
        info.put(IEnvironment.ID, aa.getEnvironment());
        info.put(IValueAnalyzer.ID, aa);
        info.put(IUseDefInfo.ALIASED_USE_DEF_ID, _aliasUD);
        info.put(IUseDefInfo.GLOBAL_USE_DEF_ID, _staticFieldUD);
        info.put(IStmtGraphFactory.ID, getStmtGraphFactory());

        final EquivalenceClassBasedEscapeAnalysis _ecba = new EquivalenceClassBasedEscapeAnalysis(_cgi, _tgi,
                getBbm());
        info.put(IEscapeInfo.ID, _ecba.getEscapeInfo());

        final IMonitorInfo _monitorInfo = new MonitorAnalysis();
        info.put(IMonitorInfo.ID, _monitorInfo);

        final SafeLockAnalysis _sla;

        if (useSafeLockAnalysis) {
            _sla = new SafeLockAnalysis();
            info.put(SafeLockAnalysis.ID, _sla);
        } else {
            _sla = null;
        }

        initialize();
        aa.analyze(getEnvironment(), getRootMethods());

        _callGraphInfoCollector.reset();
        _processors.clear();
        _processors.add(_callGraphInfoCollector);
        _pc.reset();
        _pc.driveProcessors(_processors);
        _cgi.createCallGraphInfo(_callGraphInfoCollector.getCallInfo());
        writeInfo("CALL GRAPH:\n" + _cgi.toString());

        if (commonUncheckedException) {
            final ExceptionRaisingAnalysis _t = (ExceptionRaisingAnalysis) _eti;
            _t.setupForCommonUncheckedExceptions();
        }

        _processors.clear();
        ((ThreadGraph) _tgi).reset();
        _processors.add((IProcessor) _tgi);
        _processors.add((IProcessor) _eti);
        _processors.add(_countingProcessor);
        _cgipc.reset();
        _cgipc.driveProcessors(_processors);
        writeInfo("THREAD GRAPH:\n" + ((ThreadGraph) _tgi).toString());
        writeInfo("EXCEPTION THROW INFO:\n" + ((ExceptionRaisingAnalysis) _eti).toString());
        writeInfo("STATISTICS: " + MapUtils.verbosePrint(new TreeMap(_countingProcessor.getStatistics())));

        _aliasUD.hookup(_cgipc);
        _staticFieldUD.hookup(_cgipc);
        _cgipc.process();
        _staticFieldUD.unhook(_cgipc);
        _aliasUD.unhook(_cgipc);

        writeInfo("BEGIN: dependency analyses");

        if (exceptionalExits) {
            bbm = new BasicBlockGraphMgr(_eti);
            bbm.setStmtGraphFactory(getStmtGraphFactory());
        }

        final AnalysesController _ac = new AnalysesController(info, _cgipc, getBbm());
        _ac.addAnalyses(IMonitorInfo.ID, Collections.singleton((MonitorAnalysis) _monitorInfo));
        _ac.addAnalyses(EquivalenceClassBasedEscapeAnalysis.ID, Collections.singleton(_ecba));

        if (useSafeLockAnalysis) {
            _ac.addAnalyses(SafeLockAnalysis.ID, Collections.singleton(_sla));
        }

        for (final Iterator _i1 = das.iterator(); _i1.hasNext();) {
            final IDependencyAnalysis _da1 = (IDependencyAnalysis) _i1.next();

            for (final Iterator<? extends Comparable<? extends Object>> _i2 = _da1.getIds().iterator(); _i2
                    .hasNext();) {
                final Comparable<? extends Object> _id = _i2.next();
                _ac.addAnalyses(_id, Collections.singleton(_da1));
            }
        }

        _ac.initialize();
        _ac.execute();

        // write xml
        for (final Iterator _i1 = das.iterator(); _i1.hasNext();) {
            final IDependencyAnalysis _da1 = (IDependencyAnalysis) _i1.next();

            for (final Iterator _i2 = _da1.getIds().iterator(); _i2.hasNext();) {
                final Object _id = _i2.next();
                MapUtils.putIntoListInMap(info, _id, _da1);
            }
        }
        xmlizer.setGenerator(new UniqueJimpleIDGenerator());
        xmlizer.writeXML(info);

        if (dumpJimple) {
            xmlizer.dumpJimple(null, xmlizer.getXmlOutputDir(), _xmlcgipc);
        }
        writeInfo("Total classes loaded: " + getEnvironment().getClasses().size());

        SystemDependenceGraphBuilder.getSystemDependenceGraph(das, _cgi, getEnvironment().getClasses());
    }
}

// End of File