Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: edu/ucsb/ccs/jcontractor/jContractor.java


1   package edu.ucsb.ccs.jcontractor;
2   
3   import java.util.*;
4   import java.io.*;
5   import java.lang.reflect.Method;
6   import java.lang.reflect.InvocationTargetException;
7   import com.werken.opt.*;
8   
9   /**
10   * Main entry point into the jContractor system.  This class can be
11   * run stand alone to run another program with contract checking
12   * enabled.  jContractor will substitute its own class loader for the
13   * default class loader, and modify the bytecode of loaded classes to
14   * enforce contracts at runtime.  The <code>runInstrumented(String,
15   * String []) method may be used to programatically run a class with
16   * contracts enabled.
17   *
18   * If specified, the instrumentation file controls the instrumentation
19   * level of each class in the system.  The available instrumentation
20   * levels are:
21   *
22   * <pre>
23   *   None - No contracts checked.
24   *   Pre  - Preconditions checked.
25   *   Post - Preconditions and postconditions checked.
26   *   All  - Preconditions, postconditions, and invariants checked.
27   * </pre>
28   *
29   * The instrumentation file contains class names followed by
30   * instrumentation levels, and separated by whitespace.  For example:
31   *
32   * <pre>
33   *   *                                      none
34   *   edu.*                                  pre
35   *   edu.ucsb.ccs.jcontractor.jInstrument   all
36   * </pre>
37   *
38   * This file says the the jInstrument class should be instrumented
39   * completetly and the other classes in edu and all subpackages should
40   * have precondition checks.  Wildcard matching works as in Java
41   * import statements, except that the wildcard matches any class in
42   * the package or any subpackage.  More specific filters override
43   * general filters (edu.ccs.jcontractor.jInstrument overrides edu.*).
44   *
45   * If you would prefer to instrument a class and save the instrumented
46   * bytecode so that it may be run without jContractor, take a look at
47   * the jInstrument class.
48   *
49   * <pre>
50   *  Usage: jContractor [-options] class [args]
51   *
52   *  Options:
53   *     -f <file>          Specify the instrumentation file.
54   *     -v, --verbose      Enable verbose logging.  Prints name of each
55   *                        class as it is instrumented.
56   *     -e, --version      Print version number and exit.
57   * </pre>
58   *
59   * @see jInstrument
60   * @see jContractorClassLoader
61   *
62   * @author Parker Abercrombie
63   * @author Murat Karaorman
64   */
65  
66  public class jContractor {
67  
68    /**
69     * Usage message to be printed if the command line arguments do not
70     * match the specification.
71     */
72    public static final String USAGE_MESSAGE =
73        "Usage: jContractor [-options] class [args]\n\n"
74      + "Options:\n"
75      + "  -f <file>    \t\t\t Specify the instrumentation file.\n"
76      + "  -n, --none <class or package>  Suppresses instrumentation of the\n"
77      + "                                 specified class(es).\n"
78      + "  -p, --pre <class or package>   Instruments the specified\n"
79      + "                                 class(es) for preconditions\n"
80      + "                                 checks.\n"
81      + "  -o, --post <class or package>  Instruments the specified class(es) for\n"
82      + "                                 precondition and postcondition checks.\n"
83      + "  -a, --all <class or package>   Instruments the specified class(es) for\n"
84      + "                                 all contract checks.\n"
85      + "  -v, --verbose \t\t Enable verbose logging.  Prints name of each \n"
86      + "                \t\t class as it is instrumented.\n"
87      + "  -e, --version \t\t Print version number and exit.\n";
88  
89    /**
90     * Constant for the version number that is printed when the
91     * --version command line argument is given.
92     */
93    public static final String VERSION = "jContractor version 0.1";
94  
95    /**
96     * Run a class with contracts enabled.  This method will replace the
97     * default class loader with a jContractorClassLoader, and run the
98     * code.  This method uses a default instance of jInstrument, and
99     * checks all contracts on all classes.
100    *
101    * @param className the name of the class to run.  The class must
102    *                  exist on the class path, and define a
103    *                  <code>main(String[])</code>.
104    * @param args command line arguments to pass to the
105    *             <code>main(String[])</code> method of the invoked
106    *             class.
107    */
108   public static void runInstrumented (String classname,
109                                       String [] args) throws Throwable {
110     runInstrumented(classname, args, new jInstrument());
111   }
112 
113   /**
114    * Run a class with contracts enabled, using the specified instance
115    * of jInstrument.  This method will replace the default class
116    * loader with a jContractorClassLoader, and run the code.
117    *
118    * @param className the name of the class to run.  The class must
119    *                  exist on the class path, and define a
120    *                  <code>main(String[])</code>.
121    * @param args command line arguments to pass to the
122    *             <code>main(String[])</code> method of the invoked
123    *             class.
124    * @param instrumentor an instance of jInstrument to use to
125    *                     instrument classes.
126    */
127   public static void runInstrumented (String classname,
128                                       String [] args,
129                                       jInstrument instrumentor) throws Throwable {
130     try {
131       jContractorClassLoader classLoader = new jContractorClassLoader(instrumentor);
132       Method m;
133 
134       Class instrumentedClass = classLoader.loadClass(classname);
135 
136       // Call the main() method of the target class
137       // pass cmd-line args to main
138       m = instrumentedClass.getMethod("main",
139                                       new Class[] { args.getClass() });
140 
141       m.invoke(null, new Object[] { args });
142     } catch (RuntimeException e) {e.printStackTrace();
143       // This is thrown by jContractorClassLoader.loadClass when an
144       // instrumentation problem occurs.
145       System.err.println("jContractor execution aborted: "
146                          + e.getMessage());
147     } catch (InvocationTargetException e) {
148       // If the invoked class threw an exception, rethrow the
149       // exception.  This is probably more useful to clients than an
150       // InvocationTargetException.
151       throw e.getTargetException();
152     }
153   }
154 
155   /**
156    * @deprecated Use edu.ucsb.ccs.jaqual.Logical.implies instead.
157    */
158   public static boolean implies (boolean op1, boolean op2) {
159     return !op1 || op2;
160   }
161 
162   /**
163    * Main entry point to the application.  This program requires one
164    * command line argument, the name of a class to run.  jContractor
165    * will replace the default class loader with a
166    * jContractorClassLoader, and run the program.
167    *
168    * @param args command line argument.  The first should be the name
169    *             of a class to run.  The class must exist on the class
170    *             path, and define a <code>main(String [])</code>
171    *             method.
172    */
173   public static void main (String args[]) {
174     Options opts = new Options();
175     CommandLine cmdLine;
176     String classname;
177 
178     String instrumentationFile = null, packageList = null;
179     CompositeInstrumentationFilter filter = new CompositeInstrumentationFilter();
180     boolean useDefaultInstrumentationFilter = true;    
181 
182     jInstrument instrumentor = new jInstrument();
183 
184     try {
185       opts.addOption('v', "verbose", false, "Verbose");
186       opts.addOption('e', "version", false, "Version");
187       opts.addOption('f', true, "Instrumentation file");
188       opts.addOption('n', "none", true, "No instrumentation");
189       opts.addOption('p', "pre", true, "Precondition level instrumentation");
190       opts.addOption('o', "post", true, "Postcondition level instrumentation");
191       opts.addOption('a', "all", true, "All level instrumentation");
192     } catch (DuplicateOptionException e) {
193       System.out.println("edu.ucsb.ccs.jcontractor.jContractor.main(): " + e);
194     }
195 
196     try {
197       cmdLine = opts.parse(args);
198       instrumentor.setVerbose(cmdLine.optIsSet('v'));
199 
200       // Parse the instrumentation file.
201       instrumentationFile = cmdLine.getOptValue('f');
202       if (instrumentationFile != null) {
203         useDefaultInstrumentationFilter = false;
204         jInstrument.parseInstrumentationFile(instrumentationFile, filter);
205       }
206 
207       packageList = cmdLine.getOptValue('n'); // --none
208       if (packageList != null) {
209         useDefaultInstrumentationFilter = false;
210         jInstrument.parseInstrumentationList(packageList,
211                                              InstrumentationFilter.NONE,
212                                              filter);
213       }
214 
215       packageList = cmdLine.getOptValue('p'); // --pre
216       if (packageList != null) {
217         useDefaultInstrumentationFilter = false;
218         jInstrument.parseInstrumentationList(packageList,
219                                              InstrumentationFilter.PRE,
220                                              filter);
221       }
222 
223       packageList = cmdLine.getOptValue('o'); // --post
224       if (packageList != null) {
225         useDefaultInstrumentationFilter = false;
226         jInstrument.parseInstrumentationList(packageList,
227                                              InstrumentationFilter.POST,
228                                              filter);
229       }
230 
231       packageList = cmdLine.getOptValue('a'); // --all
232       if (packageList != null) {
233         useDefaultInstrumentationFilter = false;
234         jInstrument.parseInstrumentationList(packageList,
235                                              InstrumentationFilter.ALL,
236                                              filter);
237       }
238 
239       // Set a specialized instrumentation filter, if neccessary.
240       if (!useDefaultInstrumentationFilter) {
241         instrumentor.setInstrumentationFilter(filter);
242       }
243 
244       // If the --version option is present, just print the version
245       // number and exit.  Otherwise actually instrument stuff.
246       if (cmdLine.optIsSet('e')) {
247         System.out.println(VERSION);
248       } else if (!cmdLine.getArgs().isEmpty()) {
249         Iterator iter = cmdLine.getArgs().iterator();
250         classname = (String) iter.next();
251 
252         // Create an array to hold the arguments passed to the invoked
253         // program.  These arguments are everything after the class
254         // name on the command line.
255         Vector argsVector = new Vector();
256         while (iter.hasNext()) {
257           argsVector.addElement((String) iter.next());
258         }
259 
260         // Convert the vector to a String []
261         String [] cargs = new String [argsVector.size()];
262         for (int i = 0; i < argsVector.size(); i++) {
263           cargs[i] = (String) argsVector.elementAt(i);
264         }
265 
266         runInstrumented(classname, cargs, instrumentor);
267       } else {
268         throw new MissingArgumentException("Class name missing");
269       }
270     } catch (MissingArgumentException e) {
271       System.err.println(USAGE_MESSAGE);
272       System.exit(1);
273     } catch (UnrecognizedOptionException e) {
274       System.err.println(USAGE_MESSAGE);
275       System.exit(1);
276     } catch (Throwable t) {
277       System.out.println("jContractor Exception occured!");
278       t.printStackTrace();
279     }
280   }
281 }