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

  1 thilo.boehm 1.1 //%LICENSE////////////////////////////////////////////////////////////////
  2                 //
  3                 // Licensed to The Open Group (TOG) under one or more contributor license
  4                 // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5                 // this work for additional information regarding copyright ownership.
  6                 // Each contributor licenses this file to you under the OpenPegasus Open
  7                 // Source License; you may not use this file except in compliance with the
  8                 // License.
  9                 //
 10                 // Permission is hereby granted, free of charge, to any person obtaining a
 11                 // copy of this software and associated documentation files (the "Software"),
 12                 // to deal in the Software without restriction, including without limitation
 13                 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14                 // and/or sell copies of the Software, and to permit persons to whom the
 15                 // Software is furnished to do so, subject to the following conditions:
 16                 //
 17                 // The above copyright notice and this permission notice shall be included
 18                 // in all copies or substantial portions of the Software.
 19                 //
 20                 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21                 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 thilo.boehm 1.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23                 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24                 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25                 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26                 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27                 //
 28                 //////////////////////////////////////////////////////////////////////////
 29                 //
 30                 //%/////////////////////////////////////////////////////////////////////////////
 31                 
 32                 #include <cstdlib>
 33                 #include <cctype>
 34                 #include <fstream>
 35                 #include <cstdio>
 36 thilo.boehm 1.2 #include <Pegasus/Common/FileSystem.h>
 37 thilo.boehm 1.1 #include "OptionManager.h"
 38 thilo.boehm 1.2 
 39 thilo.boehm 1.1 
 40                 PEGASUS_USING_STD;
 41                 
 42                 PEGASUS_NAMESPACE_BEGIN
 43                 
 44                 ////////////////////////////////////////////////////////////////////////////////
 45                 //
 46                 // TODO: expand variables in the configuration file. For example:
 47                 //
 48                 //     provider_dir = "${home}/providers"
 49                 //
 50                 ////////////////////////////////////////////////////////////////////////////////
 51                 
 52                 ////////////////////////////////////////////////////////////////////////////////
 53                 //
 54                 // Option
 55                 //
 56                 ////////////////////////////////////////////////////////////////////////////////
 57                 
 58                 const Array<String>& Option::getDomain() const
 59                 {
 60 thilo.boehm 1.1     return _domain;
 61                 }
 62                 
 63                 void Option::setDomain(const Array<String>& domain)
 64                 {
 65                     _domain = domain;
 66                 }
 67                 
 68                 ////////////////////////////////////////////////////////////////////////////////
 69                 //
 70                 // OptionManager
 71                 //
 72                 ////////////////////////////////////////////////////////////////////////////////
 73                 
 74                 OptionManager::OptionManager()
 75                     :_msgPath("")
 76                 {
 77                 
 78                 }
 79                 
 80                 OptionManager::~OptionManager()
 81 thilo.boehm 1.1 {
 82                     // Delete all options in the list:
 83                 
 84                     for (Uint32 i = 0; i < _options.size(); i++)
 85                         delete _options[i];
 86                 }
 87                 
 88                 void OptionManager::registerOption(Option* option)
 89                 {
 90                     if (!option)
 91                         throw NullPointer();
 92                 
 93                     if (lookupOption(option->getOptionName()))
 94                         throw OMDuplicateOption(option->getOptionName());
 95                 
 96                     _options.append(option);
 97                 }
 98                 
 99                 
100                 void OptionManager::registerOptions(OptionRow* optionRow, Uint32 numOptions)
101                 {
102 thilo.boehm 1.1     for (Uint32 i = 0; i < numOptions; i++)
103                     {
104                         // Get option name:
105                 
106                         if (!optionRow[i].optionName)
107                             throw NullPointer();
108                 
109                         String optionName = optionRow[i].optionName;
110                 
111                         // Get default value:
112                 
113                         String defaultValue;
114                 
115                         if (optionRow[i].defaultValue)
116                             defaultValue = optionRow[i].defaultValue;
117                 
118                         // Get the required flag:
119                 
120                         Boolean required = optionRow[i].required != 0;
121                 
122                         // Get the type:
123 thilo.boehm 1.1 
124                         Option::Type type = optionRow[i].type;
125                 
126                         // Get the domain:
127                 
128                         Array<String> domain;
129                 
130                         if (optionRow[i].domain)
131                         {
132                             Uint32 domainSize = optionRow[i].domainSize;
133                 
134                             for (Uint32 j = 0; j < domainSize; j++)
135                                 domain.append(optionRow[i].domain[j]);
136                         }
137                 
138                         // Get commandLineOptionName:
139                 
140                         String commandLineOptionName;
141                 
142                         if (optionRow[i].commandLineOptionName)
143                             commandLineOptionName = optionRow[i].commandLineOptionName;
144 thilo.boehm 1.1 
145                         // get optionHelp Message String
146                 
147                         String optionHelpMessage;
148                 
149                         if (optionRow[i].optionHelpMessage)
150                             optionHelpMessage = optionRow[i].optionHelpMessage;
151                 
152                         // Add the option:
153                 
154                         Option* option = new Option(
155                             optionName,
156                             defaultValue,
157                             required,
158                             type,
159                             domain,
160                             commandLineOptionName,
161                             optionHelpMessage);
162                 
163                         registerOption(option);
164                     }
165 thilo.boehm 1.1 }
166                 
167                 void OptionManager::registerOptions(
168                     OptionRowWithMsg* optionRow,
169                     Uint32 numOptions)
170                 {
171                     for (Uint32 i = 0; i < numOptions; i++)
172                     {
173                         // Get option name:
174                 
175                         if (!optionRow[i].optionName)
176                         {
177                             throw NullPointer();
178                         }
179                 
180                         String optionName = optionRow[i].optionName;
181                 
182                         // Get default value:
183                 
184                         String defaultValue;
185                 
186 thilo.boehm 1.1         if (optionRow[i].defaultValue)
187                         {
188                             defaultValue = optionRow[i].defaultValue;
189                         }
190                         // Get the required flag:
191                 
192                         Boolean required = optionRow[i].required != 0;
193                 
194                         // Get the type:
195                 
196                         Option::Type type = optionRow[i].type;
197                 
198                         // Get the domain:
199                 
200                         Array<String> domain;
201                 
202                         if (optionRow[i].domain)
203                         {
204                             Uint32 domainSize = optionRow[i].domainSize;
205                 
206                             for (Uint32 j = 0; j < domainSize; j++)
207 thilo.boehm 1.1             {
208                                 domain.append(optionRow[i].domain[j]);
209                             }
210                         }
211                 
212                         // Get commandLineOptionName:
213                 
214                         String commandLineOptionName;
215                 
216                         if (optionRow[i].commandLineOptionName)
217                         {
218                             commandLineOptionName = optionRow[i].commandLineOptionName;
219                         }
220                         // get optionHelp Message String
221                 
222                         String optionHelpMessage;
223                 
224                         if (optionRow[i].optionHelpMessage)
225                         {
226                             optionHelpMessage = optionRow[i].optionHelpMessage;
227                         }
228 thilo.boehm 1.1 
229                         String messageKey = String();
230                         if (optionRow[i].messageKey)
231                         {
232                             messageKey = optionRow[i].messageKey;
233                         }
234                 
235                         // Add the option:
236                 
237                         Option* option = new Option(
238                             optionName,
239                             defaultValue,
240                             required,
241                             type,
242                             domain,
243                             commandLineOptionName,
244                             optionHelpMessage,
245                             messageKey);
246                 
247                         registerOption(option);
248                     }
249 thilo.boehm 1.1 }
250                 void OptionManager::mergeCommandLine(
251                     int& argc,
252                     char**& argv,
253                     Boolean abortOnErr)
254                 {
255                     for (int i = 0; i < argc; )
256                     {
257                         // Check for -option:
258                 
259                         const char* arg = argv[i];
260                 
261                         if (*arg == '-')
262                         {
263                             // Look for the option:
264                 
265                             Option* option = _lookupOptionByCommandLineOptionName(arg + 1);
266                 
267 dev.meetei  1.3             // a Null option here could mean either 
268                             // 1) option is missing
269                             // 2) option is invalid
270                             String optn = arg+1;
271 thilo.boehm 1.1             if (!option)
272                             {
273                                 if (abortOnErr)
274                                 {
275 dev.meetei  1.3                     //option is invalid
276                                     if(optn.size() != 0)
277                                     {
278                                         throw OMMBadCmdLineOption(arg);
279                                     }
280                                     //option is missing 
281                                     else
282                                     {
283                                         throw OMMissingCommandLineOptionArgument(arg);
284                                     }
285 thilo.boehm 1.1                 }
286                                 else
287                                 {
288                                     i++;
289                                     continue;
290                                 }
291                             }
292                 
293                             // Get the option argument if any:
294                 
295                             const char* optionArgument = "true";
296                 
297                             if (option->getType() != Option::BOOLEAN)
298                             {
299                                 if (i + 1 == argc)
300                                     throw OMMissingCommandLineOptionArgument(arg);
301                 
302                                 optionArgument = argv[i + 1];
303                             }
304                 
305                             // Validate the value:
306 thilo.boehm 1.1 
307                             if (!option->isValid(optionArgument))
308                                 throw OMInvalidOptionValue(arg, optionArgument);
309                 
310                             // Set the value:
311                 
312                             option->setValue(optionArgument);
313                 
314                             // Remove the option and its argument from the command line:
315                 
316                             if (option->getType() == Option::BOOLEAN)
317                             {
318                                 memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));
319                                 argc--;
320                             }
321                             else
322                             {
323                                 memmove(&argv[i], &argv[i + 2], (argc-i-1) * sizeof(char*));
324                                 argc -= 2;
325                             }
326                         }
327 thilo.boehm 1.1         else
328                             i++;
329                     }
330                 }
331                 
332                 void OptionManager::mergeFile(const String& fileName)
333                 {
334                    // Open the input file:
335                     ifstream is(fileName.getCString());
336                 
337                     if (!is)
338                         throw NoSuchFile(fileName);
339                 
340                     // For each line of the file:
341                 
342                     String line;
343                 
344                     for (Uint32 lineNumber = 1; GetLine(is, line); lineNumber++)
345                     {
346                         // -- Get the identifier and value:
347                 
348 thilo.boehm 1.1         if (line[0] == '#')
349                             continue;
350                 
351                         // Skip leading whitespace:
352                 
353                         const Char16* p = line.getChar16Data();
354                 
355                         while (*p && isspace(*p))
356                             p++;
357                 
358                         if (!*p)
359                             continue;
360                 
361                         if (*p == '#')
362                             continue;
363                 
364                         // Get the identifier:
365                 
366                         String ident;
367                 
368                         if (!(isalpha(*p) || *p == '_'))
369 thilo.boehm 1.1             throw OMConfigFileSyntaxError(fileName, lineNumber);
370                 
371                         ident.append(*p++);
372                 
373                         while (isalnum(*p) || *p == '_')
374                             ident.append(*p++);
375                 
376                         // Skip whitespace after identifier:
377                 
378                         while (*p && isspace(*p))
379                             p++;
380                 
381                         // Expect an equal sign:
382                 
383                         if (*p != '=')
384                             throw OMConfigFileSyntaxError(fileName, lineNumber);
385                         p++;
386                 
387                         // Skip whitespace after equal sign:
388                 
389                         while (*p && isspace(*p))
390 thilo.boehm 1.1             p++;
391                 
392                         // Expect open quote:
393                 
394                         if (*p != '"')
395                             throw OMConfigFileSyntaxError(fileName, lineNumber);
396                         p++;
397                 
398                         // Get the value:
399                 
400                         String value;
401                 
402                         while (*p && *p != '"')
403                         {
404                             if (*p == '\\')
405                             {
406                                 p++;
407                 
408                                 switch (*p)
409                                 {
410                                     case 'n':
411 thilo.boehm 1.1                         value.append('\n');
412                                         break;
413                 
414                                     case 'r':
415                                         value.append('\r');
416                                         break;
417                 
418                                     case 't':
419                                         value.append('\t');
420                                         break;
421                 
422                                     case 'f':
423                                         value.append('\f');
424                                         break;
425                 
426                                     case '"':
427                                         value.append('"');
428                                         break;
429                 
430                                     case '\0':
431                                         throw OMConfigFileSyntaxError(fileName, lineNumber);
432 thilo.boehm 1.1 
433                                     default:
434                                         value.append(*p);
435                                 }
436                                 p++;
437                             }
438                             else
439                                 value.append(*p++);
440                         }
441                 
442                 
443                         // Expect close quote:
444                 
445                         if (*p != '"')
446                             throw OMConfigFileSyntaxError(fileName, lineNumber);
447                         p++;
448                 
449                         // Skip whitespace through end of line:
450                 
451                         while (*p && isspace(*p))
452                             p++;
453 thilo.boehm 1.1 
454                         if (*p)
455                             throw OMConfigFileSyntaxError(fileName, lineNumber);
456                 
457                         // Now that we have the identifier and value, merge it:
458                 
459                         Option* option = (Option*)lookupOption(ident);
460                 
461                         if (!option)
462                             throw OMUnrecognizedConfigFileOption(ident);
463                 
464                         if (!option->isValid(value))
465                             throw OMInvalidOptionValue(ident, value);
466                 
467                         option->setValue(value);
468                     }
469                 }
470                 
471                 void OptionManager::checkRequiredOptions() const
472                 {
473                     for (Uint32 i = 0; i < _options.size(); i++)
474 thilo.boehm 1.1     {
475                         const Option* option = _options[i];
476                 
477                         if (option->getRequired() && !option->isResolved())
478                             throw OMMissingRequiredOptionValue(option->getOptionName());
479                     }
480                 }
481                 
482                 const Option* OptionManager::lookupOption(const String& name) const
483                 {
484                     for (Uint32 i = 0; i < _options.size(); i++)
485                     {
486                         if (_options[i]->getOptionName() == name)
487                             return _options[i];
488                     }
489                 
490                     return 0;
491                 }
492                 
493                 Boolean OptionManager::lookupValue(const String& name, String& value) const
494                 {
495 thilo.boehm 1.1     const Option* option = lookupOption(name);
496                 
497                     if (!option)
498                         return false;
499                 
500                     value = option->getValue();
501                     return true;
502                 }
503                 
504                 Boolean OptionManager::lookupIntegerValue(
505                     const String& name,
506                     Uint32& value) const
507                 {
508                     //ATTN: KS P1 7 May 2002 - Add test for Integer type in om table.
509                     String valueString;
510                     if (lookupValue(name, valueString))
511                     {
512                         value = atol(valueString.getCString());
513                         return true;
514                     }
515                     else
516 thilo.boehm 1.1     {
517                         return false;
518                     }
519                 
520                 }
521                 
522                 Boolean OptionManager::valueEquals(
523                     const String& name,
524                     const String& value) const
525                 {
526                     String optionString;
527                 
528                     return (lookupValue(name, optionString) && optionString == value);
529                 }
530                 
531                 Boolean OptionManager::isTrue(const String& name) const
532                 {
533                     //ATTN: KS 7 May 2002 P3 Add test to confirm boolean type
534                     return valueEquals(name, "true") ? true: false;
535                 }
536                 
537 thilo.boehm 1.1 /*  ATTN: P3 MB 2001 Buried this one for the moment to think about it.
538                 Uint32 OptionManager::isStringInOptionMask(
539                     const String& option,
540                     const String& entry)
541                 {
542                     String optionString;
543                 
544                     if (lookupValue(name, optionString) && optionString == value)
545                         if (optionString.find(entry)
546                             return 1;
547                     else
548                         return PEG_NOT_FOUND;
549                 }
550                 */
551                 
552                 Option* OptionManager::_lookupOptionByCommandLineOptionName(const String& name)
553                 {
554                     for (Uint32 i = 0; i < _options.size(); i++)
555                     {
556                         if (_options[i]->getCommandLineOptionName() == name)
557                             return _options[i];
558 thilo.boehm 1.1     }
559                 
560                     return 0;
561                 }
562                 
563                 void OptionManager::print() const
564                 {
565                     for (Uint32 i = 0; i < _options.size(); i++)
566                     {
567                         Option* option = _options[i];
568                         cout << option->getOptionName() << "=\"";
569                         cout << option->getValue() << "\" ";
570                         cout << option->getOptionHelpMessage() << "\n";
571                     }
572                     cout << endl;
573                 }
574                 
575                 void OptionManager::setMessagePath(String messagePath)
576                 {
577                     _msgPath = messagePath;
578                 }
579 thilo.boehm 1.1 /* This is utility function to create help string for the option*/
580                 String createOptionHelpString(Option* option)
581                 {
582                     String defMsg = " -";
583                     defMsg.append(option->getCommandLineOptionName());
584                     defMsg.append("  ");
585                     defMsg.append(option->getOptionName());
586                     defMsg.append(". ");
587                     defMsg.append(option->getOptionHelpMessage());
588                     defMsg.append(". Default(");
589                     defMsg.append(option->getDefaultValue());
590                     defMsg.append(")\n");
591                     return defMsg;
592                 }
593                 
594                 void OptionManager::printOptionsHelp() const
595                 {
596                     for (Uint32 i = 0; i < _options.size(); i++)
597                     {
598                         String str;
599                         Option* option = _options[i];
600 thilo.boehm 1.1         String defMsg = createOptionHelpString(option);
601                         CString cstr = defMsg.getCString();
602                         const String messageKey = option->getMessageKey();
603                         CString msgKeyCString = messageKey.getCString();
604                         if (String::compare(messageKey, String::EMPTY))
605                         {
606                             MessageLoaderParms parms(
607                                 (const char*)msgKeyCString,
608                                 (const char*)cstr);
609                             parms.msg_src_path = _msgPath;
610                             str = MessageLoader::getMessage(parms);
611                         }
612                         else
613                         {
614                             str = defMsg;
615                         }
616                         cout << str;
617                     }
618                     cout << endl;
619                 }
620                 
621 thilo.boehm 1.1 void OptionManager::printOptionsHelpTxt(
622                     const String& header,
623                     const String& trailer) const
624                 {
625                     cout << "\n" << header << "\n";
626                     printOptionsHelp();
627                     cout << trailer << "\n";
628                 }
629                 
630                 ////////////////////////////////////////////////////////////////////////////////
631                 //
632                 // Option
633                 //
634                 ////////////////////////////////////////////////////////////////////////////////
635                 
636                 Option::Option(
637                     const String& optionName,
638                     const String& defaultValue,
639                     Boolean required,
640                     Type type,
641                     const Array<String>& domain,
642 thilo.boehm 1.1     const String& commandLineOptionName,
643                     const String& optionHelpMessage,
644                     const String& messageKey)
645                     :
646                     _optionName(optionName),
647                     _defaultValue(defaultValue),
648                     _value(defaultValue),
649                     _required(required),
650                     _type(type),
651                     _domain(domain),
652                     _commandLineOptionName(commandLineOptionName),
653                     _optionHelpMessage(optionHelpMessage),
654                     _messageKey(messageKey),
655                     _resolved(false)
656                 {
657                     if (!isValid(_value))
658                         throw OMInvalidOptionValue(_optionName, _value);
659                 }
660                 
661                 Option::Option(const Option& x)
662                     :
663 thilo.boehm 1.1     _optionName(x._optionName),
664                     _defaultValue(x._defaultValue),
665                     _value(x._value),
666                     _required(x._required),
667                     _type(x._type),
668                     _domain(x._domain),
669                     _commandLineOptionName(x._commandLineOptionName),
670                     _optionHelpMessage(x._optionHelpMessage),
671                     _messageKey(x._messageKey)
672                 {
673                 }
674                 
675                 Option::~Option()
676                 {
677                 
678                 }
679                 
680                 Option& Option::operator=(const Option& x)
681                 {
682                     if (this != &x)
683                     {
684 thilo.boehm 1.1         _optionName = x._optionName;
685                         _defaultValue = x._defaultValue;
686                         _value = x._value;
687                         _required = x._required;
688                         _type = x._type;
689                         _domain = x._domain;
690                         _commandLineOptionName = x._commandLineOptionName;
691                         _optionHelpMessage = x._optionHelpMessage;
692                         _messageKey = x._messageKey;
693                     }
694                     return *this;
695                 }
696                 
697                 Boolean Option::isValid(const String& value) const
698                 {
699                     // Check to see that the value is in the domain (if a domain was given)
700                 
701                     Uint32 domainSize = _domain.size();
702                 
703                     if (domainSize)
704                     {
705 thilo.boehm 1.1         Boolean found = false;
706                 
707                         for (Uint32 i = 0; i < domainSize; i++)
708                         {
709                             if (value == _domain[i])
710                                 found = true;
711                         }
712                 
713                         if (!found)
714                             return false;
715                     }
716                 
717                     // Check the type:
718                 
719                     switch (_type)
720                     {
721                         case BOOLEAN:
722                         {
723                             if (value == "true" || value == "false")
724                                 return true;
725                             else
726 thilo.boehm 1.1                 return false;
727                         }
728                 
729                         case STRING:
730                             return true;
731                 
732                         case INTEGER:
733                         case NATURAL_NUMBER:
734                         case WHOLE_NUMBER:
735                         {
736                             CString tmp = value.getCString();
737                             char* end = 0;
738                             long x = strtol(tmp, &end, 10);
739                 
740                             if (!end || *end != '\0')
741                                 return false;
742                 
743                             switch (_type)
744                             {
745                                 case INTEGER:
746                                     return true;
747 thilo.boehm 1.1 
748                                 case NATURAL_NUMBER:
749                                     return x >= 1;
750                 
751                                 case WHOLE_NUMBER:
752                                     return x >= 0;
753                 
754                                 default:
755                                     break;
756                             }
757                         }
758                     }
759                 
760                     // Unreachable!
761                     return false;
762                 }
763                 
764                 ////////////////////////////////////////////////////////////////////////////////
765                 //
766                 // ConfigFileSyntaxError
767                 //
768 thilo.boehm 1.1 ////////////////////////////////////////////////////////////////////////////////
769                 
770                 String OMConfigFileSyntaxError::_formatMessage(
771                     const String& file, Uint32 line)
772                 {
773                     char buffer[32];
774                     sprintf(buffer, "%u", line);
775                     MessageLoaderParms parms(
776                         "Common.OptionManager.SYNTAX_ERR_CONFIG_FILE",
777                         "Syntax error in configuration file: ");
778                     String result = MessageLoader::getMessage(parms);
779                     result.append(file);
780                     result.append("(");
781                     result.append(buffer);
782                     result.append(")");
783                     return result;
784                 }
785                 
786                 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2