001    package edu.rice.cs.cunit;
002    
003    import edu.rice.cs.cunit.instrumentors.IInstrumentationStrategy;
004    import edu.rice.cs.cunit.util.Debug;
005    
006    import java.io.FileNotFoundException;
007    import java.io.FileOutputStream;
008    import java.io.PrintStream;
009    import java.lang.reflect.Method;
010    import java.util.ArrayList;
011    import java.util.List;
012    
013    /**
014     * @author Mathias Ricken
015     */
016    public abstract class ACUnitRun {
017        /**
018         * Class to load and execute.
019         */
020        protected String _className;
021    
022        /**
023         * Arguments to pass to the class main method.
024         */
025        protected String[] _progArgs;
026    
027        /**
028         * String with syntax description
029         */
030        protected static final String OPTIONS_FORMAT = "[-h] [-d] [-output <txt>] [-ns] [-backup] [-i <iclass>] [-X <s>] <class> [args...]";
031    
032        /**
033         * Do not save instrumented class files?
034         */
035        protected boolean _noSaveInstrumented = false;
036    
037        /**
038         * Make backups of original files?
039         */
040        protected boolean _makeBackups = false;
041    
042        /**
043         * Instrumentor class name.
044         */
045        protected String _instrumentorClassName = getDefaultInstrumentorName();
046    
047        /**
048         * List of parameters to the instrumentors.
049         */
050        protected List<String> _parameters = new ArrayList<String>();
051    
052        /**
053         * Print a help message to the specified stream.
054         * @param out output stream
055         */
056        protected static void help(PrintStream out) {
057            //           ---------1---------2---------3---------4---------5---------6---------7---------8
058            out.println("Flags : "+ OPTIONS_FORMAT);
059            out.println("-h                Show this help");
060            out.println("-d                Debug output");
061            out.println("-output <txt>     Debug output to file <txt>");
062            out.println("-ns               Do not save instrumented class files");
063            out.println("-backup           Make backups of original class files (only if no -nw)");
064            out.println("-i <iclass>       Specify <iclass> as instrumentor class name");
065            out.println("-X <s>            Pass <s> as parameter to instrumentors; may be repeated");
066            out.println("<class> [args...] Class file whose main method to execute, and arguments.");
067        }
068    
069        /**
070         * Read the command line arguments or ask for them in a dialog.
071         *
072         * @param args command line arguments
073         */
074        protected void readArgs(String[] args) {
075            if (args.length == 0) {
076                help(System.err);
077                System.exit(1);
078            }
079    
080            int argIndex = 0;
081            while((argIndex<args.length) && (args[argIndex].startsWith("-"))) {
082                final String a = args[argIndex];
083                if (a.equalsIgnoreCase("-?") || a.equalsIgnoreCase("-h")) {
084                    help(System.out);
085                    System.exit(1);
086                }
087                else if (a.equals("-nw")) {
088                    _noSaveInstrumented = true;
089                }
090                else if (a.equals("-backup")) {
091                    _makeBackups = true;
092                }
093                else if (a.equals("-d")) {
094                    Debug.out.setDebug(true);
095                }
096                else if (a.equals("-output")) {
097                    if (argIndex + 1 > args.length) {
098                        System.err.println("Error: <txt> file parameter missing.");
099                        help(System.err);
100                        System.exit(1);
101                    }
102                    String name = args[++argIndex];
103                    try {
104                        FileOutputStream debugOut = new FileOutputStream(name);
105                        Debug.out.setOutput(new PrintStream(debugOut, true));
106                        Debug.out.setDebug(true);
107                    }
108                    catch(FileNotFoundException e) {
109                        System.err.println("Error: Could not open <txt> file " + name + " for output.");
110                        System.exit(1);
111                    }
112                }
113                else if (a.equals("-i")) {
114                    if (argIndex + 1 > args.length) {
115                        System.err.println("Error: <iclass> file parameter missing.");
116                        help(System.err);
117                        System.exit(1);
118                    }
119                    _instrumentorClassName = args[++argIndex];
120                    if (_instrumentorClassName.indexOf('.') < 0) {
121                        _instrumentorClassName = FileInstrumentor.INSTRUMENTOR_PACKAGE_PREFIX + _instrumentorClassName;
122                    }
123                }
124                else if (a.equals("-X")) {
125                    if (argIndex + 1 > args.length) {
126                        System.err.println("Error: <s> parameter missing.");
127                        help(System.err);
128                        System.exit(1);
129                    }
130                    _parameters.add(args[++argIndex]);
131                }
132                ++argIndex;
133            }
134    
135            if (_noSaveInstrumented && _makeBackups) {
136                System.err.println("Error: -backup may only be specified without -ns.");
137                System.exit(1);
138            }
139    
140            if (argIndex>=args.length) {
141                System.err.println("Error: <class> missing");
142                System.exit(1);
143            }
144    
145            _className = args[argIndex];
146    
147            _progArgs = new String[args.length - 1 - argIndex];
148            System.arraycopy(args, 1, _progArgs, 0, _progArgs.length);
149        }
150    
151        /**
152         * Main method.
153         *
154         * @param args command line arguments
155         */
156        protected void run(String[] args) {
157            try {
158                readArgs(args);
159    
160                IInstrumentationStrategy itor = null;
161                try {
162                    @SuppressWarnings("unchecked") Class<IInstrumentationStrategy> c = (Class<IInstrumentationStrategy>)Class
163                        .forName(_instrumentorClassName);
164                    itor = c.getConstructor(List.class).newInstance(_parameters);
165                }
166                catch(NoSuchMethodException e) {
167                    try {
168                        @SuppressWarnings("unchecked") Class<IInstrumentationStrategy> c
169                            = (Class<IInstrumentationStrategy>)Class.forName(_instrumentorClassName);
170                        itor = c.getConstructor().newInstance();
171                    }
172                    catch(Throwable e2) {
173                        e2.printStackTrace(Debug.out);
174                        System.exit(1);
175                    }
176                }
177                catch(Throwable e2) {
178                    e2.printStackTrace(Debug.out);
179                    System.exit(1);
180                }
181    
182                InstrumentingClassLoader classLoader = new InstrumentingClassLoader(new IInstrumentationStrategy[]{itor});
183                classLoader.setSaveInstrumented(!_noSaveInstrumented);
184                classLoader.setMakeBackups(_makeBackups);
185    
186                Class<?> cls = classLoader.loadClass(_className, true);
187    
188                Debug.out.println(System.getProperty("line.separator") + System.getProperty("line.separator") +
189                    System.getProperty("line.separator") +
190                    "---------------------------------------------------------------------");
191    
192                cls.newInstance();
193    
194                Class mainArgType[] = {(new String[0]).getClass()};
195                Method main = cls.getMethod("main", mainArgType);
196    
197                Object argsArray[] = {_progArgs};
198    
199                main.invoke(null, argsArray);
200            }
201            catch(Exception e) {
202                e.printStackTrace();
203                if (null!=e.getCause()) {
204                    System.err.println("Cause:");
205                    e.getCause().printStackTrace();
206                }
207            }
208        }
209    
210        /**
211         * Abstract method deciding what instrumentor to run by default.
212         * @return the default name of the instrumentor.
213         */
214        public abstract String getDefaultInstrumentorName();
215    }