edu.illinois.keshmesh.detector.Main.java Source code

Java tutorial

Introduction

Here is the source code for edu.illinois.keshmesh.detector.Main.java

Source

/**
 * This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
 */
package edu.illinois.keshmesh.detector;

import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.eclipse.jdt.core.IJavaProject;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.ibm.wala.analysis.pointers.BasicHeapGraph;
import com.ibm.wala.analysis.pointers.HeapGraph;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.io.FileProvider;

import edu.illinois.keshmesh.config.ConfigurationOptions;
import edu.illinois.keshmesh.constants.Constants;
import edu.illinois.keshmesh.detector.bugs.BugInstances;
import edu.illinois.keshmesh.detector.bugs.BugPattern;
import edu.illinois.keshmesh.detector.bugs.BugPatterns;
import edu.illinois.keshmesh.detector.exception.Exceptions;
import edu.illinois.keshmesh.detector.exception.Exceptions.WALAInitializationException;
import edu.illinois.keshmesh.detector.util.AnalysisUtils;
import edu.illinois.keshmesh.detector.util.DisplayUtils;
import edu.illinois.keshmesh.report.FileWriterFactory;
import edu.illinois.keshmesh.report.KeyValuePair;
import edu.illinois.keshmesh.report.Reporter;
import edu.illinois.keshmesh.report.StringWriterFactory;
import edu.illinois.keshmesh.walaconfig.KeshmeshCGModel;

/**
 * 
 * @author Mohsen Vakilian
 * @author Stas Negara
 * 
 */
public class Main {

    private static boolean hasShownGraphs = false;

    private final static StringWriterFactory stringWriterFactory = new StringWriterFactory();

    public static BugInstances initAndPerformAnalysis(IJavaProject javaProject, Reporter reporter,
            ConfigurationOptions configurationOptions) throws WALAInitializationException {
        BugInstances bugInstances = new BugInstances();
        int objectSensitivityLevel = configurationOptions.getObjectSensitivityLevel();
        reporter.report(new KeyValuePair("OBJECT_SENSITIVITY_LEVEL", String.valueOf(objectSensitivityLevel)));
        BasicAnalysisData basicAnalysisData = initBytecodeAnalysis(javaProject, reporter, configurationOptions);
        if (configurationOptions.shouldDumpCallGraph()) {
            dumpCallGraph(basicAnalysisData.callGraph);
        }
        Iterator<BugPattern> bugPatternsIterator = BugPatterns.iterator();
        while (bugPatternsIterator.hasNext()) {
            BugPattern bugPattern = bugPatternsIterator.next();
            BugPatternDetector bugPatternDetector = bugPattern.createBugPatternDetector();
            Stopwatch stopWatch = Stopwatch.createStarted();
            BugInstances instancesOfCurrentBugPattern = bugPatternDetector.performAnalysis(javaProject,
                    basicAnalysisData);
            stopWatch.stop();
            reporter.report(
                    new KeyValuePair("BUG_PATTERN_" + bugPattern.getName() + "_DETECTION_TIME_IN_MILLISECONDS",
                            String.valueOf(stopWatch.elapsed(TimeUnit.MILLISECONDS))));
            bugInstances.addAll(instancesOfCurrentBugPattern);
            reporter.report(new KeyValuePair("NUMBER_OF_INSTANCES_OF_BUG_PATTERN_" + bugPattern.getName(),
                    String.valueOf(instancesOfCurrentBugPattern.size())));
        }
        reporter.close();
        return bugInstances;
    }

    private static BasicAnalysisData initBytecodeAnalysis(IJavaProject javaProject, Reporter reporter,
            ConfigurationOptions configurationOptions) throws WALAInitializationException {
        KeshmeshCGModel model;
        try {
            String exclusionsFileName = FileProvider
                    .getFileFromPlugin(Activator.getDefault(), "EclipseDefaultExclusions.txt").getAbsolutePath();
            model = new KeshmeshCGModel(javaProject, exclusionsFileName,
                    configurationOptions.getObjectSensitivityLevel());
            Stopwatch stopWatch = Stopwatch.createStarted();
            model.buildGraph();
            stopWatch.stop();
            reporter.report(new KeyValuePair("CALL_GRAPH_CONSTRUCTION_TIME_IN_MILLISECONDS",
                    String.valueOf(stopWatch.elapsed(TimeUnit.MILLISECONDS))));
            reportEntryPointStatistics(reporter, model.getEntryPoints());
            dumpEntryPoints(model.getEntryPoints());
        } catch (Exception e) {
            throw new Exceptions.WALAInitializationException(e);
        }
        CallGraph callGraph = model.getGraph();
        reportCallGraphStatistics(reporter, callGraph);
        PointerAnalysis pointerAnalysis = model.getPointerAnalysis();
        HeapModel heapModel = pointerAnalysis.getHeapModel();
        BasicHeapGraph heapGraph = new BasicHeapGraph(pointerAnalysis, callGraph);
        if (configurationOptions.shouldDumpHeapGraph()) {
            dumpHeapGraph(heapGraph);
        }
        reporter.report(
                new KeyValuePair("NUMBER_OF_NODES_OF_HEAP_GRAPH", String.valueOf(heapGraph.getNumberOfNodes())));
        if (!hasShownGraphs) {
            try {
                DisplayUtils.displayGraph(callGraph);
                DisplayUtils.displayGraph(heapGraph);
                hasShownGraphs = true;
            } catch (WalaException e) {
                throw new WALAInitializationException(e);
            }
        }
        IClassHierarchy classHierarchy = model.getClassHierarchy();
        reporter.report(new KeyValuePair("NUMBER_OF_CLASSES", String.valueOf(classHierarchy.getNumberOfClasses())));
        return new BasicAnalysisData(classHierarchy, callGraph, pointerAnalysis, heapModel, heapGraph);
    }

    private static void reportEntryPointStatistics(Reporter reporter, Iterable<Entrypoint> entryPoints) {
        reporter.report(new KeyValuePair("NUMBER_OF_ENTRY_POINTS", String.valueOf(Iterables.size(entryPoints))));
    }

    private static void dumpEntryPoints(Iterable<Entrypoint> entryPoints) {
        Writer writer = new FileWriterFactory(Constants.KESHMESH_ENTRY_POINTS_FILE_NAME, stringWriterFactory)
                .create();
        List<Entrypoint> sortedEntryPoints = sortedCopy(entryPoints);
        try {
            writer.write(Joiner.on(Constants.LINE_SEPARATOR).join(sortedEntryPoints));
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static List<Entrypoint> sortedCopy(Iterable<Entrypoint> entryPoints) {
        Ordering<Entrypoint> ordering = Ordering.natural().onResultOf(new Function<Entrypoint, String>() {
            @Override
            public String apply(Entrypoint entryPoint) {
                return entryPoint.toString();
            }
        });
        return ordering.sortedCopy(entryPoints);
    }

    private static void reportCallGraphStatistics(Reporter reporter, CallGraph callGraph) {
        reporter.report(
                new KeyValuePair("NUMBER_OF_NODES_OF_CALL_GRAPH", String.valueOf(callGraph.getNumberOfNodes())));
        Iterable<CGNode> primordialCGNodes = Iterables.filter(callGraph, new Predicate<CGNode>() {
            @Override
            public boolean apply(CGNode cgNode) {
                return AnalysisUtils.isJDKClass(cgNode.getMethod().getDeclaringClass());
            }
        });
        reporter.report(new KeyValuePair("NUMBER_OF_PRIMORDIAL_NODES_OF_CALL_GRAPH",
                String.valueOf(Iterables.size(primordialCGNodes))));
        Iterable<CGNode> extensionCGNodes = Iterables.filter(callGraph, new Predicate<CGNode>() {
            @Override
            public boolean apply(CGNode cgNode) {
                return AnalysisUtils.isLibraryClass(cgNode.getMethod().getDeclaringClass());
            }
        });
        reporter.report(new KeyValuePair("NUMBER_OF_EXTENSION_NODES_OF_CALL_GRAPH",
                String.valueOf(Iterables.size(extensionCGNodes))));
        Iterable<CGNode> applicationCGNodes = Iterables.filter(callGraph, new Predicate<CGNode>() {
            @Override
            public boolean apply(CGNode cgNode) {
                return AnalysisUtils.isApplicationClass(cgNode.getMethod().getDeclaringClass());
            }
        });
        reporter.report(new KeyValuePair("NUMBER_OF_APPLICATION_NODES_OF_CALL_GRAPH",
                String.valueOf(Iterables.size(applicationCGNodes))));
    }

    private static void dumpCallGraph(CallGraph callGraph) {
        Preconditions.checkNotNull(callGraph);
        Writer writer = new FileWriterFactory(Constants.KESHMESH_CALL_GRAPH_FILE_NAME, stringWriterFactory)
                .create();
        Iterator<CGNode> cgNodesIter = callGraph.iterator();
        try {
            while (cgNodesIter.hasNext()) {
                CGNode cgNode = cgNodesIter.next();
                IMethod method = cgNode.getMethod();
                if (AnalysisUtils.isJDKClass(method.getDeclaringClass()))
                    continue;
                writer.write("**CGNode:** " + cgNode + "\n");
                IR ir = cgNode.getIR();
                if (ir != null) {
                    writer.write("**IR:** " + ir + "\n");
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void dumpHeapGraph(HeapGraph heapGraph) {
        Preconditions.checkNotNull(heapGraph);
        Writer writer = new FileWriterFactory(Constants.KESHMESH_HEAP_GRAPH_FILE_NAME, stringWriterFactory)
                .create();
        Preconditions.checkNotNull(heapGraph);
        Iterator<Object> cgNodesIter = heapGraph.iterator();
        try {
            while (cgNodesIter.hasNext()) {
                writer.write(cgNodesIter.next() + "\n");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}