/******************************************************************************* * Copyright (c) 2014 Imperial College London * 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: * Raul Castro Fernandez - initial API and implementation ******************************************************************************/ package uk.ac.imperial.lsds.java2sdg; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import soot.CompilationDeathException; import soot.PhaseOptions; import soot.Scene; import soot.SootClass; import soot.SootField; import soot.SootMethod; import soot.options.Options; import soot.toolkits.graph.UnitGraph; import soot.util.Chain; import uk.ac.imperial.lsds.java2sdg.bricks.InternalStateRepr; import uk.ac.imperial.lsds.java2sdg.bricks.SDG.OperatorBlock; import uk.ac.imperial.lsds.java2sdg.bricks.SDG.PartialSDGBuilder; import uk.ac.imperial.lsds.java2sdg.bricks.SDG.SDGBuilder; import uk.ac.imperial.lsds.java2sdg.bricks.TaskElement.TaskElementBuilder; import uk.ac.imperial.lsds.java2sdg.codegenerator.CodeGenerator; import uk.ac.imperial.lsds.java2sdg.flowanalysis.LiveVariableAnalysis; import uk.ac.imperial.lsds.java2sdg.flowanalysis.TEBoundaryAnalysis; import uk.ac.imperial.lsds.java2sdg.input.SourceCodeHandler; import uk.ac.imperial.lsds.java2sdg.output.DOTExporter; public class Main { private final static Logger log = LoggerFactory.getLogger(Main.class.getName()); public static void main(String args[]){ /** Parse input parameters **/ // Define options org.apache.commons.cli.Options options = new org.apache.commons.cli.Options(); options.addOption("h", "help", false, "print this message"); options.addOption("t", "target", true, "desired target. dot for DOT file or seepjar for SEEP runnable jar"); options.addOption("o", "output", true, "desired output file name"); options.addOption("i", "input", true, "the name of the input program"); options.addOption("cp", "classpath", true, "the path to additional libraries and code used by the input program"); // generate helper HelpFormatter formatter = new HelpFormatter(); // Parse arguments CommandLineParser parser = new BasicParser(); CommandLine cmd = null; try { cmd = parser.parse(options, args); } catch (ParseException e) { // TODO Auto-generated catch block System.err.println( "Parsing failed. Reason: " + e.getMessage() ); } // Get values String className = null; String pathToSeepJar = "../seep-system/target/seep-system-0.0.1-SNAPSHOT.jar"; String pathToDriverFile = null; String outputTarget = null; String outputFileName = null; if(cmd.hasOption("i")){ className = cmd.getOptionValue("i"); if(className == null){ formatter.printHelp( "java2sdg", options ); System.exit(0); } } else{ formatter.printHelp( "java2sdg", options ); System.exit(0); } if(cmd.hasOption("cp")){ pathToDriverFile = cmd.getOptionValue("cp"); if(pathToDriverFile == null){ System.err.println("cp parameter cannot be empty. Please specify the path to your classpath"); System.exit(0); } } else{ pathToDriverFile = "."; } if(cmd.hasOption("o")){ outputFileName = cmd.getOptionValue("o"); if(outputFileName == null){ System.err.println("o parameter cannot be empty. Please specify a name for the output file"); System.exit(0); } } else{ formatter.printHelp( "java2sdg", options ); System.exit(0); } if(cmd.hasOption("t")){ outputTarget = cmd.getOptionValue("t"); if(outputTarget == null){ System.err.println("t parameter cannot be empty. Please specify a target, dot/seepjar"); System.exit(0); } if(!(outputTarget.equals("dot") || outputTarget.equals("seepjar"))){ System.err.println("Invalid target option"); formatter.printHelp( "java2sdg", options ); System.exit(0); } } else{ outputTarget = "dot"; } /** Set up SOOT for compilation and java manipulation **/ // Get java.home to access rt.jar, required by soot String javaHome = System.getProperty("java.home"); String sootClassPath = javaHome+"/lib/rt.jar:"+pathToSeepJar+":./"; String pathToSourceCode = pathToDriverFile+"/"+className; /** Parse input program source code. This stage performs operations at high level only **/ // Parse original source code log.info("Parsing source code..."); SourceCodeHandler sch = SourceCodeHandler.getInstance(pathToSourceCode); log.info("Parsing source code...OK"); /** Initialise soot and load input program **/ // With the class loaded, we can then get the SootClass wrapper to work with log.info("Setting soot classpath: "+sootClassPath); Scene.v().setSootClassPath(sootClassPath); Options.v().setPhaseOption("jb", "preserve-source-annotations"); log.info("Loading class..."); SootClass c = null; try{ System.out.println(); c = Scene.v().loadClassAndSupport(className); c.setApplicationClass(); } catch(CompilationDeathException cde){ System.out.println(); log.error(cde.getMessage()); System.exit(1); } log.info("Loading class...OK"); /** Extract fields and workflows **/ PhaseOptions.v().setPhaseOption("tag.ln", "on"); // tell compiler to include line numbers // List fields and indicate which one is state log.info("Extracting state information..."); Chain<SootField> fields = c.getFields(); Iterator<SootField> fieldsIterator = fields.iterator(); Map<String, InternalStateRepr> stateElements = Util.extractStateInformation(fieldsIterator); log.info("Extracting state information...OK"); // List relevant methods (the ones that need to be analyzed) log.info("Extracting workflows..."); Iterator<SootMethod> methodIterator = c.methodIterator(); List<String> workflows = Util.extractWorkflows(methodIterator, c); log.info("Extracting workflows...OK"); //TODO: Insert a module here that checks for illegal programs (lower level than only parsing source code) /** Build partialSDGs, one per workflow **/ SDGBuilder sdgBuilder = new SDGBuilder(); int workflowId = 0; // Analyse and extract a partial SDG per workflow for(String methodName : workflows){ // Build CFG log.info("Building partialSDG for workflow: "+methodName); UnitGraph cfg = Util.getCFGForMethod(methodName, c); // get cfg // Perform live variable analysis LiveVariableAnalysis lva = LiveVariableAnalysis.getInstance(cfg); //compute livevariables // Perform TE boundary analysis TEBoundaryAnalysis oba = TEBoundaryAnalysis.getBoundaryAnalyzer(cfg, stateElements, sch, lva); List<TaskElementBuilder> sequentialTEList = oba.performTEAnalysis(); List<OperatorBlock> partialSDG = PartialSDGBuilder.buildPartialSDG(sequentialTEList, workflowId); // for(OperatorBlock ob : partialSDG){ // System.out.println(ob); // } workflowId++; sdgBuilder.addPartialSDG(partialSDG); } /** Build SDG from partialSDGs **/ log.info("Building SDG from "+sdgBuilder.getNumberOfPartialSDGs()+" partialSDGs..."); List<OperatorBlock> sdg = sdgBuilder.synthetizeSDG(); // for(OperatorBlock ob : sdg){ // System.out.println(ob); // } log.info("Building SDG from partialSDGs...OK"); /** Ouput SDG in a given format **/ // Output if(outputTarget.equals("dot")){ // dot output // Export SDG to dot log.info("Exporting SDG to DOT file..."); DOTExporter exporter = DOTExporter.getInstance(); exporter.export(sdg, outputFileName); log.info("Exporting SDG to DOT file...OK"); } else if(outputTarget.equals("seepjar")){ log.info("Exporting SEEP runnable query..."); List<OperatorBlock> assembledCode = CodeGenerator.assemble(sdg); for(OperatorBlock ob : assembledCode){ System.out.println("---->"); System.out.println(""); System.out.println(""); System.out.println(""); System.out.println(""); System.out.println(ob.getCode()); System.out.println(""); System.out.println(""); System.out.println(""); System.out.println(""); } // Set<TaskElement> sdg = SDGAssembler.getSDG(oba, lva, sch); // // // SDGAssembler sdgAssembler = new SDGAssembler(); // // Set<OperatorBlock> sdg = sdgAssembler.getFakeLinearPipelineOfStatelessOperators(1); // // QueryBuilder qBuilder = new QueryBuilder(); // String q = qBuilder.generateQueryPlanDriver(sdg); // System.out.println("QueryPlan: "+q); // qBuilder.buildAndPackageQuery(); } } }