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