View Javadoc
1   /*
2    * This file is part of dependency-check-cli.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.cli;
19  
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import org.apache.commons.cli.CommandLine;
23  import org.apache.commons.cli.CommandLineParser;
24  import org.apache.commons.cli.HelpFormatter;
25  import org.apache.commons.cli.Option;
26  import org.apache.commons.cli.OptionBuilder;
27  import org.apache.commons.cli.OptionGroup;
28  import org.apache.commons.cli.Options;
29  import org.apache.commons.cli.ParseException;
30  import org.apache.commons.cli.PosixParser;
31  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
32  import org.owasp.dependencycheck.utils.Settings;
33  
34  /**
35   * A utility to parse command line arguments for the DependencyCheck.
36   *
37   * @author Jeremy Long <jeremy.long@owasp.org>
38   */
39  public final class CliParser {
40  
41      /**
42       * The command line.
43       */
44      private CommandLine line;
45      /**
46       * Indicates whether the arguments are valid.
47       */
48      private boolean isValid = true;
49  
50      /**
51       * Parses the arguments passed in and captures the results for later use.
52       *
53       * @param args the command line arguments
54       * @throws FileNotFoundException is thrown when a 'file' argument does not point to a file that exists.
55       * @throws ParseException is thrown when a Parse Exception occurs.
56       */
57      public void parse(String[] args) throws FileNotFoundException, ParseException {
58          line = parseArgs(args);
59  
60          if (line != null) {
61              validateArgs();
62          }
63      }
64  
65      /**
66       * Parses the command line arguments.
67       *
68       * @param args the command line arguments
69       * @return the results of parsing the command line arguments
70       * @throws ParseException if the arguments are invalid
71       */
72      private CommandLine parseArgs(String[] args) throws ParseException {
73          final CommandLineParser parser = new PosixParser();
74          final Options options = createCommandLineOptions();
75          return parser.parse(options, args);
76      }
77  
78      /**
79       * Validates that the command line arguments are valid.
80       *
81       * @throws FileNotFoundException if there is a file specified by either the SCAN or CPE command line arguments that
82       * does not exist.
83       * @throws ParseException is thrown if there is an exception parsing the command line.
84       */
85      private void validateArgs() throws FileNotFoundException, ParseException {
86          if (isRunScan()) {
87              validatePathExists(getScanFiles(), "scan");
88              validatePathExists(getReportDirectory(), "out");
89              if (!line.hasOption(ArgumentName.APP_NAME)) {
90                  throw new ParseException("Missing 'app' argument; the scan cannot be run without the an application name.");
91              }
92              if (line.hasOption(ArgumentName.OUTPUT_FORMAT)) {
93                  final String format = line.getOptionValue(ArgumentName.OUTPUT_FORMAT);
94                  try {
95                      Format.valueOf(format);
96                  } catch (IllegalArgumentException ex) {
97                      final String msg = String.format("An invalid 'format' of '%s' was specified. "
98                              + "Supported output formats are XML, HTML, VULN, or ALL", format);
99                      throw new ParseException(msg);
100                 }
101             }
102         }
103     }
104 
105     /**
106      * Validates whether or not the path(s) points at a file that exists; if the path(s) does not point to an existing
107      * file a FileNotFoundException is thrown.
108      *
109      * @param paths the paths to validate if they exists
110      * @param optType the option being validated (e.g. scan, out, etc.)
111      * @throws FileNotFoundException is thrown if one of the paths being validated does not exist.
112      */
113     private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
114         for (String path : paths) {
115             validatePathExists(path, optType);
116         }
117     }
118 
119     /**
120      * Validates whether or not the path points at a file that exists; if the path does not point to an existing file a
121      * FileNotFoundException is thrown.
122      *
123      * @param path the paths to validate if they exists
124      * @param optType the option being validated (e.g. scan, out, etc.)
125      * @throws FileNotFoundException is thrown if the path being validated does not exist.
126      */
127     private void validatePathExists(String path, String optType) throws FileNotFoundException {
128         final File f = new File(path);
129         if (!f.exists()) {
130             isValid = false;
131             final String msg = String.format("Invalid '%s' argument: '%s'", optType, path);
132             throw new FileNotFoundException(msg);
133         }
134     }
135 
136     /**
137      * Generates an Options collection that is used to parse the command line and to display the help message.
138      *
139      * @return the command line options used for parsing the command line
140      */
141     @SuppressWarnings("static-access")
142     private Options createCommandLineOptions() {
143 
144         final Options options = new Options();
145         addStandardOptions(options);
146         addAdvancedOptions(options);
147 
148         return options;
149     }
150 
151     /**
152      * Adds the standard command line options to the given options collection.
153      *
154      * @param options a collection of command line arguments
155      * @throws IllegalArgumentException thrown if there is an exception
156      */
157     @SuppressWarnings("static-access")
158     private void addStandardOptions(final Options options) throws IllegalArgumentException {
159         final Option help = new Option(ArgumentName.HELP_SHORT, ArgumentName.HELP, false,
160                 "Print this message.");
161 
162         final Option advancedHelp = OptionBuilder.withLongOpt(ArgumentName.ADVANCED_HELP)
163                 .withDescription("Print the advanced help message.").create();
164 
165         final Option version = new Option(ArgumentName.VERSION_SHORT, ArgumentName.VERSION,
166                 false, "Print the version information.");
167 
168         final Option noUpdate = new Option(ArgumentName.DISABLE_AUTO_UPDATE_SHORT, ArgumentName.DISABLE_AUTO_UPDATE,
169                 false, "Disables the automatic updating of the CPE data.");
170 
171         final Option appName = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APP_NAME)
172                 .withDescription("The name of the application being scanned. This is a required argument.")
173                 .create(ArgumentName.APP_NAME_SHORT);
174 
175         final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN)
176                 .withDescription("The path to scan - this option can be specified multiple times.")
177                 .create(ArgumentName.SCAN_SHORT);
178 
179         final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP)
180                 .withDescription("A property file to load.")
181                 .create(ArgumentName.PROP_SHORT);
182 
183         final Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT)
184                 .withDescription("The folder to write reports to. This defaults to the current directory.")
185                 .create(ArgumentName.OUT_SHORT);
186 
187         final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ArgumentName.OUTPUT_FORMAT)
188                 .withDescription("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
189                 .create(ArgumentName.OUTPUT_FORMAT_SHORT);
190 
191         final Option verboseLog = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.VERBOSE_LOG)
192                 .withDescription("The file path to write verbose logging information.")
193                 .create(ArgumentName.VERBOSE_LOG_SHORT);
194 
195         final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.SUPPRESION_FILE)
196                 .withDescription("The file path to the suppression XML file.")
197                 .create();
198 
199         final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NEXUS)
200                 .withDescription("Disable the Nexus Analyzer.")
201                 .create();
202 
203         final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.NEXUS_URL)
204                 .withDescription("The url to the Nexus Server.")
205                 .create();
206 
207         //This is an option group because it can be specified more then once.
208         final OptionGroup og = new OptionGroup();
209         og.addOption(path);
210 
211         options.addOptionGroup(og)
212                 .addOption(out)
213                 .addOption(outputFormat)
214                 .addOption(appName)
215                 .addOption(version)
216                 .addOption(help)
217                 .addOption(advancedHelp)
218                 .addOption(noUpdate)
219                 .addOption(props)
220                 .addOption(verboseLog)
221                 .addOption(suppressionFile)
222                 .addOption(disableNexusAnalyzer)
223                 .addOption(nexusUrl);
224     }
225 
226     /**
227      * Adds the advanced command line options to the given options collection. These are split out for purposes of being
228      * able to display two different help messages.
229      *
230      * @param options a collection of command line arguments
231      * @throws IllegalArgumentException thrown if there is an exception
232      */
233     @SuppressWarnings("static-access")
234     private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
235 
236         final Option data = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.DATA_DIRECTORY)
237                 .withDescription("The location of the H2 Database file. This option should generally not be set.")
238                 .create(ArgumentName.DATA_DIRECTORY_SHORT);
239 
240         final Option connectionTimeout = OptionBuilder.withArgName("timeout").hasArg().withLongOpt(ArgumentName.CONNECTION_TIMEOUT)
241                 .withDescription("The connection timeout (in milliseconds) to use when downloading resources.")
242                 .create(ArgumentName.CONNECTION_TIMEOUT_SHORT);
243 
244         final Option proxyUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.PROXY_URL)
245                 .withDescription("The proxy url to use when downloading resources.")
246                 .create(ArgumentName.PROXY_URL_SHORT);
247 
248         final Option proxyPort = OptionBuilder.withArgName("port").hasArg().withLongOpt(ArgumentName.PROXY_PORT)
249                 .withDescription("The proxy port to use when downloading resources.")
250                 .create(ArgumentName.PROXY_PORT_SHORT);
251 
252         final Option proxyUsername = OptionBuilder.withArgName("user").hasArg().withLongOpt(ArgumentName.PROXY_USERNAME)
253                 .withDescription("The proxy username to use when downloading resources.")
254                 .create();
255 
256         final Option proxyPassword = OptionBuilder.withArgName("pass").hasArg().withLongOpt(ArgumentName.PROXY_PASSWORD)
257                 .withDescription("The proxy password to use when downloading resources.")
258                 .create();
259 
260         final Option connectionString = OptionBuilder.withArgName("connStr").hasArg().withLongOpt(ArgumentName.CONNECTION_STRING)
261                 .withDescription("The connection string to the database.")
262                 .create();
263         final Option dbUser = OptionBuilder.withArgName("user").hasArg().withLongOpt(ArgumentName.DB_NAME)
264                 .withDescription("The username used to connect to the database.")
265                 .create();
266         final Option dbPassword = OptionBuilder.withArgName("password").hasArg().withLongOpt(ArgumentName.DB_PASSWORD)
267                 .withDescription("The password for connecting to the database.")
268                 .create();
269         final Option dbDriver = OptionBuilder.withArgName("driver").hasArg().withLongOpt(ArgumentName.DB_DRIVER)
270                 .withDescription("The database driver name.")
271                 .create();
272         final Option dbDriverPath = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.DB_DRIVER_PATH)
273                 .withDescription("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
274                 .create();
275 
276         options.addOption(proxyPort)
277                 .addOption(proxyUrl)
278                 .addOption(proxyUsername)
279                 .addOption(proxyPassword)
280                 .addOption(connectionTimeout)
281                 .addOption(connectionString)
282                 .addOption(dbUser)
283                 .addOption(data)
284                 .addOption(dbPassword)
285                 .addOption(dbDriver)
286                 .addOption(dbDriverPath);
287     }
288 
289     /**
290      * Determines if the 'version' command line argument was passed in.
291      *
292      * @return whether or not the 'version' command line argument was passed in
293      */
294     public boolean isGetVersion() {
295         return (line != null) && line.hasOption(ArgumentName.VERSION);
296     }
297 
298     /**
299      * Determines if the 'help' command line argument was passed in.
300      *
301      * @return whether or not the 'help' command line argument was passed in
302      */
303     public boolean isGetHelp() {
304         return (line != null) && line.hasOption(ArgumentName.HELP);
305     }
306 
307     /**
308      * Determines if the 'scan' command line argument was passed in.
309      *
310      * @return whether or not the 'scan' command line argument was passed in
311      */
312     public boolean isRunScan() {
313         return (line != null) && isValid && line.hasOption(ArgumentName.SCAN);
314     }
315 
316     /**
317      * Returns true if the disableNexus command line argument was specified.
318      *
319      * @return true if the disableNexus command line argument was specified; otherwise false
320      */
321     public boolean isNexusDisabled() {
322         return (line != null) && line.hasOption(ArgumentName.DISABLE_NEXUS);
323     }
324 
325     /**
326      * Returns the url to the nexus server if one was specified.
327      *
328      * @return the url to the nexus server; if none was specified this will return null;
329      */
330     public String getNexusUrl() {
331         if (line == null || !line.hasOption(ArgumentName.NEXUS_URL)) {
332             return null;
333         } else {
334             return line.getOptionValue(ArgumentName.NEXUS_URL);
335         }
336     }
337 
338     /**
339      * Displays the command line help message to the standard output.
340      */
341     public void printHelp() {
342         final HelpFormatter formatter = new HelpFormatter();
343         final Options options = new Options();
344         addStandardOptions(options);
345         if (line != null && line.hasOption(ArgumentName.ADVANCED_HELP)) {
346             addAdvancedOptions(options);
347         }
348         final String helpMsg = String.format("%n%s"
349                 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
350                 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
351                 Settings.getString("application.name", "DependencyCheck"),
352                 Settings.getString("application.name", "DependencyCheck"));
353 
354         formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
355                 helpMsg,
356                 options,
357                 "",
358                 true);
359 
360     }
361 
362     /**
363      * Retrieves the file command line parameter(s) specified for the 'scan' argument.
364      *
365      * @return the file paths specified on the command line for scan
366      */
367     public String[] getScanFiles() {
368         return line.getOptionValues(ArgumentName.SCAN);
369     }
370 
371     /**
372      * Returns the directory to write the reports to specified on the command line.
373      *
374      * @return the path to the reports directory.
375      */
376     public String getReportDirectory() {
377         return line.getOptionValue(ArgumentName.OUT, ".");
378     }
379 
380     /**
381      * Returns the output format specified on the command line. Defaults to HTML if no format was specified.
382      *
383      * @return the output format name.
384      */
385     public String getReportFormat() {
386         return line.getOptionValue(ArgumentName.OUTPUT_FORMAT, "HTML");
387     }
388 
389     /**
390      * Returns the application name specified on the command line.
391      *
392      * @return the application name.
393      */
394     public String getApplicationName() {
395         return line.getOptionValue(ArgumentName.APP_NAME);
396     }
397 
398     /**
399      * Returns the connection timeout.
400      *
401      * @return the connection timeout
402      */
403     public String getConnectionTimeout() {
404         return line.getOptionValue(ArgumentName.CONNECTION_TIMEOUT);
405     }
406 
407     /**
408      * Returns the proxy url.
409      *
410      * @return the proxy url
411      */
412     public String getProxyUrl() {
413         return line.getOptionValue(ArgumentName.PROXY_URL);
414     }
415 
416     /**
417      * Returns the proxy port.
418      *
419      * @return the proxy port
420      */
421     public String getProxyPort() {
422         return line.getOptionValue(ArgumentName.PROXY_PORT);
423     }
424 
425     /**
426      * Returns the proxy username.
427      *
428      * @return the proxy username
429      */
430     public String getProxyUsername() {
431         return line.getOptionValue(ArgumentName.PROXY_USERNAME);
432     }
433 
434     /**
435      * Returns the proxy password.
436      *
437      * @return the proxy password
438      */
439     public String getProxyPassword() {
440         return line.getOptionValue(ArgumentName.PROXY_PASSWORD);
441     }
442 
443     /**
444      * Get the value of dataDirectory.
445      *
446      * @return the value of dataDirectory
447      */
448     public String getDataDirectory() {
449         return line.getOptionValue(ArgumentName.DATA_DIRECTORY);
450     }
451 
452     /**
453      * Returns the properties file specified on the command line.
454      *
455      * @return the properties file specified on the command line
456      */
457     public File getPropertiesFile() {
458         final String path = line.getOptionValue(ArgumentName.PROP);
459         if (path != null) {
460             return new File(path);
461         }
462         return null;
463     }
464 
465     /**
466      * Returns the path to the verbose log file.
467      *
468      * @return the path to the verbose log file
469      */
470     public String getVerboseLog() {
471         return line.getOptionValue(ArgumentName.VERBOSE_LOG);
472     }
473 
474     /**
475      * Returns the path to the suppression file.
476      *
477      * @return the path to the suppression file
478      */
479     public String getSuppressionFile() {
480         return line.getOptionValue(ArgumentName.SUPPRESION_FILE);
481     }
482 
483     /**
484      * <p>
485      * Prints the manifest information to standard output.</p>
486      * <ul><li>Implementation-Title: ${pom.name}</li>
487      * <li>Implementation-Version: ${pom.version}</li></ul>
488      */
489     public void printVersionInfo() {
490         final String version = String.format("%s version %s",
491                 Settings.getString("application.name", "DependencyCheck"),
492                 Settings.getString("application.version", "Unknown"));
493         System.out.println(version);
494     }
495 
496     /**
497      * Checks if the auto update feature has been disabled. If it has been disabled via the command line this will
498      * return false.
499      *
500      * @return if auto-update is allowed.
501      */
502     public boolean isAutoUpdate() {
503         return (line == null) || !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE);
504     }
505 
506     /**
507      * Returns the database driver name if specified; otherwise null is returned.
508      *
509      * @return the database driver name if specified; otherwise null is returned
510      */
511     public String getDatabaseDriverName() {
512         return line.getOptionValue(ArgumentName.DB_DRIVER);
513     }
514 
515     /**
516      * Returns the database driver path if specified; otherwise null is returned.
517      *
518      * @return the database driver name if specified; otherwise null is returned
519      */
520     public String getDatabaseDriverPath() {
521         return line.getOptionValue(ArgumentName.DB_DRIVER_PATH);
522     }
523 
524     /**
525      * Returns the database connection string if specified; otherwise null is returned.
526      *
527      * @return the database connection string if specified; otherwise null is returned
528      */
529     public String getConnectionString() {
530         return line.getOptionValue(ArgumentName.CONNECTION_STRING);
531     }
532 
533     /**
534      * Returns the database database user name if specified; otherwise null is returned.
535      *
536      * @return the database database user name if specified; otherwise null is returned
537      */
538     public String getDatabaseUser() {
539         return line.getOptionValue(ArgumentName.DB_NAME);
540     }
541 
542     /**
543      * Returns the database database password if specified; otherwise null is returned.
544      *
545      * @return the database database password if specified; otherwise null is returned
546      */
547     public String getDatabasePassword() {
548         return line.getOptionValue(ArgumentName.DB_PASSWORD);
549     }
550 
551     /**
552      * A collection of static final strings that represent the possible command line arguments.
553      */
554     public static class ArgumentName {
555 
556         /**
557          * The long CLI argument name specifying the directory/file to scan.
558          */
559         public static final String SCAN = "scan";
560         /**
561          * The short CLI argument name specifying the directory/file to scan.
562          */
563         public static final String SCAN_SHORT = "s";
564         /**
565          * The long CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
566          */
567         public static final String DISABLE_AUTO_UPDATE = "noupdate";
568         /**
569          * The short CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
570          */
571         public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
572         /**
573          * The long CLI argument name specifying the directory to write the reports to.
574          */
575         public static final String OUT = "out";
576         /**
577          * The short CLI argument name specifying the directory to write the reports to.
578          */
579         public static final String OUT_SHORT = "o";
580         /**
581          * The long CLI argument name specifying the output format to write the reports to.
582          */
583         public static final String OUTPUT_FORMAT = "format";
584         /**
585          * The short CLI argument name specifying the output format to write the reports to.
586          */
587         public static final String OUTPUT_FORMAT_SHORT = "f";
588         /**
589          * The long CLI argument name specifying the name of the application to be scanned.
590          */
591         public static final String APP_NAME = "app";
592         /**
593          * The short CLI argument name specifying the name of the application to be scanned.
594          */
595         public static final String APP_NAME_SHORT = "a";
596         /**
597          * The long CLI argument name asking for help.
598          */
599         public static final String HELP = "help";
600         /**
601          * The long CLI argument name asking for advanced help.
602          */
603         public static final String ADVANCED_HELP = "advancedHelp";
604         /**
605          * The short CLI argument name asking for help.
606          */
607         public static final String HELP_SHORT = "h";
608         /**
609          * The long CLI argument name asking for the version.
610          */
611         public static final String VERSION_SHORT = "v";
612         /**
613          * The short CLI argument name asking for the version.
614          */
615         public static final String VERSION = "version";
616         /**
617          * The short CLI argument name indicating the proxy port.
618          */
619         public static final String PROXY_PORT_SHORT = "p";
620         /**
621          * The CLI argument name indicating the proxy port.
622          */
623         public static final String PROXY_PORT = "proxyport";
624         /**
625          * The short CLI argument name indicating the proxy url.
626          */
627         public static final String PROXY_URL_SHORT = "u";
628         /**
629          * The CLI argument name indicating the proxy url.
630          */
631         public static final String PROXY_URL = "proxyurl";
632         /**
633          * The CLI argument name indicating the proxy username.
634          */
635         public static final String PROXY_USERNAME = "proxyuser";
636         /**
637          * The CLI argument name indicating the proxy password.
638          */
639         public static final String PROXY_PASSWORD = "proxypass";
640         /**
641          * The short CLI argument name indicating the connection timeout.
642          */
643         public static final String CONNECTION_TIMEOUT_SHORT = "c";
644         /**
645          * The CLI argument name indicating the connection timeout.
646          */
647         public static final String CONNECTION_TIMEOUT = "connectiontimeout";
648         /**
649          * The short CLI argument name for setting the location of an additional properties file.
650          */
651         public static final String PROP_SHORT = "p";
652         /**
653          * The CLI argument name for setting the location of an additional properties file.
654          */
655         public static final String PROP = "propertyfile";
656         /**
657          * The CLI argument name for setting the location of the data directory.
658          */
659         public static final String DATA_DIRECTORY = "data";
660         /**
661          * The short CLI argument name for setting the location of the data directory.
662          */
663         public static final String DATA_DIRECTORY_SHORT = "d";
664         /**
665          * The CLI argument name for setting the location of the data directory.
666          */
667         public static final String VERBOSE_LOG = "log";
668         /**
669          * The short CLI argument name for setting the location of the data directory.
670          */
671         public static final String VERBOSE_LOG_SHORT = "l";
672         /**
673          * The CLI argument name for setting the location of the suppression file.
674          */
675         public static final String SUPPRESION_FILE = "suppression";
676         /**
677          * Disables the Nexus Analyzer.
678          */
679         public static final String DISABLE_NEXUS = "disableNexus";
680         /**
681          * The URL of the nexus server.
682          */
683         public static final String NEXUS_URL = "nexus";
684         /**
685          * The CLI argument name for setting the connection string.
686          */
687         public static final String CONNECTION_STRING = "connectionString";
688         /**
689          * The CLI argument name for setting the database user name.
690          */
691         public static final String DB_NAME = "dbUser";
692         /**
693          * The CLI argument name for setting the database password.
694          */
695         public static final String DB_PASSWORD = "dbPassword";
696         /**
697          * The CLI argument name for setting the database driver name.
698          */
699         public static final String DB_DRIVER = "dbDriverName";
700         /**
701          * The CLI argument name for setting the path to the database driver; in case it is not on the class path.
702          */
703         public static final String DB_DRIVER_PATH = "dbDriverPath";
704     }
705 }