Home | History | Annotate | Download | only in instr
      1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
      2  *
      3  * This program and the accompanying materials are made available under
      4  * the terms of the Common Public License v1.0 which accompanies this distribution,
      5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
      6  *
      7  * $Id: instrCommand.java,v 1.1.1.1.2.1 2004/07/16 23:32:04 vlad_r Exp $
      8  */
      9 package com.vladium.emma.instr;
     10 
     11 import java.io.IOException;
     12 
     13 import com.vladium.util.ClassLoaderResolver;
     14 import com.vladium.util.args.IOptsParser;
     15 import com.vladium.util.asserts.$assert;
     16 import com.vladium.emma.Command;
     17 import com.vladium.emma.IAppConstants;
     18 import com.vladium.emma.IAppErrorCodes;
     19 import com.vladium.emma.EMMARuntimeException;
     20 
     21 // ----------------------------------------------------------------------------
     22 /**
     23  * @author Vlad Roubtsov, (C) 2003
     24  */
     25 public
     26 final class instrCommand extends Command
     27 {
     28     // public: ................................................................
     29 
     30     public instrCommand (final String usageToolName, final String [] args)
     31     {
     32         super (usageToolName, args);
     33 
     34         m_outMode = InstrProcessor.OutMode.OUT_MODE_COPY; // default
     35     }
     36 
     37     public synchronized void run ()
     38     {
     39         ClassLoader loader;
     40         try
     41         {
     42             loader = ClassLoaderResolver.getClassLoader ();
     43         }
     44         catch (Throwable t)
     45         {
     46             loader = getClass ().getClassLoader ();
     47         }
     48 
     49         try
     50         {
     51             // process 'args':
     52             {
     53                 final IOptsParser parser = getOptParser (loader);
     54                 final IOptsParser.IOpts parsedopts = parser.parse (m_args);
     55 
     56                 // check if usage is requested before checking args parse errors etc:
     57                 {
     58                     final int usageRequestLevel = parsedopts.usageRequestLevel ();
     59 
     60                     if (usageRequestLevel > 0)
     61                     {
     62                         usageexit (parser, usageRequestLevel, null);
     63                         return;
     64                     }
     65                 }
     66 
     67                 final IOptsParser.IOpt [] opts = parsedopts.getOpts ();
     68 
     69                 if (opts == null) // this means there were args parsing errors
     70                 {
     71                     parsedopts.error (m_out, STDOUT_WIDTH);
     72                     usageexit (parser, IOptsParser.SHORT_USAGE, null);
     73                     return;
     74                 }
     75 
     76                 // process parsed args:
     77                 try
     78                 {
     79                     for (int o = 0; o < opts.length; ++ o)
     80                     {
     81                         final IOptsParser.IOpt opt = opts [o];
     82                         final String on = opt.getCanonicalName ();
     83 
     84                         if (! processOpt (opt))
     85                         {
     86                             if ("ip".equals (on))
     87                             {
     88                                 m_instrpath = getListOptValue (opt, PATH_DELIMITERS, true);
     89                             }
     90                             else if ("d".equals (on))
     91                             {
     92                                 m_outDirName = opt.getFirstValue ();
     93                             }
     94                             else if ("out".equals (on))
     95                             {
     96                                 m_outFileName = opt.getFirstValue ();
     97                             }
     98                             else if ("merge".equals (on))
     99                             {
    100                                 m_outDataMerge = getOptionalBooleanOptValue (opt) ? Boolean.TRUE : Boolean.FALSE;
    101                             }
    102                             else if ("ix".equals (on))
    103                             {
    104                                 // note: this allows path delimiter in the pattern list as well
    105                                 m_ixpath = getListOptValue (opt, COMMA_DELIMITERS, true);
    106                             }
    107                             else if ("m".equals (on))
    108                             {
    109                                 final String ov = opt.getFirstValue ();
    110 
    111                                 final InstrProcessor.OutMode outMode = InstrProcessor.OutMode.nameToMode (ov);
    112                                 if (outMode == null)
    113                                 {
    114                                     usageexit (parser, IOptsParser.SHORT_USAGE,
    115                                         "invalid '" + opts [o].getName () + "' option value: " + ov);
    116                                     return;
    117                                 }
    118                                 m_outMode = outMode;
    119                             }
    120                         }
    121                     }
    122 
    123                     // user '-props' file property overrides:
    124 
    125                     if (! processFilePropertyOverrides ()) return;
    126 
    127                     // process prefixed opts:
    128 
    129                     processCmdPropertyOverrides (parsedopts);
    130                 }
    131                 catch (IOException ioe)
    132                 {
    133                     throw new EMMARuntimeException (IAppErrorCodes.ARGS_IO_FAILURE, ioe);
    134                 }
    135 
    136                 // handle cmd line-level defaults:
    137                 {
    138                     if ($assert.ENABLED) $assert.ASSERT (m_outMode != null, "m_outMode not set");
    139 
    140                     if ((m_outMode != InstrProcessor.OutMode.OUT_MODE_OVERWRITE) && (m_outDirName == null))
    141                     {
    142                         usageexit (parser, IOptsParser.SHORT_USAGE,
    143                             "output directory must be specified for '" + m_outMode + "' output mode");
    144                         return;
    145                     }
    146                 }
    147             }
    148 
    149             // run the instrumentor:
    150             {
    151                 final InstrProcessor processor = InstrProcessor.create ();
    152                 processor.setAppName (IAppConstants.APP_NAME); // for log prefixing
    153 
    154                 processor.setInstrPath (m_instrpath, true); // TODO: an option to set 'canonical'?
    155                 processor.setInclExclFilter (m_ixpath);
    156                 $assert.ASSERT (m_outMode != null, "m_outMode not set");
    157                 processor.setOutMode (m_outMode);
    158                 processor.setInstrOutDir (m_outDirName);
    159                 processor.setMetaOutFile (m_outFileName);
    160                 processor.setMetaOutMerge (m_outDataMerge);
    161                 processor.setPropertyOverrides (m_propertyOverrides);
    162 
    163                 processor.run ();
    164             }
    165         }
    166         catch (EMMARuntimeException yre)
    167         {
    168             // TODO: see below
    169 
    170             exit (true, yre.getMessage (), yre, RC_UNEXPECTED); // does not return
    171             return;
    172         }
    173         catch (Throwable t)
    174         {
    175             // TODO: embed: OS/JVM fingerprint, build #, etc
    176             // TODO: save stack trace in a file and prompt user to send it to ...
    177 
    178             exit (true, "unexpected failure: ", t, RC_UNEXPECTED); // does not return
    179             return;
    180         }
    181 
    182         exit (false, null, null, RC_OK);
    183     }
    184 
    185     // protected: .............................................................
    186 
    187 
    188     protected void initialize ()
    189     {
    190         super.initialize ();
    191     }
    192 
    193     protected String usageArgsMsg ()
    194     {
    195         return "[options]";
    196     }
    197 
    198     // package: ...............................................................
    199 
    200     // private: ...............................................................
    201 
    202 
    203     private String [] m_instrpath;
    204     private String [] m_ixpath;
    205     private String m_outDirName;
    206     private String m_outFileName;
    207     private Boolean m_outDataMerge;
    208     private InstrProcessor.OutMode m_outMode;
    209 
    210 } // end of class
    211 // ----------------------------------------------------------------------------