(file) Return to OptionManager.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 karl  1.51 //%2006////////////////////////////////////////////////////////////////////////
  2 karl  1.42 //
  3 karl  1.46 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.42 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.46 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.47 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.51 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 karl  1.42 //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15            // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18            // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.51 // 
 21 karl  1.42 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22            // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24            // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27            // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31 a.arora 1.45 //
 32              // Author: Mike Brasher (mbrasher@bmc.com)
 33              //
 34              // Modified By: Karl Schopmeyer(k.schopmeyer@opengroup.org)
 35              //                 June 2001 - Extend help and print to include help description
 36              //                 Feb 2002 - ad IsTrue
 37              //              Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
 38 david.dillard 1.48 //              David Dillard, VERITAS Software Corp.
 39                    //                  (david.dillard@veritas.com)
 40 a.arora       1.45 //
 41                    //%/////////////////////////////////////////////////////////////////////////////
 42                    
 43                    #include <cstdlib>
 44                    #include <cctype>
 45                    #include <fstream>
 46                    #include <cstdio>
 47                    #include "OptionManager.h"
 48                    #include "FileSystem.h"
 49                    
 50                    PEGASUS_USING_STD;
 51                    
 52                    PEGASUS_NAMESPACE_BEGIN
 53                    
 54                    ////////////////////////////////////////////////////////////////////////////////
 55                    //
 56                    // TODO: expand variables in the configuration file. For example:
 57                    //
 58                    //     provider_dir = "${home}/providers"
 59                    //
 60                    ////////////////////////////////////////////////////////////////////////////////
 61 a.arora       1.45 
 62                    ////////////////////////////////////////////////////////////////////////////////
 63                    //
 64                    // Option
 65                    //
 66                    ////////////////////////////////////////////////////////////////////////////////
 67                    
 68                    const Array<String>& Option::getDomain() const
 69                    {
 70                        return _domain;
 71                    }
 72                    
 73                    void Option::setDomain(const Array<String>& domain)
 74                    {
 75                        _domain = domain;
 76                    }
 77                    
 78                    ////////////////////////////////////////////////////////////////////////////////
 79                    //
 80                    // OptionManager
 81                    //
 82 a.arora       1.45 ////////////////////////////////////////////////////////////////////////////////
 83                    
 84                    OptionManager::OptionManager()
 85                    {
 86                    
 87                    }
 88                    
 89                    OptionManager::~OptionManager()
 90                    {
 91                        // Delete all options in the list:
 92                    
 93                        for (Uint32 i = 0; i < _options.size(); i++)
 94                    	delete _options[i];
 95                    }
 96                    
 97 david.dillard 1.48 void OptionManager::registerOption(Option* option)
 98 a.arora       1.45 {
 99                        if (!option)
100                    	throw NullPointer();
101                    
102                        if (lookupOption(option->getOptionName()))
103                    	throw OMDuplicateOption(option->getOptionName());
104                    
105                        _options.append(option);
106                    }
107                    
108                    
109                    void OptionManager::registerOptions(OptionRow* optionRow, Uint32 numOptions)
110                    {
111                        for (Uint32 i = 0; i < numOptions; i++)
112                        {
113                    	// Get option name:
114                    
115                    	if (!optionRow[i].optionName)
116                    	    throw NullPointer();
117                    
118                    	String optionName = optionRow[i].optionName;
119 a.arora       1.45 
120                    	// Get default value:
121                    
122                    	String defaultValue;
123                    
124                    	if (optionRow[i].defaultValue)
125                    	    defaultValue = optionRow[i].defaultValue;
126                    
127                    	// Get the required flag:
128                    
129                    	Boolean required = optionRow[i].required != 0;
130                    
131                    	// Get the type:
132                    
133                    	Option::Type type = optionRow[i].type;
134                    
135                    	// Get the domain:
136                    
137                    	Array<String> domain;
138                    
139                    	if (optionRow[i].domain)
140 a.arora       1.45 	{
141                    	    Uint32 domainSize = optionRow[i].domainSize;
142                    
143                    	    for (Uint32 j = 0; j < domainSize; j++)
144                    		domain.append(optionRow[i].domain[j]);
145                    	}
146                    
147                    	// Get commandLineOptionName:
148                    
149                    	String commandLineOptionName;
150                    
151                    	if (optionRow[i].commandLineOptionName)
152                    	    commandLineOptionName = optionRow[i].commandLineOptionName;
153                    
154                    	// get optionHelp Message String
155                    
156                    	String optionHelpMessage;
157                    
158                    	if (optionRow[i].optionHelpMessage)
159                    	    optionHelpMessage = optionRow[i].optionHelpMessage;
160                    
161 a.arora       1.45 	// Add the option:
162                    
163                    	Option* option = new Option(
164                    	    optionName,
165                    	    defaultValue,
166                    	    required,
167                    	    type,
168                    	    domain,
169                    	    commandLineOptionName,
170                    	    optionHelpMessage);
171                    
172                    	registerOption(option);
173                        }
174                    }
175                    
176                    void OptionManager::mergeCommandLine(int& argc, char**& argv, Boolean abortOnErr)
177                    {
178                        for (int i = 0; i < argc; )
179                        {
180                    	// Check for -option:
181                    
182 a.arora       1.45 	const char* arg = argv[i];
183                    
184                    	if (*arg == '-')
185                    	{
186                    	    // Look for the option:
187                    
188                    	    Option* option = _lookupOptionByCommandLineOptionName(arg + 1);
189                    
190                    	    if (!option)
191                    	    {
192                    		if (abortOnErr)
193                                    {
194 david.dillard 1.48                     throw OMMBadCmdLineOption(arg);
195 a.arora       1.45                 }
196                                    else
197                                    {
198                                        i++;
199                        		    continue;
200                                    }
201                    	    }
202                    
203                    	    // Get the option argument if any:
204                    
205                    	    const char* optionArgument = "true";
206                    
207                    	    if (option->getType() != Option::BOOLEAN)
208                    	    {
209                    		if (i + 1 == argc)
210                    		    throw OMMissingCommandLineOptionArgument(arg);
211                    
212                    		optionArgument = argv[i + 1];
213                    	    }
214                    
215                    	    // Validate the value:
216 a.arora       1.45 
217                    	    if (!option->isValid(optionArgument))
218                    		throw OMInvalidOptionValue(arg, optionArgument);
219                    
220                    	    // Set the value:
221                    
222                    	    option->setValue(optionArgument);
223                    
224                    	    // Remove the option and its argument from the command line:
225                    
226                    	    if (option->getType() == Option::BOOLEAN)
227                    	    {
228                    		memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));
229                    		argc--;
230                    	    }
231                    	    else
232                    	    {
233                    		memmove(&argv[i], &argv[i + 2], (argc-i-1) * sizeof(char*));
234                    		argc -= 2;
235                    	    }
236                    	}
237 a.arora       1.45 	else
238                    	    i++;
239                        }
240                    }
241                    
242                    void OptionManager::mergeFile(const String& fileName)
243                    {
244                       // Open the input file:
245                    #if defined(PEGASUS_OS_OS400)
246                        ifstream is(fileName.getCString(),PEGASUS_STD(_CCSID_T(1208)));
247                    #else
248                        ifstream is(fileName.getCString());
249                    #endif
250                    
251                        if (!is)
252                    	throw NoSuchFile(fileName);
253                    
254                        // For each line of the file:
255                    
256                        String line;
257                    
258 a.arora       1.45     for (Uint32 lineNumber = 1; GetLine(is, line); lineNumber++)
259                        {
260                    	// -- Get the identifier and value:
261                    
262                    	if (line[0] == '#')
263                    	    continue;
264                    
265                    	// Skip leading whitespace:
266                    
267                    	const Char16* p = line.getChar16Data();
268                    
269                    	while (*p && isspace(*p))
270                    	    p++;
271                    
272                    	if (!*p)
273                    	    continue;
274                    
275                    	if (*p == '#')
276                    	    continue;
277                    
278                    	// Get the identifier:
279 a.arora       1.45 
280                    	String ident;
281                    
282                    	if (!(isalpha(*p) || *p == '_'))
283                    	    throw OMConfigFileSyntaxError(fileName, lineNumber);
284                    
285                    	ident.append(*p++);
286                    
287                    	while (isalnum(*p) || *p == '_')
288                    	    ident.append(*p++);
289                    
290                    	// Skip whitespace after identifier:
291                    
292                    	while (*p && isspace(*p))
293                    	    p++;
294                    
295                    	// Expect an equal sign:
296                    
297                    	if (*p != '=')
298                    	    throw OMConfigFileSyntaxError(fileName, lineNumber);
299                    	p++;
300 a.arora       1.45 
301                    	// Skip whitespace after equal sign:
302                    
303                    	while (*p && isspace(*p))
304                    	    p++;
305                    
306                    	// Expect open quote:
307                    
308                    	if (*p != '"')
309                    	    throw OMConfigFileSyntaxError(fileName, lineNumber);
310                    	p++;
311                    
312                    	// Get the value:
313                    
314                    	String value;
315                    
316                    	while (*p && *p != '"')
317                    	{
318                    	    if (*p == '\\')
319                    	    {
320                    		p++;
321 a.arora       1.45 
322                    		switch (*p)
323                    		{
324 david.dillard 1.48 		    case 'n':
325                    			value.append('\n');
326 a.arora       1.45 			break;
327 david.dillard 1.48 
328 a.arora       1.45 		    case 'r':
329                    			value.append('\r');
330                    			break;
331                    
332                    		    case 't':
333                    			value.append('\t');
334                    			break;
335                    
336                    		    case 'f':
337                    			value.append('\f');
338                    			break;
339                    
340                    		    case '"':
341                    			value.append('"');
342                    			break;
343                    
344                    		    case '\0':
345                    			throw OMConfigFileSyntaxError(fileName, lineNumber);
346                    
347                    		    default:
348                    			value.append(*p);
349 a.arora       1.45 		}
350                    		p++;
351                    	    }
352                    	    else
353                    		value.append(*p++);
354                    	}
355                    
356                    
357                    	// Expect close quote:
358                    
359                    	if (*p != '"')
360                    	    throw OMConfigFileSyntaxError(fileName, lineNumber);
361                    	p++;
362                    
363                    	// Skip whitespace through end of line:
364                    
365                    	while (*p && isspace(*p))
366                    	    p++;
367                    
368                    	if (*p)
369                    	    throw OMConfigFileSyntaxError(fileName, lineNumber);
370 a.arora       1.45 
371                    	// Now that we have the identifier and value, merge it:
372                    
373                    	Option* option = (Option*)lookupOption(ident);
374                    
375                    	if (!option)
376                    	    throw OMUnrecognizedConfigFileOption(ident);
377                    
378                    	if (!option->isValid(value))
379                    	    throw OMInvalidOptionValue(ident, value);
380                    
381                    	option->setValue(value);
382                        }
383                    }
384                    
385                    void OptionManager::checkRequiredOptions() const
386                    {
387                        for (Uint32 i = 0; i < _options.size(); i++)
388                        {
389                    	const Option* option = _options[i];
390                    
391 a.arora       1.45 	if (option->getRequired() && !option->isResolved())
392                    	    throw OMMissingRequiredOptionValue(option->getOptionName());
393                        }
394                    }
395                    
396                    const Option* OptionManager::lookupOption(const String& name) const
397                    {
398                        for (Uint32 i = 0; i < _options.size(); i++)
399                        {
400                    	if (_options[i]->getOptionName() == name)
401                    	    return _options[i];
402                        }
403                    
404                        return 0;
405                    }
406                    
407                    Boolean OptionManager::lookupValue(const String& name, String& value) const
408                    {
409                        const Option* option = lookupOption(name);
410                    
411                        if (!option)
412 a.arora       1.45 	return false;
413                    
414                        value = option->getValue();
415                        return true;
416                    }
417                    
418                    Boolean OptionManager::lookupIntegerValue(const String& name, Uint32& value) const
419                    {
420                        //ATTN: KS P1 7 May 2002 - Add test for Integer type in om table.
421                        String valueString;
422                        if (lookupValue(name, valueString))
423                        {
424                    	value = atol(valueString.getCString());
425                    	return true;
426                        }
427                        else
428                        {
429                    	return false;
430                        }
431                    
432                    }
433 a.arora       1.45 
434 david.dillard 1.48 Boolean OptionManager::valueEquals(const String& name, const String& value)
435 a.arora       1.45     const
436                    {
437                        String optionString;
438                    
439                        return (lookupValue(name, optionString) && optionString == value) ? true : false;
440                    }
441                    
442                    Boolean OptionManager::isTrue(const String& name) const
443                    {
444 david.dillard 1.48     //ATTN: KS 7 May 2002 P3 Add test to confirm boolean type
445 a.arora       1.45     return valueEquals(name, "true") ? true: false;
446                    }
447                    /*  ATTN: P3 MB 2001 Buried this one for the moment to think about it.
448 david.dillard 1.48 Uint32 OptionManager::isStringInOptionMask(const String& option,
449                    					   const String& entry)
450 a.arora       1.45 {
451                        String optionString;
452                    
453                        if (lookupValue(name, optionString) && optionString == value)
454                    	if (optionString.find(entry)
455                    	    return 1;
456                        else
457                    	return PEG_NOT_FOUND;
458                    }
459                    */
460                    
461                    Option* OptionManager::_lookupOptionByCommandLineOptionName(const String& name)
462                    {
463                        for (Uint32 i = 0; i < _options.size(); i++)
464                        {
465                    	if (_options[i]->getCommandLineOptionName() == name)
466                    	    return _options[i];
467                        }
468                    
469                        return 0;
470                    }
471 a.arora       1.45 
472                    void OptionManager::print() const
473                    {
474                        for (Uint32 i = 0; i < _options.size(); i++)
475                        {
476                    	Option* option = _options[i];
477                    	cout << option->getOptionName() << "=\"";
478                    	cout << option->getValue() << "\" ";
479                    	cout << option->getOptionHelpMessage() << "\n";
480                        }
481                        cout << endl;
482                    }
483                    
484                    void OptionManager::printOptionsHelp() const
485                    {
486                        for (Uint32 i = 0; i < _options.size(); i++)
487                        {
488                    	Option* option = _options[i];
489                    	cout << " -";
490                    	cout << option->getCommandLineOptionName() << "  ";
491                    	cout << option->getOptionName() << ". ";
492 a.arora       1.45 	cout << option->getOptionHelpMessage();
493                            cout << ". Default(" << option->getDefaultValue() << ")\n";
494                        }
495                        cout << endl;
496                    
497                    }
498                    
499                    void OptionManager::printOptionsHelpTxt(const String& header, const String& trailer) const
500                    {
501                        cout << "\n" << header << "\n";
502                        printOptionsHelp();
503                        cout << trailer << "\n";
504                    }
505                    
506                    ////////////////////////////////////////////////////////////////////////////////
507                    //
508                    // Option
509                    //
510                    ////////////////////////////////////////////////////////////////////////////////
511                    
512                    Option::Option(
513 a.arora       1.45     const String& optionName,
514                        const String& defaultValue,
515                        Boolean required,
516                        Type type,
517                        const Array<String>& domain,
518                        const String& commandLineOptionName,
519                        const String& optionHelpMessage)
520                        :
521                        _optionName(optionName),
522                        _defaultValue(defaultValue),
523                        _value(defaultValue),
524                        _required(required),
525                        _type(type),
526                        _domain(domain),
527                        _commandLineOptionName(commandLineOptionName),
528                        _optionHelpMessage(optionHelpMessage),
529                        _resolved(false)
530                    {
531                        if (!isValid(_value))
532                    	throw OMInvalidOptionValue(_optionName, _value);
533                    }
534 a.arora       1.45 
535 david.dillard 1.48 Option::Option(const Option& x)
536 a.arora       1.45     :
537                        _optionName(x._optionName),
538                        _defaultValue(x._defaultValue),
539                        _value(x._value),
540                        _required(x._required),
541                        _type(x._type),
542                        _domain(x._domain),
543                        _commandLineOptionName(x._commandLineOptionName),
544                        _optionHelpMessage(x._optionHelpMessage)
545                    
546                    {
547                    }
548                    
549                    Option::~Option()
550                    {
551                    
552                    }
553                    
554                    Option& Option::operator=(const Option& x)
555                    {
556                        if (this != &x)
557 a.arora       1.45     {
558                    	_optionName = x._optionName;
559                    	_defaultValue = x._defaultValue;
560                    	_value = x._value;
561                    	_required = x._required;
562                    	_type = x._type;
563                    	_domain = x._domain;
564                    	_commandLineOptionName = x._commandLineOptionName;
565                    	_optionHelpMessage = x._optionHelpMessage;
566                        }
567                        return *this;
568                    }
569                    
570                    Boolean Option::isValid(const String& value) const
571                    {
572                        // Check to see that the value is in the domain (if a domain was given)
573                    
574                        Uint32 domainSize = _domain.size();
575                    
576                        if (domainSize)
577                        {
578 a.arora       1.45 	Boolean found = false;
579                    
580                    	for (Uint32 i = 0; i < domainSize; i++)
581                    	{
582                    	    if (value == _domain[i])
583                    		found = true;
584                    	}
585                    
586                    	if (!found)
587                    	    return false;
588                        }
589                    
590                        // Check the type:
591                    
592                        switch (_type)
593                        {
594                    	case BOOLEAN:
595                    	{
596                    	    if (value == "true" || value == "false")
597                    		return true;
598 dave.sudlik   1.52             else
599                                    return false;
600 a.arora       1.45 	}
601                    
602                    	case STRING:
603                    	    return true;
604                    
605                    	case INTEGER:
606                    	case NATURAL_NUMBER:
607                    	case WHOLE_NUMBER:
608                    	{
609                    	    CString tmp = value.getCString();
610                    	    char* end = 0;
611                    	    long x = strtol(tmp, &end, 10);
612                    
613                    	    if (!end || *end != '\0')
614                    		return false;
615                    
616                    	    switch (_type)
617                    	    {
618 david.dillard 1.48 		case INTEGER:
619 a.arora       1.45 		    return true;
620                    
621                    		case NATURAL_NUMBER:
622                    		    return x >= 1;
623                    
624                    		case WHOLE_NUMBER:
625                    		    return x >= 0;
626                    
627                    		default:
628                    		    break;
629                    	    }
630                    	}
631                        }
632                    
633                        // Unreachable!
634 dave.sudlik   1.52     return false;
635 a.arora       1.45 }
636                    
637                    ////////////////////////////////////////////////////////////////////////////////
638                    //
639                    // ConfigFileSyntaxError
640                    //
641                    ////////////////////////////////////////////////////////////////////////////////
642                    
643                    String OMConfigFileSyntaxError::_formatMessage(
644                        const String& file, Uint32 line)
645                    {
646                        char buffer[32];
647                        sprintf(buffer, "%d", line);
648                    	 //l10n
649                    	 MessageLoaderParms parms("Common.OptionManager.SYNTAX_ERR_CONFIG_FILE",
650                    	 								 "Syntax error in configuration file: ");
651                    	 String result = MessageLoader::getMessage(parms);
652                        //String result = "Syntax error in configuration file: ";
653                        result.append(file);
654                        result.append("(");
655                        result.append(buffer);
656 a.arora       1.45     result.append(")");
657                        return result;
658                    }
659                    
660                    PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2