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 mike 1.3 /** Print all the options. */
255 void print() const;
|
256 mike 1.2
|
257 mike 1.1 private:
258
|
259 mike 1.4 /** Lookup the option by its commandLineOptionName.
260 @return 0 if no such option.
261 */
262 Option* _lookupOptionByCommandLineOptionName(const String& name);
263
|
264 mike 1.1 Array<Option*> _options;
265 };
266
267 /** The Option class is used to specify information about an Option.
268
269 See the OptionManager class for more details.
270 */
|
271 mike 1.2 class PEGASUS_COMMON_LINKAGE Option
|
272 mike 1.1 {
273 public:
274
275 /** Valid value types. */
|
276 karl 1.12 enum Type
|
277 mike 1.5 {
278 // (..., -3, -2, -1, 0, 1, 2, 3, ...)
|
279 karl 1.12 INTEGER,
|
280 mike 1.5
281 // (1, 2, 3, ...)
|
282 karl 1.12 NATURAL_NUMBER,
|
283 mike 1.5
284 // (0, 1, 2, 3, ...)
|
285 karl 1.12 WHOLE_NUMBER,
|
286 mike 1.5
287 // "true" or "false"
|
288 karl 1.12 BOOLEAN,
|
289 mike 1.5
290 // Anything
291 STRING
292 };
|
293 mike 1.1
294 /** Constructor.
295
|
296 mike 1.8 @param optionName the name of this option.
|
297 mike 1.1
|
298 mike 1.8 @param defaultValue the default value of this option.
|
299 mike 1.1
|
300 mike 1.8 @param required whether the value of this option is required.
|
301 mike 1.1
|
302 mike 1.8 @param type type of the value. This is used to validate the value.
|
303 mike 1.1
|
304 mike 1.8 @param domain list of legal value for this option. If this list
|
305 mike 1.1 is empty, then no domain is enforced.
306
|
307 mike 1.8 @param commandLineOptionName name of the corresponding command line
|
308 mike 1.1 option (which may be different from the option name).
309 */
310 Option(
311 const String& optionName,
312 const String& defaultValue,
313 Boolean required,
314 Type type,
|
315 mike 1.13 const Array<String>& domain = EmptyStringArray(),
|
316 mike 1.2 const String& commandLineOptionName = String());
317
318 Option(const Option& x);
|
319 mike 1.1
320 virtual ~Option();
321
|
322 mike 1.2 Option& operator=(const Option& x);
|
323 mike 1.1
324 /** Accessor */
325 const String& getOptionName() const
326 {
327 return _optionName;
328 }
329
330 /** Modifier */
331 void setOptionName(const String& optionName)
332 {
333 _optionName = optionName;
334 }
335
336 /** Accessor */
337 const String& getDefaultValue() const
338 {
339 return _defaultValue;
340 }
341
342 /** Modifier. */
343 void setDefaultValue(const String& defaultValue)
344 mike 1.1 {
345 _defaultValue = defaultValue;
346 }
347
|
348 karl 1.12 /** Accessor
|
349 karl 1.11 @return - Returns string representation of value
350 */
|
351 mike 1.1 const String& getValue() const
352 {
353 return _value;
354 }
355
356 /** Modifier */
357 void setValue(const String& value)
358 {
359 _value = value;
|
360 mike 1.9 _resolved = true;
|
361 mike 1.1 }
362
363 /** Accessor */
364 Boolean getRequired() const
365 {
366 return _required;
367 }
368
369 /** Modifier */
370 void setRequired(Boolean required)
371 {
372 _required = required;
373 }
374
375 /** Accessor */
376 Type getType() const
377 {
378 return _type;
379 }
380
381 /** Modifier */
382 mike 1.1 void setType(Type type)
383 {
384 _type = type;
385 }
386
387 /** Accessor */
|
388 mike 1.13 const Array<String>& getDomain() const;
|
389 mike 1.1
390 /** Modifier */
|
391 mike 1.13 void setDomain(const Array<String>& domain);
|
392 mike 1.1
393 /** Accessor */
394 const String& getCommandLineOptionName() const
395 {
396 return _commandLineOptionName;
397 }
398
399 /** Modifier */
400 void setCommandLineOptionName(const String& commandLineOptionName)
401 {
402 _commandLineOptionName = commandLineOptionName;
403 }
404
|
405 karl 1.12 /** Accesor. Returns true if an option value was ever obtained for
|
406 mike 1.1 this option.
407 */
|
408 karl 1.12 Boolean isResolved() const
|
409 mike 1.9 {
|
410 karl 1.12 return _resolved;
|
411 mike 1.1 }
412
413 /** Checks to see if the given value is valid or not. This method may be
414 overriden by derived classes to do special purpose validation of the
415 value. This implementation just checks the domain and type.
416 */
417 virtual Boolean isValid(const String& value) const;
418
419 private:
420 String _optionName;
421 String _defaultValue;
422 String _value;
423 Boolean _required;
424 Type _type;
|
425 mike 1.13 Array<String> _domain;
|
426 mike 1.1 String _commandLineOptionName;
|
427 mike 1.9 Boolean _resolved;
|
428 mike 1.4 };
429
|
430 mike 1.5 /** The OptionRow provides a declarative way of defining Option objects.
431 For the declarative programming enthusiast, we provide this structure.
432 It provides a declarative way of defining options for the OptionManager
433 class. Some developers prefer this since it makes all the options visible
434 in a kind of table like structure. Here is an example of how it can be
435 used to define a port number and hostname options. We also show how to
436 register one of these option lists with an OptionManager.
437
438 <pre>
439 static OptionRow options[] =
440 {
441 { "port", "80", false, Option::NATURAL_NUMBER },
442 { "hostname", "", true, Option::STRING }
443 };
444
445 ...
446
447 OptionManager om;
448 om.registerOptions(options, sizeof(options) / sizeof(options[0]));
449 </pre>
450
451 mike 1.5 Recall that static memory areas are initialized with zeros so that the
452 members that are not initialized explicitly in the example above are
453 initialized implicitly with zeros (which the OptionManager used to
454 determine that they are not used).
455
456 It is possible to specify domains as well. For example, suppose we
457 want to define a "color" option that can be in the following set:
458 {"red", "green", "blue"}. Here is how to express that:
459
460 <pre>
461 static const char* colors[] = { "red", "green", "blue" };
|
462 mike 1.9 static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
|
463 mike 1.5
|
464 karl 1.12 static OptionRow options[] =
|
465 mike 1.5 {
|
466 mike 1.9 { "color", "red", false, Option::STRING, colors, NUM_COLORS }
|
467 mike 1.5 };
468 </pre>
469 */
470 struct OptionRow
471 {
472 const char* optionName;
473 const char* defaultValue;
|
474 mike 1.14 int required;
|
475 mike 1.5 Option::Type type;
476 char** domain;
477 Uint32 domainSize;
478 const char* commandLineOptionName;
479 };
480
481 /** Exception class */
|
482 mike 1.4 class MissingCommandLineOptionArgument : public Exception
483 {
484 public:
485
486 MissingCommandLineOptionArgument(const String& optionName)
487 : Exception("Missing command line option argument: " + optionName) { }
488 };
489
|
490 mike 1.5 /** Exception class */
491 class InvalidOptionValue : public Exception
492 {
493 public:
494
495 InvalidOptionValue(const String& name, const String& value)
496 : Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
497 };
498
499 /** Exception class */
500 class DuplicateOption : public Exception
|
501 mike 1.4 {
502 public:
503
|
504 mike 1.5 DuplicateOption(const String& name)
505 : Exception("Duplicate option: " + name) { }
|
506 mike 1.6 };
507
508 /** Exception class */
509 class ConfigFileSyntaxError : public Exception
510 {
511 public:
512
513 ConfigFileSyntaxError(const String& file, Uint32 line)
514 : Exception(_formatMessage(file, line)) { }
515
516 static String _formatMessage(const String& file, Uint32 line);
517 };
518
519 /** Exception class */
520 class UnrecognizedConfigFileOption : public Exception
521 {
522 public:
523
524 UnrecognizedConfigFileOption(const String& name)
525 : Exception("Unrecognized config file option: " + name) { }
|
526 mike 1.9 };
527
528 /** Exception class */
529 class MissingRequiredOptionValue : public Exception
530 {
531 public:
532
533 MissingRequiredOptionValue(const String& name)
534 : Exception("Missing required option value: " + name) { }
|
535 mike 1.1 };
536
537 PEGASUS_NAMESPACE_END
538
539 #endif /* Pegasus_OptionManager_h */
|