averroes.options.AverroesOptions.java Source code

Java tutorial

Introduction

Here is the source code for averroes.options.AverroesOptions.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Karim Ali and Ondej Lhotk.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Karim Ali - initial API and implementation and/or initial documentation
 *******************************************************************************/
package averroes.options;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import probe.ObjectManager;
import probe.ProbeClass;
import soot.SootClass;

/**
 * A class that holds all the properties required by Averroes to run. For the
 * possible values of each property, you can consult the accompanying
 * averroes.properties.sample file or the online tutorial at {@link http
 * ://karimali.ca/averroes}
 * 
 * @author Karim Ali
 * 
 */
public final class AverroesOptions {

    private static List<String> dynamicClasses = null;

    private static Option applicationRegex = Option.builder("r").longOpt("application-regex").desc(
            "a list of regular expressions for application packages or classes separated by File.pathSeparator")
            .hasArg().argName("regex").required().build();

    private static Option mainClass = Option.builder("m").longOpt("main-class")
            .desc("the main class that runs the application when the program executes").hasArg().argName("class")
            .required().build();

    private static Option applicationJars = Option.builder("a").longOpt("application-jars")
            .desc("a list of the application JAR files separated by File.pathSeparator").hasArg().argName("path")
            .required().build();

    private static Option libraryJars = Option.builder("l").longOpt("library-jars")
            .desc("a list of the JAR files for library dependencies separated by File.pathSeparator").hasArg()
            .argName("path").required(false).build();

    private static Option dynamicClassesFile = Option.builder("d").longOpt("dynamic-classes-file").desc(
            "a file that contains a list of classes that are loaded dynamically by Averroes (e.g., classes instantiated through reflection)")
            .hasArg().argName("file").required(false).build();

    private static Option tamiflexFactsFile = Option.builder("t").longOpt("tamiflex-facts-file")
            .desc("a file that contains reflection facts generated for this application in the TamiFlex format")
            .hasArg().argName("file").required(false).build();

    private static Option outputDirectory = Option.builder("o").longOpt("output-directory")
            .desc("the directory to which Averroes will write any output files/folders.").hasArg()
            .argName("directory").required().build();

    private static Option jreDirectory = Option.builder("j").longOpt("java-runtime-directory")
            .desc("the directory that contains the Java runtime environment that Averroes should model").hasArg()
            .argName("directory").required().build();

    private static Option help = Option.builder("h").longOpt("help").desc("print out this help message")
            .hasArg(false).required(false).build();

    private static Options options = new Options().addOption(applicationRegex).addOption(mainClass)
            .addOption(applicationJars).addOption(libraryJars).addOption(dynamicClassesFile)
            .addOption(tamiflexFactsFile).addOption(outputDirectory).addOption(jreDirectory).addOption(help);

    private static CommandLine cmd;

    /**
     * Process the input arguments of Averroes.
     * 
     * @param args
     */
    public static void processArguments(String[] args) {
        try {
            cmd = new DefaultParser().parse(options, args);

            // Do we need to print out help messages?
            if (cmd.hasOption(help.getOpt())) {
                help();
            }
        } catch (ParseException e) {
            e.printStackTrace();
            help();
        }
    }

    /**
     * Print out some help information.
     */
    private static void help() {
        new HelpFormatter().printHelp("jar -jar averroes.jar", "", options, "", true);
        System.exit(0);
    }

    /**
     * The list of application packages or classes separated by
     * {@link File#pathSeparator}.
     * 
     * @return
     */
    public static List<String> getApplicationRegex() {
        return Arrays.asList(cmd.getOptionValue(applicationRegex.getOpt()).split(File.pathSeparator));
    }

    /**
     * The main class that runs the application when the program executes.
     * 
     * @return
     */
    public static String getMainClass() {
        return cmd.getOptionValue(mainClass.getOpt());
    }

    /**
     * The list of the application JAR files separated by
     * {@link File#pathSeparator}.
     * 
     * @return
     */
    public static List<String> getApplicationJars() {
        return Arrays.asList(cmd.getOptionValue(applicationJars.getOpt()).split(File.pathSeparator));
    }

    /**
     * The list of the library JAR files separated by {@link File#pathSeparator}
     * 
     * @return
     */
    public static List<String> getLibraryJarFiles() {
        return Arrays.asList(cmd.getOptionValue(libraryJars.getOpt(), "").split(File.pathSeparator));
    }

    /**
     * Is support for dynamic classes enabled?
     * 
     * @return
     */
    public static boolean isDynamicClassesEnabled() {
        return cmd.hasOption(dynamicClassesFile.getOpt());
    }

    /**
     * Get the names of classes that might be dynamically loaded by the input
     * program.
     * 
     * @return
     */
    public static List<String> getDynamicClasses() throws IOException {
        if (dynamicClasses == null) {
            dynamicClasses = new ArrayList<String>();

            if (isDynamicClassesEnabled()) {
                BufferedReader in = new BufferedReader(
                        new FileReader(cmd.getOptionValue(dynamicClassesFile.getOpt())));
                String line;
                while ((line = in.readLine()) != null) {
                    dynamicClasses.add(line);
                }
                in.close();
            }
        }

        return dynamicClasses;
    }

    /**
     * Get the class names of the dynamic library classes.
     * 
     * @return
     * @throws IOException
     */
    public static List<String> getDynamicLibraryClasses() throws IOException {
        return getDynamicClasses().stream().filter(AverroesOptions::isLibraryClass).collect(Collectors.toList());
    }

    /**
     * Get the class names of the dynamic application classes.
     * 
     * @return
     * @throws IOException
     */
    public static List<String> getDynamicApplicationClasses() throws IOException {
        return getDynamicClasses().stream().filter(AverroesOptions::isApplicationClass)
                .collect(Collectors.toList());
    }

    /**
     * Is support for TamiFlex facts enabled?
     * 
     * @return
     */
    public static boolean isTamiflexEnabled() {
        return cmd.hasOption(tamiflexFactsFile.getOpt());
    }

    /**
     * Get the files that contains the reflection facts in the TamiFlex format
     * for this program.
     * 
     * @return
     */
    public static String getTamiflexFactsFile() {
        return cmd.getOptionValue(tamiflexFactsFile.getOpt(), "");
    }

    /**
     * The directory to which Averroes will write any output files/folders.
     * 
     * @return
     */
    public static String getOutputDirectory() {
        return cmd.getOptionValue(outputDirectory.getOpt());
    }

    /**
     * The version for the Java runtime environment to be used. This can one of
     * (1.4, 1.6, 1.7, 1.8, system).
     * 
     * @return
     */
    public static String getJreDirectory() {
        return cmd.getOptionValue(jreDirectory.getOpt());
    }

    /**
     * Check if a class belongs to the application, based on the
     * {@value #APPLICATION_INCLUDES} property.
     * 
     * @param probeClass
     * @return
     */
    public static boolean isApplicationClass(ProbeClass probeClass) {
        for (String entry : getApplicationRegex()) {
            /*
             * 1. If the entry ends with .* then this means it's a package. 2.
             * If the entry ends with .** then it's a super package. 3. If the
             * entry is **, then it's the default package. 4. Otherwise, it's
             * the full class name.
             */
            if (entry.endsWith(".*")) {
                String pkg = entry.replace(".*", "");
                if (probeClass.pkg().equalsIgnoreCase(pkg)) {
                    return true;
                }
            } else if (entry.endsWith(".**")) {
                String pkg = entry.replace("**", "");
                if (probeClass.toString().startsWith(pkg)) {
                    return true;
                }
            } else if (entry.equalsIgnoreCase("**") && probeClass.pkg().isEmpty()) {
                return true;
            } else if (entry.equalsIgnoreCase(probeClass.toString())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check if a class belongs to the application, based on the
     * {@link #applicationRegex} option.
     * 
     * @param className
     * @return
     */
    public static boolean isApplicationClass(String className) {
        return isApplicationClass(ObjectManager.v().getClass(className));
    }

    /**
     * Check if a class belongs to the application, based on the
     * {@link #applicationRegex} option.
     * 
     * @param sootClass
     * @return
     */
    public static boolean isApplicationClass(SootClass sootClass) {
        return isApplicationClass(sootClass.getName());
    }

    /**
     * Check if a class belongs to the library (i.e., not an application class).
     * 
     * @param className
     * @return
     */
    public static boolean isLibraryClass(String className) {
        return !isApplicationClass(className);
    }
}