edu.ksu.cis.indus.staticanalyses.flow.instances.ofa.OFAXMLizerCLI.java Source code

Java tutorial

Introduction

Here is the source code for edu.ksu.cis.indus.staticanalyses.flow.instances.ofa.OFAXMLizerCLI.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.flow.instances.ofa;

import edu.ksu.cis.indus.common.ToStringBasedComparator;
import edu.ksu.cis.indus.common.collections.MapUtils;
import edu.ksu.cis.indus.common.datastructures.Pair.PairManager;
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.common.soot.MetricsProcessor.MetricKeys;
import edu.ksu.cis.indus.processing.IProcessingFilter;
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.interfaces.IValueAnalyzer;
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.AbstractXMLizer;
import edu.ksu.cis.indus.xmlizer.UniqueJimpleIDGenerator;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
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.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.apache.commons.cli.PosixParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import soot.SootMethod;
import soot.Type;
import soot.Value;

/**
 * This class provides a command-line interface to xmlize object flow information.
 * 
 * @author <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
 * @author $Author: rvprasad $
 * @version $Revision: 1.47 $ $Date: 2007/02/10 19:07:50 $
 */
public final class OFAXMLizerCLI extends SootBasedDriver {

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

    /**
     * This indicates if analysis should be run for all root methods or separated for each root method.
     */
    private boolean cumulative;

    /**
     * The type/sort of OFA to use.
     */
    private String type;

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

    /**
     * Retrieves the name that serves as the base for the file names into which info will be dumped along with the root
     * methods to be considered in one execution of the analyses.
     * 
     * @param root is the object based on which base name should be generated.
     * @param methods is the collection that will contain the root methods upon return.
     * @return a name along with the root methods via <code>methods</code>.
     * @pre root != null and methods != null
     * @post result != null and (methods.contains(root) or methods.containsAll(root))
     */
    public static String getBaseNameOfFileAndRootMethods(final Object root, final Collection<SootMethod> methods) {
        final String _result;

        if (root instanceof SootMethod) {
            final SootMethod _sm = (SootMethod) root;
            _result = (_sm.getDeclaringClass().getJavaStyleName() + "_" + _sm.getSubSignature()).replaceAll(" ",
                    "_");
            methods.add(_sm);
        } else {
            _result = "cumulative_" + System.currentTimeMillis();
            methods.addAll((Collection) root);
        }
        return _result;
    }

    /**
     * The entry point to the program via command line.
     * 
     * @param args is the command line arguments.
     * @throws RuntimeException when object flow analysis fails.
     */
    public static void main(final String[] args) {
        final Options _options = new Options();
        Option _option = new Option("c", "cumulative", false, "Consider all root methods in the same execution.");
        _options.addOption(_option);
        _option = new Option("o", "output", true, "Directory into which xml files will be written into.");
        _option.setArgs(1);
        _options.addOption(_option);
        _option = new Option("j", "jimple", false, "Dump xmlized jimple.");
        _options.addOption(_option);
        _option = new Option("h", "help", false, "Display message.");
        _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("t", "ofa-type", false, "Type of analysis : fioi, fsoi, fios, fsos, fioirt, fsoirt.");
        _option.setArgs(1);
        _option.setArgName("type");
        _option.setOptionalArg(false);
        _option.setRequired(true);
        _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);

        final PosixParser _parser = new PosixParser();

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

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

            String _outputDir = _cl.getOptionValue('o');

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

            if (_cl.getArgList().isEmpty()) {
                throw new MissingArgumentException("Please specify atleast one class.");
            }

            final OFAXMLizerCLI _cli = new OFAXMLizerCLI();
            _cli.xmlizer.setXmlOutputDir(_outputDir);
            _cli.xmlizer.setGenerator(new UniqueJimpleIDGenerator());
            _cli.setCumulative(_cl.hasOption('c'));
            _cli.setClassNames(_cl.getArgList());
            _cli.type = _cl.getOptionValue('t');

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

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

            _cli.initialize();

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

    /**
     * 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 " + OFAXMLizerCLI.class.getName() + " <options> <classnames>";
        (new HelpFormatter()).printHelp(_cmdLineSyn, "Options are: ", options, "");
    }

    /**
     * Xmlize the given system.
     * 
     * @param dumpJimple <code>true</code> indicates that the jimple should be xmlized as well; <code>false</code>,
     *            otherwise.
     * @param <T> dummy type parameter.
     */
    private <T extends ITokens<T, Value>> void execute(final boolean dumpJimple) {
        setInfoLogger(LOGGER);

        final String _tagName = "OFAXMLizer:FA";
        final IValueAnalyzer<Value> _aa;
        if (type.equals("fioi")) {
            _aa = OFAnalyzer.getFIOIAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else if (type.equals("fios")) {
            _aa = OFAnalyzer.getFIOSAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else if (type.equals("fsoi")) {
            _aa = OFAnalyzer.getFSOIAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else if (type.equals("fsos")) {
            _aa = OFAnalyzer.getFSOSAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else if (type.equals("fioirt")) {
            _aa = OFAnalyzer.getFSOIRTAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else if (type.equals("fsoirt")) {
            _aa = OFAnalyzer.getFSOIRTAnalyzer(_tagName,
                    TokenUtil.<T, Value, Type>getTokenManager(new SootValueTypeManager()), getStmtGraphFactory());
        } else {
            throw new IllegalArgumentException(
                    "ofa-type has to be one of the following: fioi, fsoi, fios, fsos, fioirt," + " fsoirt.");
        }

        final ValueAnalyzerBasedProcessingController _pc = new ValueAnalyzerBasedProcessingController();
        final Collection<IProcessor> _processors = new ArrayList<IProcessor>();
        final CallGraphInfo _cgi = new CallGraphInfo(new PairManager(false, true));
        final OFABasedCallInfoCollector _callGraphInfoCollector = new OFABasedCallInfoCollector();
        final Collection<SootMethod> _rm = new ArrayList<SootMethod>();
        final ProcessingController _xmlcgipc = new ProcessingController();
        final MetricsProcessor _countingProcessor = new MetricsProcessor();
        final OneAllStmtSequenceRetriever _ssr = new OneAllStmtSequenceRetriever();
        _ssr.setStmtGraphFactory(getStmtGraphFactory());
        _pc.setStmtSequencesRetriever(_ssr);
        _pc.setAnalyzer(_aa);

        final IProcessingFilter _tagFilter = new TagBasedProcessingFilter(_tagName);
        _pc.setProcessingFilter(_tagFilter);
        _xmlcgipc.setEnvironment(_aa.getEnvironment());

        final IProcessingFilter _xmlFilter = new CGBasedXMLizingProcessingFilter(_cgi);
        _xmlFilter.chain(_tagFilter);
        _xmlcgipc.setProcessingFilter(_xmlFilter);
        _xmlcgipc.setStmtSequencesRetriever(_ssr);

        final Map _info = new HashMap();
        _info.put(IValueAnalyzer.ID, _aa);
        _info.put(IValueAnalyzer.TAG_ID, _tagName);

        final List<Object> _roots = new ArrayList<Object>();

        if (cumulative) {
            _roots.add(getRootMethods());
        } else {
            _roots.addAll(getRootMethods());
        }
        Collections.sort(_roots, ToStringBasedComparator.getComparator());
        writeInfo("Root methods are: " + _roots.size() + "\n" + _roots);

        for (final Iterator<Object> _k = _roots.iterator(); _k.hasNext();) {
            _rm.clear();

            final Object _root = _k.next();
            final String _fileBaseName = getBaseNameOfFileAndRootMethods(_root, _rm);

            writeInfo("RootMethod: " + _root);
            writeInfo("BEGIN: FA");

            final long _start = System.currentTimeMillis();
            _aa.reset();
            getBbm().reset();

            _aa.analyze(getEnvironment(), _rm);

            final long _stop = System.currentTimeMillis();
            addTimeLog("FA", _stop - _start);
            writeInfo("END: FA");

            _callGraphInfoCollector.reset();
            _processors.clear();
            _processors.add(_callGraphInfoCollector);
            _processors.add(_countingProcessor);
            _pc.reset();
            _pc.driveProcessors(_processors);
            _processors.clear();
            _cgi.reset();
            _cgi.createCallGraphInfo(_callGraphInfoCollector.getCallInfo());

            final ByteArrayOutputStream _stream = new ByteArrayOutputStream();
            new PrintWriter(_stream).write("STATISTICS: " + MapUtils.verbosePrint(
                    new TreeMap<MetricKeys, Map<Object, Integer>>(_countingProcessor.getStatistics())));
            writeInfo(_stream.toString());

            _info.put(AbstractXMLizer.FILE_NAME_ID, _fileBaseName);
            _info.put(IStmtGraphFactory.ID, getStmtGraphFactory());
            xmlizer.writeXML(_info);

            if (dumpJimple) {
                ((AbstractXMLizer) xmlizer).dumpJimple(_fileBaseName, xmlizer.getXmlOutputDir(), _xmlcgipc);
            }

            final OFAStringizer _str = new OFAStringizer();
            _str.getOFAInfoAsString(_info, new PrintWriter(System.out));
        }
    }

    /**
     * Sets cumulative mode.
     * 
     * @param option <code>true</code> indicates all root methods should be analyzed in one go; <code>false</code>
     *            indicates analysis should be executed once for each root method.
     */
    private void setCumulative(final boolean option) {
        cumulative = option;
    }
}

// End of File