1 karl 1.43 //%2005////////////////////////////////////////////////////////////////////////
|
2 karl 1.40 //
|
3 karl 1.42 // 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.40 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.42 // 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.43 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.40 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 david.dillard 1.44 //
|
19 karl 1.40 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
|
29 alagaraja 1.41 //
30 // Author: Mike Brasher (mbrasher@bmc.com)
31 //
|
32 david.dillard 1.44 // Modified By: Karl Schopmyer(k.schopmeyer@opengroup.org)
33 // David Dillard, VERITAS Software Corp.
34 // (david.dillard@veritas.com)
|
35 alagaraja 1.41 //
36 //%/////////////////////////////////////////////////////////////////////////////
37
38 //////////////////////////////////////////////////////////////////////////////
|
39 david.dillard 1.44 //
40 // This file defines the classes necessary to manage commandline and
41 // configuration file options for Pegasus. It defines
|
42 alagaraja 1.41 // The OptionManager Class
43 // The Option Class - Used to define information about an option
|
44 david.dillard 1.44 // The Option Row structure - Used to define option declarations in a
|
45 alagaraja 1.41 // program
46 // The optionexcptions Class
47 //
48 //////////////////////////////////////////////////////////////////////////////
49
50 #ifndef Pegasus_OptionManager_h
51 #define Pegasus_OptionManager_h
52
53 #include <Pegasus/Common/Config.h>
54 #include <Pegasus/Common/String.h>
55 #include <Pegasus/Common/ArrayInternal.h>
56 #include <Pegasus/Common/InternalException.h>
57 #include <Pegasus/Common/Linkage.h>
58 #include <Pegasus/Common/MessageLoader.h>
59
60 PEGASUS_NAMESPACE_BEGIN
61
62 class Option;
63 struct OptionRow;
64
65 typedef Option* OptionPtr;
66 alagaraja 1.41
67 // REVIEW: I seem to remember seeing another class that does something like
68 // REVIEW: this.
69
70 /** The OptionManager class manages a collection of program options.
71
72 <h4>Overview</h4>
73
74 A program option may be specified in two ways:
75
76 <ul>
77 <li>In a configuration file</li>
78 <li>On the command line</li>
79 </ul>
80
81 This class provides methods for merging options from both of these
82 sources into a single collection. The following example shows how to
83 merge options from a command line into the option manager.
84
85 <pre>
86 int main(int argc, char** argv)
87 alagaraja 1.41 {
88 OptionManager om;
89
90 ...
91
92 // Merge options from the command line into the option manager's
93 // option list. Remove arguments from command line.
94
95 om.mergeCommandLine(argc, argv);
96
97 ...
98 }
99 </pre>
100
101 Similarly, the OptionManager::mergeFile() method allows options to be
102 merged from a file.
103
104 Before options are merged into the option manager, information on each
105 option must be registered with the option manager so that the following
106 can be resolved:
107
108 alagaraja 1.41 <ul>
109 <li>The option's name</li>
110 <li>The default value (to be used if not specified elsewhere)</li>
111 <li>Whether the option is required</li>
112 <li>The option's type (e.g., boolean, integer or string)</li>
113 <li>The domain of the option if any (set of legal values)</li>
114 <li>The name the option as it appears on the command line</li>
115 </ul>
116
117 Here is how to regsiter an option:
118
119 <pre>
120 OptionManager om;
121
122 Option* option = new Option("port", "80", false,
123 Option::NATURAL_NUMBER, Array<String>(), "p");
124
125 om.registerOption(option);
126 </pre>
127
128 The arguments of the Option constructor are the same (and in the same
129 alagaraja 1.41 order) as the list just above. Notice the last argument is "p". This
130 is the name of the option argument on the command line (it would appear
131 as "-p" on the command line).
132
133 Once options have been registered, the option values may be initialized
134 using the merge methods described earlier. During merging, certain
135 validation is done using the corresponding Option instance described above.
136
137 Once options have been merged, they may obtained by calling the
138 lookupOption() method like this:
139
140 <pre>
141 Option* option = om.lookupOption("port");
142 String port = option->getValue();
143 </pre>
144
145 Or the lookupValue() convenience function may be used to lookup values:
146
147 <pre>
148 String value;
149 om.lookupValue("port", value);
150 alagaraja 1.41 </pre>
|
151 david.dillard 1.44
|
152 alagaraja 1.41 Boolean Options can easily be tested as follows:
153 <pre>
|
154 david.dillard 1.44
|
155 alagaraja 1.41 </pre>
156
157 <h4>Command Line Options</h4>
158
159 mergeCommandLine() like this:
160
161 <pre>
162 om.mergeCommandLine(argc, argv);
163 </pre>
164
165 This method searches the command line for options that match the registered
166 ones. It will extract those options from the command line (argc and argv
167 will be modified accordingly).
168
169 <h4>Configuration File Otpions</h4>
170
171 Options from a configuration file may be merged by calling the mergeFile()
172 method like this:
173
174 <pre>
175 om.mergeFile(fileName);
176 alagaraja 1.41 </pre>
177
178 This searches the file for options matching registered ones. Exceptions
179 are thrown for any unrecognized option names that are encountered.
180
181 <h4>Merge Validation</h4>
182
183 During merging, the option manager validates the following (using the
184 information optatined during option registration).
185
186 <ul>
187 <li>The type of the option - whether integer, positive integer,
188 or string or whatever.</li>
189 <li>The domain of the option - whether the supplied option is a legal
190 value for that otpion</li>
191 <li>User extended validation - whether the user overriden
192 Option::isValid() returns true when the value is passed to it</li>
193 </ul>
194
195 <h4>Typcial Usage</h4>
196
197 alagaraja 1.41 The OptionManager is typically used in the following way. First, options
198 are registered to establish the valid set of options. Next, values are
199 merged from the various sources by calling the merge functions. Finally,
200 checkRequiredOptions() is called to see if any required option values were
201 not provided.
|
202 david.dillard 1.44
|
203 alagaraja 1.41 <h4>Option Types</h4>
|
204 david.dillard 1.44
|
205 alagaraja 1.41 The option manager allows for several types of options including:
206 <UL>
|
207 david.dillard 1.44 <LI> (BOOLEAN)Simple keyword parameters (ex. -t or -h on the command
208 line). These are Boolean parameters and there are no additional parameters
|
209 alagaraja 1.41 after the keyword.
|
210 david.dillard 1.44
211 <LI> (INTEGER) Numeric parameters - (ex -port 5988). These are
|
212 alagaraja 1.41 parameters where a numeric variable follows the parameter defintion.
|
213 david.dillard 1.44
|
214 alagaraja 1.41 <LI>(WHOLE_NUMBER) Numeric parameters ATTN: Finish.
|
215 david.dillard 1.44
|
216 alagaraja 1.41 <LI> (NATURAL_NUMBER Numieric parameters - (ex ). ATTN: finish
|
217 david.dillard 1.44
218 <LI>(STRING) String Parameters - (ex. -file abd.log) These are
219 parameters that are represented by strings following the option
|
220 alagaraja 1.41 keyword. No limitations are placed on the string except that it must
221 be resolvable to a single string.
222
|
223 david.dillard 1.44 <LI> (STRING) Domain Parameters - These are parameters where there is
224 a choice of keywords from a domain of keywords. The input parameter may be any
225 one of these keywords. Thus, the domain (red blue green) for the
226 parameter "color" (-c) could be entered as -c red. The difference
227 between String interpretation and domain interpretation is the use of the
|
228 alagaraja 1.41 domain fields in the option definition.
|
229 david.dillard 1.44
230 <LI> Mask parameters - These are parameters that define an internal
|
231 alagaraja 1.41 bit mask from a set of keywords input.
232 ATTN: Finish this definition.
233 </UL>
234 */
235
236 class PEGASUS_COMMON_LINKAGE OptionManager
237 {
238 public:
239
240 /** Constructor. */
241 OptionManager();
242
243 /** Destructor. Deletes all contained Options. */
244 ~OptionManager();
245
246 /** Registers an option. The OptionManager is responsible for disposing
247 of the option; the caller must not delete this object.
248
249 @param option option to be registerd.
250 @exception NullPointer exception if option argument is null.
251 @exception OMDuplicateOption if option already defined.
252 alagaraja 1.41 */
|
253 david.dillard 1.44 void registerOption(Option* option);
|
254 alagaraja 1.41
255 /** Provides a simple way to register several options at once using
256 a declartive style table. This may also be done programmitically
257 by repeatedly calling registerOption above. See documentation for
258 OptionRow for details on how to use them.
259 */
|
260 david.dillard 1.44 void registerOptions(OptionRow* options, Uint32 numOptions);
|
261 alagaraja 1.41
262 /** Merge option values from the command line. Searches the command
263 line for registered options whose names are given by the
264 Option::getCommandLineOptionName() method. Validation is performed
265 on each option value obtained by calling Option::isValid(). Valid
266 option values are set by calling Option::setValue(). The argc and
267 argv arguments are modified: the option and its argument are
268 stripped from the command line. The option and its argument have the
269 following form: -option-name argument. A space must be supplied
270 between the two. Boolean option arguments are an exception. They
271 must have the form -option. If they are present, then they are
272 taken to be true.
273
274 ¶m argc number of argument on the command line.
275 ¶m argv list of command line arguments.
276 ¶m abortOnErr - Optional Boolean that if true causes exception if there is
277 a parameter found that is not in the table. Defaults to true
278 &exception InvalidOptionValue if validation fails.
279 &exception OMMissingCommandLineOptionArgument
280 */
281 void mergeCommandLine(int& argc, char**& argv, Boolean abortOnErr=true);
282 alagaraja 1.41
283 /** Merge option values from a file. Searches file for registered options
284 whose names are given by the options which have been registered.
285 Validation is performed on each option value by calling
286 Option::isValid(). Valid option values are set by calling
287 Option::setValue().
288
289 ¶m fileName name of file to be merged.
290 &exception NoSuchFile if file cannot be opened.
291 &exception BadConfigFileOption
292 */
293 void mergeFile(const String& fileName);
294
295 /** After merging, this method is called to check for required options
296 that were not merged (specified).
297
298 &exception OMMissingRequiredRequiredOption
299 */
300 void checkRequiredOptions() const;
301
302 /** Lookup the option with the given name.
303 alagaraja 1.41 @param Name provides the name of the option.
304 @return 0 if no such option.
305 */
306 const Option* lookupOption(const String& name) const;
307
308 /** Lookup value of an option.
309 @param Name provides the name of the option (ex. "port")
310 @param String parameter contains the String that contains the
311 value for this parameter (in String format).
312 @return Boolean return. True if the option found.
313 */
314 Boolean lookupValue(const String& name, String& value ) const;
315
316 /** LookupIntegerValue value of an option determines if the value exists
317 and converts it to integer (Uint32).
318 @param Name provides the name of the option (ex. "port")
319 @param String parameter contains the String that contains the
320 value for this parameter (in String format).
321 @return Boolean return. True if the option found.
322 */
323 Boolean lookupIntegerValue(const String& name, Uint32& value) const;
324 alagaraja 1.41
325
326 /** isStringInOptionMask - Looks for a String value in an option.
327 This function is used to detect particular options listed in strings of
328 entries forming a STRING option. Thus, for example if the option string
|
329 david.dillard 1.44 were "abc,def,ijk" in option toy isStringInOption ("toy", "def") returns
|
330 alagaraja 1.41 true.
331 @param option name of the option in the option table
332 @param entry Entry to compare
333 @return True if the entry String is found in the option.
334 */
335 //Uint32 isStringInOptionMask (const String& option, String& entry) const;
336
337 /** optionValueEquals - Test the string value of an option.
338 @param name provides the name of the option (ex. "port")
339 @param value String value for comparison.
|
340 david.dillard 1.44 @return true if the option exists and the value of the option
|
341 alagaraja 1.41 equals the input parameter value.
342 */
343 Boolean valueEquals(const String& name, const String& value) const;
344
345 /** isTrue - determines if a Boolean Option is true or false. Note
346 that this function simply tests the value for "true" string.
347 @param name - the name of the opeiton
348 @return - Returns true if the option value is true.
349 */
350 Boolean isTrue(const String& name) const;
351
352 /** Print all the options. */
353 void print() const;
354
355 /** Print the help line for all options including cmdline name, name
356 and the help string
357 */
358 void printOptionsHelp() const;
359
360 /** Print Complete Help Text message including header before the options help
361 and trailer after the options help
362 alagaraja 1.41 */
363 void printOptionsHelpTxt(const String& header, const String& trailer) const;
364
365
366 private:
367
368 /** Lookup the option by its commandLineOptionName.
369 @return 0 if no such option.
370 */
371 Option* _lookupOptionByCommandLineOptionName(const String& name);
372
373 Array<Option*> _options;
374 };
375
376 //////////////////////////////////////////////////////////////////
377 // OPTION CLASS
378 //////////////////////////////////////////////////////////////////
379
380 /** The Option class is used to specify information about an Option.
381
382 See the OptionManager class for more details.
383 alagaraja 1.41 */
384 class PEGASUS_COMMON_LINKAGE Option
385 {
386 public:
387
388 /** Valid value types. */
389 enum Type
390 {
391 // (..., -3, -2, -1, 0, 1, 2, 3, ...)
392 INTEGER,
393
394 // (1, 2, 3, ...)
395 NATURAL_NUMBER,
396
397 // (0, 1, 2, 3, ...)
398 WHOLE_NUMBER,
399
400 // "true" or "false"
401 BOOLEAN,
402
403 // Anything
404 alagaraja 1.41 STRING
405 };
406
407 /** Constructor.
408
409 @param optionName the name of this option.
410
411 @param defaultValue the default value of this option.
412
413 @param required whether the value of this option is required.
414
415 @param type type of the value. This is used to validate the value.
416
417 @param domain list of legal value for this option. If this list
418 is empty, then no domain is enforced.
419
420 @param commandLineOptionName name of the corresponding command line
421 option (which may be different from the option name).
|
422 david.dillard 1.44
|
423 alagaraja 1.41 @param optionHelpMessage Text message that defines option. To be used
424 in Usage messages.
425 */
426 Option(
427 const String& optionName,
428 const String& defaultValue,
429 Boolean required,
430 Type type,
431 const Array<String>& domain = Array<String>(),
432 const String& commandLineOptionName = String(),
433 const String& optionHelpMessage = String());
434
435 Option(const Option& x);
436
437 virtual ~Option();
438
439 Option& operator=(const Option& x);
440
441 /** Accessor */
442 const String& getOptionName() const
443 {
444 alagaraja 1.41 return _optionName;
445 }
446
447 /** Modifier */
448 void setOptionName(const String& optionName)
449 {
450 _optionName = optionName;
451 }
452
453 /** Accessor */
454 const String& getDefaultValue() const
455 {
456 return _defaultValue;
457 }
458
459 /** Modifier. */
460 void setDefaultValue(const String& defaultValue)
461 {
462 _defaultValue = defaultValue;
463 }
464
465 alagaraja 1.41 /** Accessor
466 @return - Returns string representation of value
467 */
468 const String& getValue() const
469 {
470 return _value;
471 }
472
473 /** Modifier */
474 void setValue(const String& value)
475 {
476 _value = value;
477 _resolved = true;
478 }
|
479 david.dillard 1.44
|
480 alagaraja 1.41 /** Accessor */
481 Boolean getRequired() const
482 {
483 return _required;
484 }
485
486 /** Modifier */
487 void setRequired(Boolean required)
488 {
489 _required = required;
490 }
491
492 /** Accessor */
493 Type getType() const
494 {
495 return _type;
496 }
497
498 /** Modifier */
499 void setType(Type type)
500 {
501 alagaraja 1.41 _type = type;
502 }
503
504 /** Accessor */
505 const Array<String>& getDomain() const;
506
507 /** Modifier */
508 void setDomain(const Array<String>& domain);
509
510 /** Accessor */
511 const String& getCommandLineOptionName() const
512 {
513 return _commandLineOptionName;
514 }
515
516 /** Accessor */
517 const String& getOptionHelpMessage() const
518 {
519 return _optionHelpMessage;
520 }
521
522 alagaraja 1.41 /** Modifier */
523 void setCommandLineOptionName(const String& commandLineOptionName)
524 {
525 _commandLineOptionName = commandLineOptionName;
526 }
527
528 /** Accesor. Returns true if an option value was ever obtained for
529 this option.
530 */
531 Boolean isResolved() const
532 {
533 return _resolved;
534 }
535
536 /** Checks to see if the given value is valid or not. This method may be
537 overriden by derived classes to do special purpose validation of the
538 value. This implementation just checks the domain and type.
539 */
540 virtual Boolean isValid(const String& value) const;
541
542 private:
543 alagaraja 1.41 String _optionName;
544 String _defaultValue;
545 String _value;
546 Boolean _required;
547 Type _type;
548 Array<String> _domain;
549 String _commandLineOptionName;
550 String _optionHelpMessage;
551 Boolean _resolved;
552 };
553
554 ///////////////////////////////////////////////////////////////////////
555 // OptionRow
556 ///////////////////////////////////////////////////////////////////'//
557
558 /** The OptionRow provides a declarative way of defining Option objects.
559 For the declarative programming enthusiast, we provide this structure.
560 It provides a declarative way of defining options for the OptionManager
561 class. Some developers prefer this since it makes all the options visible
562 in a kind of table like structure. Here is an example of how it can be
563 used to define a port number and hostname options. We also show how to
564 alagaraja 1.41 register one of these option lists with an OptionManager.
565
566 <pre>
567 static OptionRow options[] =
568 {
569 { "port", "80", false, Option::NATURAL_NUMBER },
570 { "hostname", "", true, Option::STRING }
571 };
572
573 ...
574
575 OptionManager om;
576 om.registerOptions(options, sizeof(options) / sizeof(options[0]));
577 </pre>
578
579 Recall that static memory areas are initialized with zeros so that the
580 members that are not initialized explicitly in the example above are
581 initialized implicitly with zeros (which the OptionManager used to
582 determine that they are not used).
583
584 It is possible to specify domains as well. For example, suppose we
585 alagaraja 1.41 want to define a "color" option that can be in the following set:
586 {"red", "green", "blue"}. Here is how to express that:
587
588 <pre>
589 static const char* colors[] = { "red", "green", "blue" };
590 static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
591
592 static OptionRow options[] =
593 {
594 { "color", "red", false, Option::STRING, colors, NUM_COLORS }
595 };
596 </pre>
|
597 david.dillard 1.44 When a domain is defined, any of the keywords in that domain are legal
598 option keywords. For example. With the domain defined above, a command
599 line or config file entry that includes -c blue sets the option "color" to
600 blue. Note that this requires a space between -c and blue.
|
601 alagaraja 1.41 */
602 struct OptionRow
603 {
604 const char* optionName;
605 const char* defaultValue;
606 int required;
607 Option::Type type;
608 char** domain;
609 Uint32 domainSize;
610 const char* commandLineOptionName;
611 const char* optionHelpMessage;
612 };
|
613 david.dillard 1.44 /* NOTE: The "required" object must be an int rather than a Boolean because
614 bool on some platforms is not defined so that we cannot use a Boolean here
615 with a static object.
|
616 alagaraja 1.41 */
|
617 david.dillard 1.44
|
618 alagaraja 1.41 /** Exception class */
619 class OMMissingCommandLineOptionArgument : public Exception
620 {
621 public:
622
623 //l10n
624 //OMMissingCommandLineOptionArgument(const String& optionName)
625 //: Exception("Missing command line option argument: " + optionName) { }
626 OMMissingCommandLineOptionArgument(const String& optionName)
627 : Exception(MessageLoaderParms("Common.OptionManager.MISSING_CMD_LINE_OPTION",
628 "Missing command line option argument: $0",
629 optionName)) { }
630 };
631
632 /** Exception class */
633 class OMInvalidOptionValue : public Exception
634 {
635 public:
636
637 //l10n
638 //OMInvalidOptionValue(const String& name, const String& value)
639 alagaraja 1.41 //: Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
640 OMInvalidOptionValue(const String& name, const String& value)
641 : Exception(MessageLoaderParms("Common.OptionManager.INVALID_OPTION_VALUE",
642 "Invalid option value: $0=\"$1\"",
643 name,
644 value)) { }
645 };
646
647 /** Exception class */
648 class OMDuplicateOption : public Exception
649 {
650 public:
651 //l10n
652 //OMDuplicateOption(const String& name)
653 //: Exception("Duplicate option: " + name) { }
654 OMDuplicateOption(const String& name)
655 : Exception(MessageLoaderParms("Common.OptionManager.DUPLICATE_OPTION",
656 "Duplicate option: $0",
657 name)) { }
658 };
659
660 alagaraja 1.41 /** Exception class */
661 class OMConfigFileSyntaxError : public Exception
662 {
663 public:
664
665 OMConfigFileSyntaxError(const String& file, Uint32 line)
666 : Exception(_formatMessage(file, line)) { }
667
668 static String _formatMessage(const String& file, Uint32 line);
669 };
670
671 /** Exception class */
672 class OMUnrecognizedConfigFileOption : public Exception
673 {
674 public:
675 //l10n
676 //OMUnrecognizedConfigFileOption(const String& name)
677 //: Exception("Unrecognized config file option: " + name) { }
678 OMUnrecognizedConfigFileOption(const String& name)
679 : Exception(MessageLoaderParms("Common.OptionManager.UNRECOGNIZED_CONFIG_FILE_OPTION",
680 "Unrecognized config file option: $0",
681 alagaraja 1.41 name)) { }
682 };
683
684 /** Exception class */
685 class OMMissingRequiredOptionValue : public Exception
686 {
687 public:
688 //l10n
689 //OMMissingRequiredOptionValue(const String& name)
690 //: Exception("Missing required option value: " + name) { }
691 OMMissingRequiredOptionValue(const String& name)
692 : Exception(MessageLoaderParms("Common.OptionManager.MISSING_REQUIRED_OPTION",
693 "Missing required option value: $0",
694 name)) { }
695 };
696
697 /** Exception class */
698 class OMMBadCmdLineOption : public Exception
699 {
700 public:
701 //l10n
702 alagaraja 1.41 // OMMBadCmdLineOption(const String& name)
703 //: Exception("Parameter not Valid: " + name) { }
704 OMMBadCmdLineOption(const String& name)
705 : Exception(MessageLoaderParms("Common.OptionManager.PARAMETER_NOT_VALID",
706 "Parameter not Valid: $0",
707 name)) { }
708 };
709
710
711 PEGASUS_NAMESPACE_END
712
713 #endif /* Pegasus_OM_h */
|