Confdump Agent  1.4.0
Options.cpp
Go to the documentation of this file.
00001 /* 
00002  * Confdump-Agent - Dump static and runtime system configuration
00003  * Copyright (C) 2009-2012  Straton IT, SAS
00004  * 
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  * 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include <iostream>
00019 #include <vector>
00020 
00021 #include "QFile"
00022 #include "QTextStream"
00023 
00024 #include "boost/foreach.hpp"
00025 #include "boost/bind.hpp"
00026 #include "boost/program_options.hpp"
00027 #include "boost/program_options/cmdline.hpp"
00028 namespace po = boost::program_options;
00029 namespace pos = boost::program_options::command_line_style;
00030 
00031 #include "Confdump/Options.hpp"
00032 #include "Confdump/RuntimeError.hpp"
00033 #include "Confdump/DumperFactory.hpp"
00034 
00035 using std::vector;
00036 using std::string;
00037 using boost::bind;
00038 
00039 namespace Confdump
00040 {
00041 
00042 Options::Options( int argc, char **argv, std::ostream &out )
00043 {
00044     po::options_description gettingHelp( tr( "Getting help" ).toLocal8Bit().constData() );
00045     gettingHelp.add_options()
00046         ( "help,h", tr( "This information", "--help" ).toLocal8Bit().constData() )
00047         ( "help-tables",
00048             tr( "displays a list of tables that can be queried and exits"
00049                                 " (can be combined with --output-file)" ).toLocal8Bit().constData() )
00050     ;
00051 
00052     po::options_description select( tr( "Configuration selection" ).toLocal8Bit().constData() );
00053     select.add_options()
00054         ( "table", po::value< vector<string> >()->notifier( bind( &Options::setTables, this, _1 ) ),
00055             tr( "tables to query (can be specified multiple times); format: [dumper.]table" ).toLocal8Bit().constData() )
00056         ( "tables-from", po::value< string >()->notifier( bind( &Options::readTablesFrom, this, _1 ) ),
00057             tr( "read a list of tables to query from this file" ).toLocal8Bit().constData() )
00058     ;
00059 
00060     po::options_description dumpers( tr( "Extra dumpers" ).toLocal8Bit().constData() );
00061     dumpers.add_options()
00062         ( "add-dumper", po::value< vector<string> >()->notifier( bind( &Options::setDumpers, this, _1 ) ),
00063             tr( "instanciate a new Dumper with a given alias (can be specified mutiple times); "
00064                 "format: alias=Dumper" ).toLocal8Bit().constData() )
00065         ( "dumper-arg", po::value< vector<string> >()->notifier( bind( &Options::setDumperArgs, this, _1 ) ),
00066             tr( "set an option on an instanciated Dumper (can be specified mutiple times); "
00067                 "format: alias.option=value" ).toLocal8Bit().constData() )
00068     ;
00069 
00070     po::options_description output( tr( "Output" ).toLocal8Bit().constData() );
00071     output.add_options()
00072         /*( "verbose,v", po::value< string >()->notifier( bind( &Options::setVerbosity, this, _1 ) )
00073                                             ->default_value( "info" )->implicit_value( "debug" ),
00074             tr( "sets verbosity to one of: trace, debug, info, warn, error" ).toLocal8Bit().constData() )*/
00075         ( "output-format", po::value< string >()->notifier( bind( &Options::setOutputFormat, this, _1 ) )
00076                                                 ->default_value( "text" ),
00077             tr( "sets output format to one of: text, xml" ).toLocal8Bit().constData() )
00078         ( "output-file", po::value< string >()->notifier( bind( &Options::setOutputFile, this, _1 ) ),
00079             tr( "output to a file instead of standard output" ).toLocal8Bit().constData() )
00080     ;
00081 
00082     po::options_description allOptions( tr(
00083         "\n"
00084         CONFDUMP_VERSION " - Dump static and runtime system configuration\n"
00085         "Copyright (C) 2009-2012  Straton IT, SAS\n"
00086         "More information at http://confdump.sf.net/\n"
00087         "\n"
00088         "This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
00089         "are welcome to redistribute it under the terms of the GPL version 3.\n"
00090         "\n"
00091         "Command-line options and arguments", "options description" ).toLocal8Bit().constData() );
00092     allOptions.add( gettingHelp ).add( select ).add( dumpers ).add( output );
00093 
00094     pos::style_t style = static_cast<pos::style_t> (
00095         pos::allow_long |           // --foo
00096         pos::long_allow_next |      // --foo bar
00097         pos::allow_short |          // -f
00098         pos::allow_dash_for_short | // -f
00099         pos::short_allow_next |     // -f bar
00100         pos::allow_sticky );        // -fF same as -f -F
00101 
00102     po::variables_map vm;
00103     po::store( po::parse_command_line( argc, argv, allOptions, style ), vm );
00104     po::notify( vm );    
00105 
00106     if ( vm.count( "help" ) )
00107     {
00108         operatingMode_ = HelpMode;
00109         out << allOptions << std::endl;
00110         #if CD_WIN32
00111         out << "WMI dumper options:\n";
00112         out << "  namespace (sets the WMI namespace to query, defaults to ROOT\\CIMv2)\n";
00113         out << "\n";
00114         out << "Win32 dumper options: (none)\n";
00115         #elif CD_UNIX
00116         //out << "Linux dumper options: none\n";
00117         #endif
00118         out << std::endl;
00119     }
00120     else if ( vm.count( "help-tables" ) )
00121     {
00122         operatingMode_ = HelpTablesMode;
00123     }
00124     else
00125     {
00126         operatingMode_ = NormalMode;
00127     }
00128 }
00129 
00130 Options::~Options()
00131 {
00132 }
00133 
00134 void Options::setVerbosity( const std::string &value )
00135 {
00136     QString level( QString::fromLocal8Bit( value.c_str() ).toLower() );
00137     if ( level == "trace" )
00138         logLevel_ = Trace;
00139     else if ( level == "debug" )
00140         logLevel_ = Debug;
00141     else if ( level == "info" || level == "information" )
00142         logLevel_ = Info;
00143     else if ( level == "warn" || level == "warning" )
00144         logLevel_ = Warning;
00145     else if ( level == "error" )
00146         logLevel_ = Error;
00147     else
00148         throw RuntimeError( tr( "Unknown verbosity level: '%1'" ).arg( level ) );
00149 }
00150 
00151 void Options::setOutputFormat( const std::string &value )
00152 {
00153     QString format( QString::fromLocal8Bit( value.c_str() ).toLower() );
00154     if ( format == "text" )
00155         outputFormat_ = TextFormat;
00156     else if ( format == "xml" )
00157         outputFormat_ = XmlFormat;
00158     else
00159         throw RuntimeError( tr( "Unknown output format: '%1'" ).arg( format ) );
00160 }
00161 
00162 void Options::setOutputFile( const std::string &value )
00163 {
00164     outputFile_ = QString::fromLocal8Bit( value.c_str() );
00165 }
00166 
00167 namespace
00168 {
00169 
00170 Options::TableList::value_type parseTable( QString qualifiedTable )
00171 {
00172         if ( qualifiedTable.count( '.' ) == 1 )
00173         {
00174                 QString alias = qualifiedTable.section( '.', 0, 0 );
00175                 QString table = qualifiedTable.section( '.', -1, -1 );
00176                 return std::make_pair( alias, table );
00177         }
00178         else
00179         {
00180                 return std::make_pair( "main", qualifiedTable );
00181         }
00182 }
00183 
00184 }
00185 
00186 void Options::setTables( const std::vector< std::string > &raw_tables )
00187 {
00188     TableList tables;
00189     BOOST_FOREACH( const std::string &raw_table, raw_tables )
00190     {
00191         QString qualifiedTable = QString::fromLocal8Bit( raw_table.c_str() );
00192         tables << parseTable( qualifiedTable );
00193     }
00194     tables_ = tables;
00195 }
00196 
00197 void Options::setDumpers( const std::vector< std::string > &raw_dumpers )
00198 {
00199     BOOST_FOREACH( const std::string &raw_dumper, raw_dumpers )
00200     {
00201         QString dumper = QString::fromLocal8Bit( raw_dumper.c_str() );
00202         QString alias = dumper.section( '=', 0, 0 ).toLower();
00203         QString implementation = dumper.section( '=', 1, -1 ).toLower();
00204         if ( alias.isEmpty() || implementation.isEmpty() )
00205             throw RuntimeError( "Invalid --add-dumper argument (must be alias=Dumper)" );
00206         dumperAliases_[alias] = implementation;
00207     }
00208 }
00209 
00210 void Options::setDumperArgs( const std::vector< std::string > &raw_args )
00211 {
00212     BOOST_FOREACH( const std::string &raw_arg, raw_args )
00213     {
00214         QString arg = QString::fromLocal8Bit( raw_arg.c_str() );   // alias.key=value
00215         QString qualifiedKey = arg.section( '=', 0, 0 ).toLower(); // alias.key
00216         std::pair<QString, QString> key = parseTable( qualifiedKey );
00217         QString value = arg.section( '=', 1, -1 );
00218         if ( key.first.isEmpty() || key.second.isEmpty() || value.isEmpty() )
00219             throw RuntimeError( "Invalid --dumper-arg argument (must be alias.key=value)" );
00220         dumperArguments_[key.first][key.second] = value;
00221     }
00222 }
00223 
00224 std::map< QString, DumperSpecification > Options::dumperSpecifications() const
00225 {
00226     // Merge dumperAliases_ + dumperArguments_
00227     std::map< QString, DumperSpecification > specifications;
00228 
00229     BOOST_FOREACH( DumperAliases::value_type dumper, dumperAliases_ )
00230     {
00231         DumperSpecification spec;
00232         QString alias = dumper.first;
00233         spec.name = dumper.second;
00234         spec.parameters = dumperArguments_[alias];
00235         specifications[alias] = spec;
00236     }
00237 
00238     // Check for unused arguments
00239     BOOST_FOREACH( DumperArguments::value_type args, dumperArguments_ )
00240     {
00241         QString alias = args.first;
00242         if ( specifications.find( alias ) == specifications.end() )
00243             throw RuntimeError( "Undefined alias used in --dumper-arg: " + alias );
00244     }
00245 
00246     return specifications;
00247 }
00248 
00249 void Options::readTablesFrom( const std::string &fileName8b )
00250 {
00251     QString fileName( QString::fromLocal8Bit( fileName8b.c_str() ) );
00252     QFile file( fileName );
00253     if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
00254         throw RuntimeError( "Couldn't open "+fileName+" for reading: "+file.error() );
00255 
00256     QTextStream in( &file );
00257     while ( !in.atEnd() )
00258     {
00259         QString line = in.readLine();
00260         if ( !line.isEmpty() && line[0] != '#' )
00261             tables_ << parseTable( line );
00262     }
00263 }
00264 
00265 Options::TableList Options::tables() const
00266 {
00267     return tables_;
00268 }
00269 
00270 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends