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 mike 1.10 // Modified By:
|
25 mike 1.9 //
|
26 mike 1.10 //%/////////////////////////////////////////////////////////////////////////////
|
27 mike 1.1
28 #ifndef Pegasus_OptionManager_h
29 #define Pegasus_OptionManager_h
30
31 #include <Pegasus/Common/Config.h>
32 #include <Pegasus/Common/String.h>
33 #include <Pegasus/Common/Array.h>
|
34 mike 1.4 #include <Pegasus/Common/Exception.h>
|
35 mike 1.1
36 PEGASUS_NAMESPACE_BEGIN
37
38 class Option;
|
39 mike 1.5 struct OptionRow;
|
40 mike 1.1
|
41 mike 1.14 PEGASUS_MEMORY_FUNCTIONS(Option*)
42
|
43 mike 1.15 typedef Option* OptionPtr;
44 #define PEGASUS_ARRAY_T OptionPtr
45 # include "ArrayInter.h"
46 #undef PEGASUS_ARRAY_T
47
|
48 karl 1.12 /** The OptionManager class manages a collection of program options.
|
49 mike 1.1
50 <h4>Overview</h4>
51
|
52 mike 1.9 A program option may be specified in two ways:
|
53 mike 1.1
54 <ul>
55 <li>In a configuration file</li>
56 <li>On the command line</li>
57 </ul>
58
|
59 karl 1.12 This class provides methods for merging options from both of these
60 sources into a single collection. The following example shows how to
|
61 mike 1.9 merge options from a command line into the option manager.
|
62 mike 1.1
63 <pre>
64 int main(int argc, char** argv)
65 {
66 OptionManager om;
67
68 ...
69
70 // Merge options from the command line into the option manager's
71 // option list. Remove arguments from command line.
72
73 om.mergeCommandLine(argc, argv);
74
75 ...
76 }
77 </pre>
78
|
79 mike 1.9 Similarly, the OptionManager::mergeFile() method allows options to be
80 merged from a file.
|
81 mike 1.1
82 Before options are merged into the option manager, information on each
83 option must be registered with the option manager so that the following
84 can be resolved:
85
86 <ul>
87 <li>The option's name</li>
88 <li>The default value (to be used if not specified elsewhere)</li>
89 <li>Whether the option is required</li>
|
90 mike 1.2 <li>The option's type (e.g., boolean, integer or string)</li>
|
91 mike 1.1 <li>The domain of the option if any (set of legal values)</li>
92 <li>The name the option as it appears on the command line</li>
93 </ul>
94
95 Here is how to regsiter an option:
96
97 <pre>
98 OptionManager om;
99
|
100 karl 1.12 Option* option = new Option("port", "80", false,
|
101 mike 1.9 Option::NATURAL_NUMBER, Array<String>(), "p");
|
102 mike 1.1
103 om.registerOption(option);
104 </pre>
105
106 The arguments of the Option constructor are the same (and in the same
|
107 mike 1.9 order) as the list just above. Notice the last argument is "p". This
108 is the name of the option argument on the command line (it would appear
109 as "-p" on the command line).
110
|
111 karl 1.12 Once options have been registered, the option values may be initialized
112 using the merge methods described earlier. During merging, certain
|
113 mike 1.9 validation is done using the corresponding Option instance described above.
|
114 mike 1.1
|
115 karl 1.12 Once options have been merged, they may obtained by calling the
|
116 mike 1.1 lookupOption() method like this:
|
117 karl 1.12
|
118 mike 1.1 <pre>
119 Option* option = om.lookupOption("port");
|
120 mike 1.9 String port = option->getValue();
121 </pre>
|
122 mike 1.1
|
123 mike 1.9 Or the lookupValue() convenience function may be used to lookup values:
124
125 <pre>
126 String value;
127 om.lookupValue("port", value);
|
128 mike 1.1 </pre>
129
130 <h4>Command Line Options</h4>
131
132 mergeCommandLine() like this:
133
134 <pre>
135 om.mergeCommandLine(argc, argv);
136 </pre>
|
137 karl 1.12
138 This method searches the command line for options that match the registered
139 ones. It will extract those options from the command line (argc and argv
|
140 mike 1.1 will be modified accordingly).
141
142 <h4>Configuration File Otpions</h4>
143
|
144 karl 1.12 Options from a configuration file may be merged by calling the mergeFile()
|
145 mike 1.1 method like this:
146
147 <pre>
148 om.mergeFile(fileName);
149 </pre>
150
151 This searches the file for options matching registered ones. Exceptions
152 are thrown for any unrecognized option names that are encountered.
153
154 <h4>Merge Validation</h4>
155
|
156 karl 1.12 During merging, the option manager validates the following (using the
|
157 mike 1.1 information optatined during option registration).
158
159 <ul>
160 <li>The type of the option - whether integer, positive integer,
|
161 mike 1.9 or string or whatever.</li>
|
162 mike 1.1 <li>The domain of the option - whether the supplied option is a legal
163 value for that otpion</li>
|
164 karl 1.12 <li>User extended validation - whether the user overriden
|
165 mike 1.1 Option::isValid() returns true when the value is passed to it</li>
166 </ul>
|
167 mike 1.2
168 <h4>Typcial Usage</h4>
169
170 The OptionManager is typically used in the following way. First, options
171 are registered to establish the valid set of options. Next, values are
172 merged from the various sources by calling the merge functions. Finally,
173 checkRequiredOptions() is called to see if any required option values were
174 not provided.
|
175 mike 1.1 */
|
176 mike 1.2 class PEGASUS_COMMON_LINKAGE OptionManager
|
177 mike 1.1 {
178 public:
179
180 /** Constructor. */
181 OptionManager();
182
183 /** Destructor. Deletes all contained Options. */
184 ~OptionManager();
185
186 /** Registers an option. The OptionManager is responsible for disposing
187 of the option; the caller must not delete this object.
188
|
189 mike 1.8 @param option option to be registerd.
|
190 mike 1.7 @exception NullPointer exception if option argument is null.
191 @exception DuplicateOption if option already defined.
|
192 mike 1.5 */
193 void registerOption(Option* option);
194
195 /** Provides a simple way to register several options at once using
196 a declartive style table. This may also be done programmitically
197 by repeatedly calling registerOption above. See documentation for
198 OptionRow for details on how to use them.
|
199 mike 1.1 */
|
200 mike 1.5 void registerOptions(OptionRow* options, Uint32 numOptions);
|
201 mike 1.1
|
202 karl 1.12 /** Merge option values from the command line. Searches the command
|
203 mike 1.1 line for registered options whose names are given by the
204 Option::getCommandLineOptionName() method. Validation is performed
205 on each option value obtained by calling Option::isValid(). Valid
206 option values are set by calling Option::setValue(). The argc and
|
207 karl 1.12 argv arguments are modified: the option and its argument are
|
208 mike 1.1 stripped from the command line. The option and its argument have the
209 following form: -option-name argument. A space must be supplied
210 between the two. Boolean option arguments are an exception. They
211 must have the form -option. If they are present, then they are
212 taken to be true.
213
|
214 mike 1.8 ¶m argc number of argument on the command line.
215 ¶m argv list of command line arguments.
|
216 mike 1.7 &exception InvalidOptionValue if validation fails.
217 &exception MissingCommandLineOptionArgument
|
218 mike 1.1 */
219 void mergeCommandLine(int& argc, char**& argv);
220
221 /** Merge option values from a file. Searches file for registered options
|
222 mike 1.9 whose names are given by the options which have been registered.
|
223 karl 1.12 Validation is performed on each option value by calling
224 Option::isValid(). Valid option values are set by calling
|
225 mike 1.1 Option::setValue().
226
|
227 mike 1.8 ¶m fileName name of file to be merged.
|
228 mike 1.7 &exception NoSuchFile if file cannot be opened.
229 &exception BadConfigFileOption
|
230 mike 1.1 */
231 void mergeFile(const String& fileName);
232
233 /** After merging, this method is called to check for required options
234 that were not merged (specified).
235
|
236 mike 1.9 &exception MissingRequiredRequiredOption
|
237 mike 1.1 */
238 void checkRequiredOptions() const;
239
|
240 mike 1.2 /** Lookup the option with the given name.
|
241 karl 1.12 @param Name provides the name of the option.
|
242 mike 1.4 @return 0 if no such option.
|
243 mike 1.2 */
|
244 mike 1.4 const Option* lookupOption(const String& name) const;
|
245 mike 1.3
|
246 mike 1.6 /** Lookup value of an option.
|
247 karl 1.12 @param Name provides the name of the option (ex. "port")
248 @param String parameter contains the String that contains the
|
249 karl 1.11 value for this parameter (in String format).
|
250 karl 1.12 @return Boolean return. True if the option found.
|
251 mike 1.6 */
252 Boolean lookupValue(const String& name, String& value) const;
253
|
254 karl 1.16 /** optionValueEquals - Test the string value of an option.
255 @param name provides the name of the option (ex. "port")
256 @param value String value for comparison.
257 @return true if the option exists and the value of the option
258 equals the input parameter value.
259 */
260 Boolean valueEquals(const String& name, const String& value) const;
261
262
|
263 mike 1.3 /** Print all the options. */
264 void print() const;
|
265 karl 1.16
|
266 mike 1.2
|
267 mike 1.1 private:
268
|
269 mike 1.4 /** Lookup the option by its commandLineOptionName.
270 @return 0 if no such option.
271 */
272 Option* _lookupOptionByCommandLineOptionName(const String& name);
273
|
274 mike 1.1 Array<Option*> _options;
275 };
276
277 /** The Option class is used to specify information about an Option.
278
279 See the OptionManager class for more details.
280 */
|
281 mike 1.2 class PEGASUS_COMMON_LINKAGE Option
|
282 mike 1.1 {
283 public:
284
285 /** Valid value types. */
|
286 karl 1.12 enum Type
|
287 mike 1.5 {
288 // (..., -3, -2, -1, 0, 1, 2, 3, ...)
|
289 karl 1.12 INTEGER,
|
290 mike 1.5
291 // (1, 2, 3, ...)
|
292 karl 1.12 NATURAL_NUMBER,
|
293 mike 1.5
294 // (0, 1, 2, 3, ...)
|
295 karl 1.12 WHOLE_NUMBER,
|
296 mike 1.5
297 // "true" or "false"
|
298 karl 1.12 BOOLEAN,
|
299 mike 1.5
300 // Anything
301 STRING
302 };
|
303 mike 1.1
304 /** Constructor.
305
|
306 mike 1.8 @param optionName the name of this option.
|
307 mike 1.1
|
308 mike 1.8 @param defaultValue the default value of this option.
|
309 mike 1.1
|
310 mike 1.8 @param required whether the value of this option is required.
|
311 mike 1.1
|
312 mike 1.8 @param type type of the value. This is used to validate the value.
|
313 mike 1.1
|
314 mike 1.8 @param domain list of legal value for this option. If this list
|
315 mike 1.1 is empty, then no domain is enforced.
316
|
317 mike 1.8 @param commandLineOptionName name of the corresponding command line
|
318 mike 1.1 option (which may be different from the option name).
319 */
320 Option(
321 const String& optionName,
322 const String& defaultValue,
323 Boolean required,
324 Type type,
|
325 mike 1.13 const Array<String>& domain = EmptyStringArray(),
|
326 mike 1.2 const String& commandLineOptionName = String());
327
328 Option(const Option& x);
|
329 mike 1.1
330 virtual ~Option();
331
|
332 mike 1.2 Option& operator=(const Option& x);
|
333 mike 1.1
334 /** Accessor */
335 const String& getOptionName() const
336 {
337 return _optionName;
338 }
339
340 /** Modifier */
341 void setOptionName(const String& optionName)
342 {
343 _optionName = optionName;
344 }
345
346 /** Accessor */
347 const String& getDefaultValue() const
348 {
349 return _defaultValue;
350 }
351
352 /** Modifier. */
353 void setDefaultValue(const String& defaultValue)
354 mike 1.1 {
355 _defaultValue = defaultValue;
356 }
357
|
358 karl 1.12 /** Accessor
|
359 karl 1.11 @return - Returns string representation of value
360 */
|
361 mike 1.1 const String& getValue() const
362 {
363 return _value;
364 }
365
366 /** Modifier */
367 void setValue(const String& value)
368 {
369 _value = value;
|
370 mike 1.9 _resolved = true;
|
371 mike 1.1 }
372
373 /** Accessor */
374 Boolean getRequired() const
375 {
376 return _required;
377 }
378
379 /** Modifier */
380 void setRequired(Boolean required)
381 {
382 _required = required;
383 }
384
385 /** Accessor */
386 Type getType() const
387 {
388 return _type;
389 }
390
391 /** Modifier */
392 mike 1.1 void setType(Type type)
393 {
394 _type = type;
395 }
396
397 /** Accessor */
|
398 mike 1.13 const Array<String>& getDomain() const;
|
399 mike 1.1
400 /** Modifier */
|
401 mike 1.13 void setDomain(const Array<String>& domain);
|
402 mike 1.1
403 /** Accessor */
404 const String& getCommandLineOptionName() const
405 {
406 return _commandLineOptionName;
407 }
408
409 /** Modifier */
410 void setCommandLineOptionName(const String& commandLineOptionName)
411 {
412 _commandLineOptionName = commandLineOptionName;
413 }
414
|
415 karl 1.12 /** Accesor. Returns true if an option value was ever obtained for
|
416 mike 1.1 this option.
417 */
|
418 karl 1.12 Boolean isResolved() const
|
419 mike 1.9 {
|
420 karl 1.12 return _resolved;
|
421 mike 1.1 }
422
423 /** Checks to see if the given value is valid or not. This method may be
424 overriden by derived classes to do special purpose validation of the
425 value. This implementation just checks the domain and type.
426 */
427 virtual Boolean isValid(const String& value) const;
428
429 private:
430 String _optionName;
431 String _defaultValue;
432 String _value;
433 Boolean _required;
434 Type _type;
|
435 mike 1.13 Array<String> _domain;
|
436 mike 1.1 String _commandLineOptionName;
|
437 mike 1.9 Boolean _resolved;
|
438 mike 1.4 };
439
|
440 mike 1.5 /** The OptionRow provides a declarative way of defining Option objects.
441 For the declarative programming enthusiast, we provide this structure.
442 It provides a declarative way of defining options for the OptionManager
443 class. Some developers prefer this since it makes all the options visible
444 in a kind of table like structure. Here is an example of how it can be
445 used to define a port number and hostname options. We also show how to
446 register one of these option lists with an OptionManager.
447
448 <pre>
449 static OptionRow options[] =
450 {
451 { "port", "80", false, Option::NATURAL_NUMBER },
452 { "hostname", "", true, Option::STRING }
453 };
454
455 ...
456
457 OptionManager om;
458 om.registerOptions(options, sizeof(options) / sizeof(options[0]));
459 </pre>
460
461 mike 1.5 Recall that static memory areas are initialized with zeros so that the
462 members that are not initialized explicitly in the example above are
463 initialized implicitly with zeros (which the OptionManager used to
464 determine that they are not used).
465
466 It is possible to specify domains as well. For example, suppose we
467 want to define a "color" option that can be in the following set:
468 {"red", "green", "blue"}. Here is how to express that:
469
470 <pre>
471 static const char* colors[] = { "red", "green", "blue" };
|
472 mike 1.9 static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
|
473 mike 1.5
|
474 karl 1.12 static OptionRow options[] =
|
475 mike 1.5 {
|
476 mike 1.9 { "color", "red", false, Option::STRING, colors, NUM_COLORS }
|
477 mike 1.5 };
478 </pre>
479 */
480 struct OptionRow
481 {
482 const char* optionName;
483 const char* defaultValue;
|
484 mike 1.14 int required;
|
485 mike 1.5 Option::Type type;
486 char** domain;
487 Uint32 domainSize;
488 const char* commandLineOptionName;
489 };
490
491 /** Exception class */
|
492 mike 1.4 class MissingCommandLineOptionArgument : public Exception
493 {
494 public:
495
496 MissingCommandLineOptionArgument(const String& optionName)
497 : Exception("Missing command line option argument: " + optionName) { }
498 };
499
|
500 mike 1.5 /** Exception class */
501 class InvalidOptionValue : public Exception
502 {
503 public:
504
505 InvalidOptionValue(const String& name, const String& value)
506 : Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
507 };
508
509 /** Exception class */
510 class DuplicateOption : public Exception
|
511 mike 1.4 {
512 public:
513
|
514 mike 1.5 DuplicateOption(const String& name)
515 : Exception("Duplicate option: " + name) { }
|
516 mike 1.6 };
517
518 /** Exception class */
519 class ConfigFileSyntaxError : public Exception
520 {
521 public:
522
523 ConfigFileSyntaxError(const String& file, Uint32 line)
524 : Exception(_formatMessage(file, line)) { }
525
526 static String _formatMessage(const String& file, Uint32 line);
527 };
528
529 /** Exception class */
530 class UnrecognizedConfigFileOption : public Exception
531 {
532 public:
533
534 UnrecognizedConfigFileOption(const String& name)
535 : Exception("Unrecognized config file option: " + name) { }
|
536 mike 1.9 };
537
538 /** Exception class */
539 class MissingRequiredOptionValue : public Exception
540 {
541 public:
542
543 MissingRequiredOptionValue(const String& name)
544 : Exception("Missing required option value: " + name) { }
|
545 mike 1.1 };
546
547 PEGASUS_NAMESPACE_END
548
549 #endif /* Pegasus_OptionManager_h */
|