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