Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

BOFA.java

00001 package edu.ksu.cis.bandera.bofa;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999                                          *
00006  * John Hatcliff (hatcliff@cis.ksu.edu)                              *
00007  * All rights reserved.                                              *
00008  *                                                                   *
00009  * This work was done as a project in the SAnToS Laboratory,         *
00010  * Department of Computing and Information Sciences, Kansas State    *
00011  * University, USA (http://www.cis.ksu.edu/santos).                  *
00012  * It is understood that any modification not identified as such is  *
00013  * not covered by the preceding statement.                           *
00014  *                                                                   *
00015  * This work is free software; you can redistribute it and/or        *
00016  * modify it under the terms of the GNU Library General Public       *
00017  * License as published by the Free Software Foundation; either      *
00018  * version 2 of the License, or (at your option) any later version.  *
00019  *                                                                   *
00020  * This work is distributed in the hope that it will be useful,      *
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00023  * Library General Public License for more details.                  *
00024  *                                                                   *
00025  * You should have received a copy of the GNU Library General Public *
00026  * License along with this toolkit; if not, write to the             *
00027  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00028  * Boston, MA  02111-1307, USA.                                      *
00029  *                                                                   *
00030  * Java is a trademark of Sun Microsystems, Inc.                     *
00031  *                                                                   *
00032  * To submit a bug report, send a comment, or get the latest news on *
00033  * this project and other SAnToS projects, please visit the web-site *
00034  *                http://www.cis.ksu.edu/santos                      *
00035  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00036 
00037 import ca.mcgill.sable.soot.*;
00038 import ca.mcgill.sable.soot.baf.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import ca.mcgill.sable.util.*;
00041 
00042 import edu.ksu.cis.bandera.annotation.*;
00043 import edu.ksu.cis.bandera.jjjc.CompilationManager;
00044 import edu.ksu.cis.bandera.jjjc.exception.CompilerException;
00045 import edu.ksu.cis.bandera.util.*;
00046 
00047 import java.io.*;
00048 import java.util.Enumeration;
00049 import java.util.Hashtable;
00050 import java.util.Vector;
00051 import java.net.URL;
00052 
00053 import org.apache.log4j.PropertyConfigurator;
00054 import org.apache.log4j.PatternLayout;
00055 import org.apache.log4j.FileAppender;
00056 
00057 /*
00058  * BOFA.java
00059  * $Id: BOFA.java,v 1.2 2002/02/01 04:08:44 robby Exp $
00060  */
00061 
00062 /**
00063  * The main class of Bandera Object Flow Analysis.  It needs to be used along
00064  * with JJJC of Bandera to do Object Flow Analysis.  It can be used
00065  * independently if soot support is available.  It serves as a stub for
00066  * executing independent of Bandera.  It can be invoked from the command prompt.
00067  *
00068  * @author <a href="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</a>
00069  * @author 
00070  * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>  
00071  *
00072  * @version $Name:  $($Revision: 1.2 $)
00073  */
00074 public class BOFA
00075 {
00076     /**
00077      * Indicates whether the Jimple files of the analyzed class should be dumped
00078      * or not.
00079      *
00080      */
00081     private static boolean dump = false;
00082 
00083     /**
00084      * Class in the code from where the analysis will commence.
00085      *
00086      */
00087     private static SootClass rootSootClass;
00088 
00089     /**
00090      * Method in the rootSootClass from where the analysis will commence.
00091      *
00092      */
00093     private static SootMethod rootSootMethod;
00094 
00095     /**
00096      * Collection of classes to be analyzed.  
00097      *
00098      * This should include all classes which can be reached from the given
00099      * classes.
00100      *
00101      */
00102     private static Collection storedClasses = null;
00103 
00104     /**
00105      * <code>SootClassManager</code> object managing the classes to be analyzed.
00106      *
00107      */
00108     static SootClassManager sootClassManager = null;
00109 
00110     /**
00111      * Central registry of callbacks.  Such callbacks are used to alter the flow
00112      * graph.  
00113      *
00114      * One possible way is to add callbacks to hook the <code>run</code> method
00115      * as a result of <code>start</code> method call.  This relation is not
00116      * evident in the Java source code but rather in the native code.
00117      *
00118      */
00119     static CallBackRegistry callbackReg = new CallBackRegistry();
00120 
00121     /*
00122      * Initializes the logging API used in BOFA.
00123      */
00124     static {
00125         try {
00126             URL t = callbackReg.getClass().getClassLoader()
00127                 .getResource("edu/ksu/cis/bandera/bofa/log4j.properties");
00128             PropertyConfigurator.configure(t);
00129         } catch (Exception  e) {
00130             System.out.println("##########################################" + 
00131                                "############################");
00132             System.out.println("Failed to initialize log4j.");
00133             e.printStackTrace();
00134             System.out.println("##########################################" + 
00135                                "############################");
00136         } // end of try-catch
00137     }   
00138 
00139     /**
00140      * Analyzes the classes that are available through JJJC.
00141      *
00142      * It is assumed that the <code>sootClassManager</code> and the
00143      * <code>storedClasses</code> has been initialized by a prior call to
00144      * <code>compile</code> or <code>analyze(SootClassManager, Collection</code>
00145      * was called.  If that is not the case, the available classes from the
00146      * <code>edu.ksu.cis.bandera.jjjc.CompilationManager</code> are used to
00147      * analyze.
00148      *
00149      * @exception ClassesNotCompiledException if there are no compiled classes
00150      * to be analyzed.
00151      * @see #analyze(SootClassManager, Collection) analyze
00152      * @see #compile compile
00153      */
00154     public static void analyze()
00155     {
00156         SootClass sc;
00157 
00158         if (sootClassManager == null)
00159             sootClassManager = CompilationManager.getSootClassManager();
00160         if (storedClasses == null)
00161             storedClasses = Util.convert("ca.mcgill.sable.util.VectorList", 
00162                                          CompilationManager.getCompiledClasses()
00163                                          .values());
00164         if (storedClasses == null || storedClasses.size() == 0) {
00165             System.out.println("You need to compile before you do Flow Analysis"
00166                                + storedClasses + " ******** " + 
00167                                storedClasses.size());
00168             class ClassesNotCompiledException extends RuntimeException 
00169             {
00170                 ClassesNotCompiledException() {}
00171             }
00172             throw new ClassesNotCompiledException();
00173         }
00174 
00175         System.out.println("Running BOFA...");
00176 
00177         // What if there is more than one main method?
00178         // What if there is no main method?
00179         for (Iterator e = storedClasses.iterator(); e.hasNext();) {
00180             sc = (SootClass) e.next();      
00181             if (sc.declaresMethod("main")) {
00182                 rootSootClass = sc;
00183                 rootSootMethod = sc.getMethod("main");
00184                 break;
00185             }
00186         }
00187         /* 
00188          * we are at present interested in only the run method defined by
00189          * classes extending Thread.  We may include stuff for analysing start()
00190          * and stop() methods of Applets. 
00191          */
00192         callbackReg.regVInvoke(new VInvokeCallBack());
00193         FA.init(sootClassManager, rootSootClass, rootSootMethod);
00194         FA.run();
00195     }
00196     /** 
00197      * Analyzes the loaded classes.
00198      *
00199      * This interface can be used analyze a set of classes which are
00200      * "jimplified" using <i>soot</i> directly.
00201      *
00202      * @param sootClassManager the class manager managing the classes to be
00203      * analyzed. 
00204      * @param storedClasses a collection of compiled
00205      * classes(<code>SootClass</code>) provided for analysis. 
00206      *
00207      * @see #analyze() analyze
00208      */
00209     public static void analyze(SootClassManager sootClassManager, 
00210                                Collection storedClasses)
00211     {
00212         BOFA.storedClasses = storedClasses;
00213         BOFA.sootClassManager = sootClassManager;
00214         analyze();
00215     }
00216     /**
00217      * Compiles the given java classes using JJJC.
00218      *
00219      * @param classPath the classpath required to compile java files.
00220      * @param classNames the names of the Java files which need to be compiled.
00221      * @param packageNames the names of the packages needed during compilation.
00222      */
00223     public static void compile(String classPath, LinkedList classNames,
00224                                   LinkedList packageNames)
00225     {
00226         String[] packages = new String[packageNames.size()];
00227         SootClass sc;
00228         int j = 0;
00229 
00230         System.out.println("Adding relevant classes...");
00231         for (Iterator i = packageNames.iterator(); i.hasNext(); j++) {
00232             packages[j] = (String) i.next();
00233         }
00234 
00235             CompilationManager.setClasspath(classPath);
00236             CompilationManager.setIncludedPackagesOrTypes(packages);
00237             try {
00238                 for (Iterator i = classNames.iterator(); i.hasNext();) {
00239                     CompilationManager.setFilename((String)i.next());
00240                     CompilationManager.compile();
00241                     CompilationManager.compile();
00242                 }
00243             } catch (Exception e) {
00244             }
00245             Hashtable exceptions = CompilationManager.getExceptions();
00246             if (exceptions.size() > 0) {
00247                 System.out.println("Compilation failed:");
00248                 for (Enumeration e = exceptions.keys(); e.hasMoreElements();) {
00249                     Object filename = e.nextElement();
00250                     System.out.println("- " + filename);
00251                     Vector es = (Vector) exceptions.get(filename);
00252                     for (java.util.Iterator i = es.iterator(); i.hasNext();) {
00253                         System.out.println("  * " + i.next());
00254                     }
00255                 }
00256             }
00257             storedClasses =
00258                 Util.convert("ca.mcgill.sable.util.VectorList", 
00259                              CompilationManager.getCompiledClasses().values());
00260             sootClassManager = CompilationManager.getSootClassManager();
00261     }
00262     /**
00263      * Outputs the Jimple representation of all classes available through the
00264      * class manager.
00265      *
00266      * @param outputPath the location where the jimple representation should be
00267      * written. 
00268      *
00269      * @exception RuntimeException if the jimple files could not be created or 
00270      * written. 
00271      */
00272     static void dumpFile(String outputPath)
00273     {
00274         StoredBody bd = new StoredBody(Jimple.v());
00275         String className;
00276         File jimpFile;
00277         FileOutputStream jimpOut;
00278         SootClass sc;
00279         for (Iterator e = storedClasses.iterator(); e.hasNext();) {
00280             sc = (SootClass) e.next();
00281             className = sc.getName();
00282             try {
00283                 jimpFile = new File(outputPath + File.separator + className + 
00284                                     ".original.jimple");
00285                 jimpOut = new FileOutputStream(jimpFile);
00286                 sc.printTo(bd, new PrintWriter(jimpOut, true));
00287             } catch (IOException ex) {
00288                 throw new RuntimeException("Could not dump jimple file (" +
00289                                             className + ")");
00290             }
00291         }
00292     }
00293     /**
00294      * Entry point to BOFA in stand alone mode.  
00295      *
00296      * Currently nothing is displayed after the analysis.  It provides an
00297      * assurance of whether the analysis went along fine or failed.
00298      *
00299      * @param args is the command line arguments.
00300      */
00301     public static void main(String[] args)
00302     {
00303         LinkedList packageNames = new LinkedList();
00304         LinkedList classNames = new LinkedList();
00305         String classPath = ".";
00306         String outputPath = ".";
00307         if (args.length == 0)
00308             printUsage();
00309 
00310         // command line processor
00311         try {
00312             for (int i = 0; i < args.length; i++) {
00313                 if (args[i].equals("--help")) {
00314                     printUsage();
00315                 } else if (args[i].equals("--dump")) {
00316                     dump = true;
00317                 } else if (args[i].equals("--package")) {
00318                     i++;
00319                     while ((i < args.length) && (!args[i].startsWith("--"))) {
00320                         packageNames.addLast(args[i].trim());
00321                         i++;
00322                     }
00323                     i--;
00324                 } else if (args[i].equals("--classpath")) {
00325                     i++;
00326                     if (i < args.length) {
00327                         classPath = args[i];
00328                     } else {
00329                         printUsage();
00330                     }
00331                 } else if (args[i].equals("--outputdir")) {
00332                     i++;
00333                     if (i < args.length) {
00334                         outputPath = args[i];
00335                     } else {
00336                         printUsage();
00337                     }
00338                 } else if (args[i].equals("--source")) {
00339                     i++;
00340                     while ((i < args.length) && (!args[i].startsWith("--"))) {
00341                         classNames.addLast(args[i].trim());
00342                         i++;
00343                     }
00344                     i--;
00345                 } else {
00346                     System.out.println("Error parsing argument: " + args[i]);
00347                     printUsage();
00348                 }
00349             }
00350         } catch (Exception ex) {
00351             System.out.println("Error in parsing arguments (" + ex + ")");
00352             printUsage();
00353         }
00354 
00355         // adding relevant classes
00356         compile(classPath, classNames, packageNames);
00357 
00358         if (dump)
00359             dumpFile(outputPath);
00360 
00361         // invoke flow analyzer
00362         analyze();
00363     }  
00364     /**
00365      * Safe exit in case of wrong usage in command line mode.
00366      */
00367     static void printUsage()
00368     {
00369         System.out.println("Wrong usage");
00370         System.out.println("java edu.ksu.cis.bandera.bofa.BOFA --source " + 
00371                            "<source> [--dump] [--classpath <path>] " + 
00372                            "[--package <package>] [--outpurdir <dir>]");
00373         System.exit(0);
00374     }
00375     /**
00376      * Resets the complete Analysis engine.  All collected data are destroyed.
00377      *
00378      */
00379     public static void reset() {
00380         rootSootClass = null;
00381         rootSootMethod = null;
00382         sootClassManager = null;
00383         storedClasses = null;
00384         FA.reset();
00385     }
00386 }

Generated at Thu Feb 7 06:41:05 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001