(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                             if (!option)
268                             {
269                                 if (abortOnErr)
270 thilo.boehm 1.1                 {
271                                     throw OMMBadCmdLineOption(arg);
272                                 }
273                                 else
274                                 {
275                                     i++;
276                                     continue;
277                                 }
278                             }
279                 
280                             // Get the option argument if any:
281                 
282                             const char* optionArgument = "true";
283                 
284                             if (option->getType() != Option::BOOLEAN)
285                             {
286                                 if (i + 1 == argc)
287                                     throw OMMissingCommandLineOptionArgument(arg);
288                 
289                                 optionArgument = argv[i + 1];
290                             }
291 thilo.boehm 1.1 
292                             // Validate the value:
293                 
294                             if (!option->isValid(optionArgument))
295                                 throw OMInvalidOptionValue(arg, optionArgument);
296                 
297                             // Set the value:
298                 
299                             option->setValue(optionArgument);
300                 
301                             // Remove the option and its argument from the command line:
302                 
303                             if (option->getType() == Option::BOOLEAN)
304                             {
305                                 memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));
306                                 argc--;
307                             }
308                             else
309                             {
310                                 memmove(&argv[i], &argv[i + 2], (argc-i-1) * sizeof(char*));
311                                 argc -= 2;
312 thilo.boehm 1.1             }
313                         }
314                         else
315                             i++;
316                     }
317                 }
318                 
319                 void OptionManager::mergeFile(const String& fileName)
320                 {
321                    // Open the input file:
322                     ifstream is(fileName.getCString());
323                 
324                     if (!is)
325                         throw NoSuchFile(fileName);
326                 
327                     // For each line of the file:
328                 
329                     String line;
330                 
331                     for (Uint32 lineNumber = 1; GetLine(is, line); lineNumber++)
332                     {
333 thilo.boehm 1.1         // -- Get the identifier and value:
334                 
335                         if (line[0] == '#')
336                             continue;
337                 
338                         // Skip leading whitespace:
339                 
340                         const Char16* p = line.getChar16Data();
341                 
342                         while (*p && isspace(*p))
343                             p++;
344                 
345                         if (!*p)
346                             continue;
347                 
348                         if (*p == '#')
349                             continue;
350                 
351                         // Get the identifier:
352                 
353                         String ident;
354 thilo.boehm 1.1 
355                         if (!(isalpha(*p) || *p == '_'))
356                             throw OMConfigFileSyntaxError(fileName, lineNumber);
357                 
358                         ident.append(*p++);
359                 
360                         while (isalnum(*p) || *p == '_')
361                             ident.append(*p++);
362                 
363                         // Skip whitespace after identifier:
364                 
365                         while (*p && isspace(*p))
366                             p++;
367                 
368                         // Expect an equal sign:
369                 
370                         if (*p != '=')
371                             throw OMConfigFileSyntaxError(fileName, lineNumber);
372                         p++;
373                 
374                         // Skip whitespace after equal sign:
375 thilo.boehm 1.1 
376                         while (*p && isspace(*p))
377                             p++;
378                 
379                         // Expect open quote:
380                 
381                         if (*p != '"')
382                             throw OMConfigFileSyntaxError(fileName, lineNumber);
383                         p++;
384                 
385                         // Get the value:
386                 
387                         String value;
388                 
389                         while (*p && *p != '"')
390                         {
391                             if (*p == '\\')
392                             {
393                                 p++;
394                 
395                                 switch (*p)
396 thilo.boehm 1.1                 {
397                                     case 'n':
398                                         value.append('\n');
399                                         break;
400                 
401                                     case 'r':
402                                         value.append('\r');
403                                         break;
404                 
405                                     case 't':
406                                         value.append('\t');
407                                         break;
408                 
409                                     case 'f':
410                                         value.append('\f');
411                                         break;
412                 
413                                     case '"':
414                                         value.append('"');
415                                         break;
416                 
417 thilo.boehm 1.1                     case '\0':
418                                         throw OMConfigFileSyntaxError(fileName, lineNumber);
419                 
420                                     default:
421                                         value.append(*p);
422                                 }
423                                 p++;
424                             }
425                             else
426                                 value.append(*p++);
427                         }
428                 
429                 
430                         // Expect close quote:
431                 
432                         if (*p != '"')
433                             throw OMConfigFileSyntaxError(fileName, lineNumber);
434                         p++;
435                 
436                         // Skip whitespace through end of line:
437                 
438 thilo.boehm 1.1         while (*p && isspace(*p))
439                             p++;
440                 
441                         if (*p)
442                             throw OMConfigFileSyntaxError(fileName, lineNumber);
443                 
444                         // Now that we have the identifier and value, merge it:
445                 
446                         Option* option = (Option*)lookupOption(ident);
447                 
448                         if (!option)
449                             throw OMUnrecognizedConfigFileOption(ident);
450                 
451                         if (!option->isValid(value))
452                             throw OMInvalidOptionValue(ident, value);
453                 
454                         option->setValue(value);
455                     }
456                 }
457                 
458                 void OptionManager::checkRequiredOptions() const
459 thilo.boehm 1.1 {
460                     for (Uint32 i = 0; i < _options.size(); i++)
461                     {
462                         const Option* option = _options[i];
463                 
464                         if (option->getRequired() && !option->isResolved())
465                             throw OMMissingRequiredOptionValue(option->getOptionName());
466                     }
467                 }
468                 
469                 const Option* OptionManager::lookupOption(const String& name) const
470                 {
471                     for (Uint32 i = 0; i < _options.size(); i++)
472                     {
473                         if (_options[i]->getOptionName() == name)
474                             return _options[i];
475                     }
476                 
477                     return 0;
478                 }
479                 
480 thilo.boehm 1.1 Boolean OptionManager::lookupValue(const String& name, String& value) const
481                 {
482                     const Option* option = lookupOption(name);
483                 
484                     if (!option)
485                         return false;
486                 
487                     value = option->getValue();
488                     return true;
489                 }
490                 
491                 Boolean OptionManager::lookupIntegerValue(
492                     const String& name,
493                     Uint32& value) const
494                 {
495                     //ATTN: KS P1 7 May 2002 - Add test for Integer type in om table.
496                     String valueString;
497                     if (lookupValue(name, valueString))
498                     {
499                         value = atol(valueString.getCString());
500                         return true;
501 thilo.boehm 1.1     }
502                     else
503                     {
504                         return false;
505                     }
506                 
507                 }
508                 
509                 Boolean OptionManager::valueEquals(
510                     const String& name,
511                     const String& value) const
512                 {
513                     String optionString;
514                 
515                     return (lookupValue(name, optionString) && optionString == value);
516                 }
517                 
518                 Boolean OptionManager::isTrue(const String& name) const
519                 {
520                     //ATTN: KS 7 May 2002 P3 Add test to confirm boolean type
521                     return valueEquals(name, "true") ? true: false;
522 thilo.boehm 1.1 }
523                 
524                 /*  ATTN: P3 MB 2001 Buried this one for the moment to think about it.
525                 Uint32 OptionManager::isStringInOptionMask(
526                     const String& option,
527                     const String& entry)
528                 {
529                     String optionString;
530                 
531                     if (lookupValue(name, optionString) && optionString == value)
532                         if (optionString.find(entry)
533                             return 1;
534                     else
535                         return PEG_NOT_FOUND;
536                 }
537                 */
538                 
539                 Option* OptionManager::_lookupOptionByCommandLineOptionName(const String& name)
540                 {
541                     for (Uint32 i = 0; i < _options.size(); i++)
542                     {
543 thilo.boehm 1.1         if (_options[i]->getCommandLineOptionName() == name)
544                             return _options[i];
545                     }
546                 
547                     return 0;
548                 }
549                 
550                 void OptionManager::print() const
551                 {
552                     for (Uint32 i = 0; i < _options.size(); i++)
553                     {
554                         Option* option = _options[i];
555                         cout << option->getOptionName() << "=\"";
556                         cout << option->getValue() << "\" ";
557                         cout << option->getOptionHelpMessage() << "\n";
558                     }
559                     cout << endl;
560                 }
561                 
562                 void OptionManager::setMessagePath(String messagePath)
563                 {
564 thilo.boehm 1.1     _msgPath = messagePath;
565                 }
566                 /* This is utility function to create help string for the option*/
567                 String createOptionHelpString(Option* option)
568                 {
569                     String defMsg = " -";
570                     defMsg.append(option->getCommandLineOptionName());
571                     defMsg.append("  ");
572                     defMsg.append(option->getOptionName());
573                     defMsg.append(". ");
574                     defMsg.append(option->getOptionHelpMessage());
575                     defMsg.append(". Default(");
576                     defMsg.append(option->getDefaultValue());
577                     defMsg.append(")\n");
578                     return defMsg;
579                 }
580                 
581                 void OptionManager::printOptionsHelp() const
582                 {
583                     for (Uint32 i = 0; i < _options.size(); i++)
584                     {
585 thilo.boehm 1.1         String str;
586                         Option* option = _options[i];
587                         String defMsg = createOptionHelpString(option);
588                         CString cstr = defMsg.getCString();
589                         const String messageKey = option->getMessageKey();
590                         CString msgKeyCString = messageKey.getCString();
591                         if (String::compare(messageKey, String::EMPTY))
592                         {
593                             MessageLoaderParms parms(
594                                 (const char*)msgKeyCString,
595                                 (const char*)cstr);
596                             parms.msg_src_path = _msgPath;
597                             str = MessageLoader::getMessage(parms);
598                         }
599                         else
600                         {
601                             str = defMsg;
602                         }
603                         cout << str;
604                     }
605                     cout << endl;
606 thilo.boehm 1.1 }
607                 
608                 void OptionManager::printOptionsHelpTxt(
609                     const String& header,
610                     const String& trailer) const
611                 {
612                     cout << "\n" << header << "\n";
613                     printOptionsHelp();
614                     cout << trailer << "\n";
615                 }
616                 
617                 ////////////////////////////////////////////////////////////////////////////////
618                 //
619                 // Option
620                 //
621                 ////////////////////////////////////////////////////////////////////////////////
622                 
623                 Option::Option(
624                     const String& optionName,
625                     const String& defaultValue,
626                     Boolean required,
627 thilo.boehm 1.1     Type type,
628                     const Array<String>& domain,
629                     const String& commandLineOptionName,
630                     const String& optionHelpMessage,
631                     const String& messageKey)
632                     :
633                     _optionName(optionName),
634                     _defaultValue(defaultValue),
635                     _value(defaultValue),
636                     _required(required),
637                     _type(type),
638                     _domain(domain),
639                     _commandLineOptionName(commandLineOptionName),
640                     _optionHelpMessage(optionHelpMessage),
641                     _messageKey(messageKey),
642                     _resolved(false)
643                 {
644                     if (!isValid(_value))
645                         throw OMInvalidOptionValue(_optionName, _value);
646                 }
647                 
648 thilo.boehm 1.1 Option::Option(const Option& x)
649                     :
650                     _optionName(x._optionName),
651                     _defaultValue(x._defaultValue),
652                     _value(x._value),
653                     _required(x._required),
654                     _type(x._type),
655                     _domain(x._domain),
656                     _commandLineOptionName(x._commandLineOptionName),
657                     _optionHelpMessage(x._optionHelpMessage),
658                     _messageKey(x._messageKey)
659                 {
660                 }
661                 
662                 Option::~Option()
663                 {
664                 
665                 }
666                 
667                 Option& Option::operator=(const Option& x)
668                 {
669 thilo.boehm 1.1     if (this != &x)
670                     {
671                         _optionName = x._optionName;
672                         _defaultValue = x._defaultValue;
673                         _value = x._value;
674                         _required = x._required;
675                         _type = x._type;
676                         _domain = x._domain;
677                         _commandLineOptionName = x._commandLineOptionName;
678                         _optionHelpMessage = x._optionHelpMessage;
679                         _messageKey = x._messageKey;
680                     }
681                     return *this;
682                 }
683                 
684                 Boolean Option::isValid(const String& value) const
685                 {
686                     // Check to see that the value is in the domain (if a domain was given)
687                 
688                     Uint32 domainSize = _domain.size();
689                 
690 thilo.boehm 1.1     if (domainSize)
691                     {
692                         Boolean found = false;
693                 
694                         for (Uint32 i = 0; i < domainSize; i++)
695                         {
696                             if (value == _domain[i])
697                                 found = true;
698                         }
699                 
700                         if (!found)
701                             return false;
702                     }
703                 
704                     // Check the type:
705                 
706                     switch (_type)
707                     {
708                         case BOOLEAN:
709                         {
710                             if (value == "true" || value == "false")
711 thilo.boehm 1.1                 return true;
712                             else
713                                 return false;
714                         }
715                 
716                         case STRING:
717                             return true;
718                 
719                         case INTEGER:
720                         case NATURAL_NUMBER:
721                         case WHOLE_NUMBER:
722                         {
723                             CString tmp = value.getCString();
724                             char* end = 0;
725                             long x = strtol(tmp, &end, 10);
726                 
727                             if (!end || *end != '\0')
728                                 return false;
729                 
730                             switch (_type)
731                             {
732 thilo.boehm 1.1                 case INTEGER:
733                                     return true;
734                 
735                                 case NATURAL_NUMBER:
736                                     return x >= 1;
737                 
738                                 case WHOLE_NUMBER:
739                                     return x >= 0;
740                 
741                                 default:
742                                     break;
743                             }
744                         }
745                     }
746                 
747                     // Unreachable!
748                     return false;
749                 }
750                 
751                 ////////////////////////////////////////////////////////////////////////////////
752                 //
753 thilo.boehm 1.1 // ConfigFileSyntaxError
754                 //
755                 ////////////////////////////////////////////////////////////////////////////////
756                 
757                 String OMConfigFileSyntaxError::_formatMessage(
758                     const String& file, Uint32 line)
759                 {
760                     char buffer[32];
761                     sprintf(buffer, "%u", line);
762                     MessageLoaderParms parms(
763                         "Common.OptionManager.SYNTAX_ERR_CONFIG_FILE",
764                         "Syntax error in configuration file: ");
765                     String result = MessageLoader::getMessage(parms);
766                     result.append(file);
767                     result.append("(");
768                     result.append(buffer);
769                     result.append(")");
770                     return result;
771                 }
772                 
773                 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2